वास्तविक दुनिया के एप्लिकेशन परिदृश्य में, बैकएंड सर्वर पर बड़ी मात्रा में प्रसंस्करण किया जाता है जहां डेटा को वास्तव में संसाधित किया जाता है और एक भंडार में रखा जाता है। स्प्रिंग की कई प्रमुख विशेषताओं के अलावा, जैसे DI (डिपेंडेंसी इंजेक्शन), एस्पेक्ट्स, और पीओजेओ-ओरिएंटेड डेवलपमेंट, स्प्रिंग को डेटा हैंडलिंग के लिए उत्कृष्ट समर्थन है। अच्छे डेटाबेस एप्लिकेशन लिखने के विभिन्न तरीके हैं। आज भी, JDBC डेटा एक्सेस क्षमता के आधार पर बड़ी संख्या में एप्लिकेशन लिखे जाते हैं। यह लेख विशेष रूप से वसंत के संबंध में JDBC से संबंधित है, इसके समर्थन, और पेशेवरों और विपक्षों के साथ उपयुक्त उदाहरण और कोड स्निपेट।
JDBC अवलोकन
ORM की दुनिया में अभी भी JDBC का उपयोग करने का एक सबसे बड़ा लाभ यह है कि इसे बहुत निचले स्तर पर डेटा के साथ काम करने के अलावा किसी अन्य फ्रेमवर्क की क्वेरी भाषा में महारत हासिल करने की आवश्यकता नहीं है। यह एक प्रोग्रामर को डेटाबेस की मालिकाना सुविधाओं का लाभ उठाने में सक्षम बनाता है। इसके नुकसान भी हैं। दुर्भाग्य से, नुकसान अक्सर इतने दृश्यमान होते हैं कि उन्हें उल्लेख की आवश्यकता नहीं होती है। उदाहरण के लिए, उनमें से एक है बॉयलरप्लेट कोड . शब्द बॉयलरप्लेट कोड मूल रूप से एक ही कोड को कोड में किसी भी मूल्य को शामिल किए बिना बार-बार लिखना है। यह आमतौर पर तब देखा जा सकता है जब हम किसी डेटाबेस से डेटा को क्वेरी करते हैं; उदाहरण के लिए, निम्नलिखित कोड में, हम केवल एक उपयोगकर्ता प्राप्त करते हैं डेटाबेस से रिकॉर्ड करें।
public User getUserById(long id) { User user = null; Connection con = null; PreparedStatement pstmt = null; ResultSet rs = null; try { con = dataSource.getConnection(); pstmt = con.prepareStatement("select * from " + "user_table where userid=?"); pstmt.setInt(1, id); rs.pstmt.executeQuery(); if (rs.next()) { user = new User(); user.setId(rs.getInt("userid")); user.setFullName(rs.getString("fullname")); user.setUserType(rs.getString("usertype")); user.setPassword(rs.getString("password")); } } catch (SQLException ex1) {} finally { try { if (rs != null) rs.close(); if (pstmt != null) rs.close(); if (con != null) rs.close(); } catch (SQLException ex2) {} } return user; }
ध्यान दें कि, हर बार जब हमें डेटाबेस के साथ बातचीत करने की आवश्यकता होती है, तो हमें तीन ऑब्जेक्ट बनाने चाहिए—एक कनेक्शन (कनेक्शन ), स्टेटमेंट (तैयार स्टेटमेंट ), और परिणामसेट (परिणामसेट ) इन सभी को भी लगाए गए कोशिश करें...पकड़ें . के भीतर संलग्न करना होगा खंड मैथा। यहां तक कि कनेक्शन के बंद होने को भी कोशिश करें…पकड़ें . के भीतर संलग्न करना होगा . यह हास्यास्पद है क्योंकि फ़ंक्शन के लिए वास्तविक आवश्यक कोड बहुत कम है। कोड केवल अनावश्यक लेकिन अनिवार्य कोड से भरा होता है और जहां भी हम डेटाबेस के साथ बातचीत करते हैं, उसे दोहराया जाना चाहिए। एक चतुर कोडिंग योजना इस गड़बड़ी को कम कर सकती है, फिर भी बॉयलरप्लेट JDBC कोड की समस्या को मिटाना असंभव है। यह न केवल JDBC बल्कि JMS, JNDI और REST की भी समस्या है।
वसंत का समाधान
स्प्रिंग फ्रेमवर्क ने इस गड़बड़ी का समाधान प्रदान किया और टेम्पलेट कक्षाओं का उपयोग करके बॉयलरप्लेट कोड को खत्म करने का एक साधन प्रदान किया। ये कक्षाएं बॉयलरप्लेट कोड को इनकैप्सुलेट करती हैं, जिससे प्रोग्रामर को राहत मिलती है। इसका मतलब यह है कि बॉयलरप्लेट कोड अभी भी है, केवल प्रोग्रामर जो टेम्पलेट कक्षाओं में से किसी एक का उपयोग करता है उसे लिखने की परेशानी से मुक्त किया जाता है। JdbcTemplate स्प्रिंग द्वारा प्रदान किया गया JDBC कोर पैकेज का केंद्रीय वर्ग है।
यह JDBC के उपयोग को सरल करता है और सामान्य त्रुटियों से बचने में मदद करता है। यह SQL प्रदान करने और परिणाम निकालने के लिए एप्लिकेशन कोड छोड़कर कोर JDBC वर्कफ़्लो निष्पादित करता है। यह वर्ग SQL प्रश्नों या अद्यतनों को निष्पादित करता है, ResultSets पर पुनरावृत्ति शुरू करता है और JDBC अपवादों को पकड़ता है और उन्हें org.springframework.dao में परिभाषित सामान्य, अधिक जानकारीपूर्ण अपवाद पदानुक्रम में अनुवादित करता है। पैकेज।
हमें केवल कॉल-बैक इंटरफेस को लागू करने और उन्हें एक स्पष्ट, परिभाषित अनुबंध देने की आवश्यकता है। उदाहरण के लिए, PreparedStatementCreator कॉलबैक इंटरफ़ेस का उपयोग तैयार कथन बनाने के लिए किया जाता है। ResultsetExtractor इंटरफ़ेस एक परिणामसेट . की तरह कार्य करता है ।
इसलिए, पिछले कोड स्निपेट को JdbcTemplate . के साथ फिर से लिखा जा सकता है इस प्रकार है:
@Autowired private JdbcTemplate jdbcTemplate; public User getUserById(long id) { return jdbcTemplate.queryForObject( "select * from user_table where userid=?", new UserRowMapper(),id); } class UserRowMapper implements RowMapper<User>{ @Override public User mapRow(ResultSet rs, int runNumber) throws SQLException { User user=new User(); user.setId(rs.getInt("userid")); user.setFullName(rs.getString("fullname")); user.setUserType(rs.getString("usertype")); user.setPassword(rs.getString("password")); return user; } }
रोमैपर आमतौर पर JdbcTemplate . द्वारा उपयोग किया जाने वाला इंटरफ़ेस है ResultSet . की पंक्तियों के आधार पर प्रति पंक्ति एक पंक्ति को मैप करने के लिए . रोमैपर वस्तुएं स्टेटलेस हैं और इसलिए पुन:प्रयोज्य हैं। वे किसी भी पंक्ति मानचित्रण तर्क को लागू करने के लिए एकदम सही हैं। ध्यान दें कि, पिछले कोड में, हमने अपवादों को स्पष्ट रूप से नहीं संभाला था जैसा कि हमने उस कोड में किया है जो JdbcTemplate का उपयोग नहीं करता है। . RowMapper कार्यान्वयन प्रोग्रामर को अपवाद से निपटने के बारे में चिंता करने की आवश्यकता के बिना परिणाम ऑब्जेक्ट में प्रत्येक पंक्ति को मैप करने का वास्तविक कार्यान्वयन करता है। इसे JdbcTemplate . पर कॉल करके कॉल और हैंडल किया जाएगा ।
अपवाद
JDBC द्वारा प्रदान किए गए अपवाद अक्सर बहुत कम मूल्य के साथ आवश्यकता से अधिक प्रभावशाली होते हैं। इस संबंध में स्प्रिंग का डेटा एक्सेस अपवाद पदानुक्रम अधिक सुव्यवस्थित और उचित है। इसका मतलब यह है कि इसके शस्त्रागार में अपवाद वर्गों का एक सुसंगत सेट है, जो JDBC के एक आकार के विपरीत सभी अपवादों के लिए उपयुक्त है जिसे SQLException कहा जाता है। डेटा एक्सेस से संबंधित सभी समस्याओं के लिए। स्प्रिंग के डेटा एक्सेस अपवाद DataAccessException . के साथ निहित हैं कक्षा। इसलिए, हमारे पास ढांचे में निहित चेक बनाम अनचेक अपवाद दोनों का विकल्प हो सकता है। यह अधिक व्यावहारिक लगता है क्योंकि रनटाइम डेटा एक्सेस के दौरान होने वाली कई समस्याओं का वास्तव में कोई समाधान नहीं है और जब हम उपयुक्त विकल्प के साथ स्थिति को संबोधित नहीं कर सकते हैं तो हम उन्हें पकड़ लेते हैं।
डेटा एक्सेस को सरल बनाने का स्प्रिंग का तरीका
स्प्रिंग वास्तव में यह करता है कि यह डेटा एक्सेस मैकेनिज्म के निश्चित और परिवर्तनशील हिस्से को दो वर्गों में विभाजित करता है जिन्हें टेम्पलेट क्लासेस कहा जाता है। और कॉलबैक कक्षाएं , क्रमश। कोड का निश्चित भाग डेटा एक्सेस के पूर्ण भाग का प्रतिनिधित्व करता है और परिवर्तनीय भाग डेटा एक्सेस विधि है जो बदलती आवश्यकता के अनुसार बदलता रहता है।
संक्षेप में, टेम्पलेट कक्षाएं हैंडल:
- लेन-देन नियंत्रण
- संसाधन प्रबंधन
- अपवाद प्रबंधन
और, कॉलबैक कक्षाएं हैंडल:
- क्वेरी स्टेटमेंट बनाना
- पैरामीटर बाध्यकारी
- परिणाम सेट मार्शलिंग
उपयोग की जाने वाली निरंतर तकनीक की पसंद के अनुसार, हम कई टेम्पलेट वर्गों में से एक को चुन सकते हैं। उदाहरण के लिए, JDBC के लिए हम JdbcTemplate . चुन सकते हैं , या ORM के लिए हम JpaTemplate . चुन सकते हैं , हाइबरनेटटेम्पलेट , और आगे।
अब, डेटाबेस से कनेक्ट करते समय, हमारे पास डेटा स्रोत को कॉन्फ़िगर करने के लिए तीन विकल्प हैं, जैसे:
- JDBC ड्राइवर द्वारा परिभाषित
- जेएनडीआई द्वारा देखा गया
- कनेक्शन पूल से प्राप्त किया गया
एक उत्पादन-तैयार एप्लिकेशन आमतौर पर कनेक्शन पूल या जेएनडीआई का उपयोग करता है। JDBC ड्राइवर परिभाषित डेटा स्रोत अब तक के सबसे सरल हैं, हालांकि इसका उपयोग ज्यादातर परीक्षण उद्देश्यों के लिए किया जाता है। स्प्रिंग पैकेज में तीन वर्ग प्रदान करता है org.springframework.jdbc.datasource इस श्रेणी के; वे हैं:
- DriverManagerDataSource: मानक JDBC का सरल कार्यान्वयन डेटा स्रोत इंटरफ़ेस, सादे पुराने JDBC को कॉन्फ़िगर करना DriverManager बीन गुणों के माध्यम से, और एक नया कनेक्शन लौटा रहा है हर अनुरोध से।
- SingleConnectionDataSource: प्रत्येक अनुरोध पर समान कनेक्शन लौटाता है। इस प्रकार का कनेक्शन मुख्य रूप से परीक्षण के लिए है।
- SimpleDriverDataSource: DriverManagerDataSource . के समान सिवाय इसके कि इसमें OSGi जैसे विशेष वर्ग लोडिंग मुद्दे हैं; यह वर्ग सीधे JDBC ड्राइवर के साथ काम करता है।
इन डेटा स्रोतों को कॉन्फ़िगर करना समान है। हम उन्हें बीन क्लास में या एक्सएमएल के माध्यम से कॉन्फ़िगर कर सकते हैं।
// Configuring MySQL data source @Bean public DataSource dataSource() { DriverManagerDataSource ds=new DriverManagerDataSource(); ds.setDriverClassName("com.mysql.jdbc.Driver"); ds.setUrl("jdbc:mysql://localhost:3306/testdb"); ds.setUsername("root"); ds.setPassword("secret"); return ds; } <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" p_driverClassName="com.mysql.jdbc.Driver" p_url="jdbc:mysql://localhost:3306/testdb" p_username="root" p_password="secret"/>
JDBC टेम्प्लेट क्लासेस
स्प्रिंग JDBC के साथ डेटा एक्सेस को आसान बनाने के लिए कुछ टेम्प्लेट क्लासेस प्रदान करता है:
- JdbcTemplate: यह मूल JDBC पैकेज का मूल वर्ग है org.springframework.jdbc.core जो अनुक्रमित प्रश्नों के माध्यम से डेटाबेस तक सबसे सरल पहुंच प्रदान करता है।
- NamedParameterJdbcTemplate: यह टेम्प्लेट वर्ग JDBC संचालन का एक बुनियादी सेट भी प्रदान करता है जहाँ मान SQL क्वेरी में पारंपरिक '?' प्लेसहोल्डर के बजाय नामित मापदंडों से बंधे होते हैं।
JDBC कॉलबैक क्लासेस
org.springframework.jdbc.core में परिभाषित प्रमुख JDBC कॉलबैक कार्यात्मक इंटरफ़ेस हैं:
- CallableStatementCallback
: JDBC CallableStatement. . पर काम करता है इस कॉलबैक का उपयोग JdbcTemplate . द्वारा आंतरिक रूप से किया जाता है और एक ही CallableStatement . पर निष्पादन की अनुमति देता है जैसे एकल या एकाधिक SQL विभिन्न मापदंडों के साथ कॉल निष्पादित करते हैं। - तैयार स्टेटमेंट कॉलबैक
: JDBC तैयार स्टेटमेंट पर काम करता है यह कॉलबैक आंतरिक रूप से JdbcTemplate . द्वारा उपयोग किया जाता है और एक PreparedStatement . पर एक से अधिक ऑपरेशन के निष्पादन की अनुमति देता है जैसे सिंगल या मल्टीपल SQL एक्ज़ीक्यूटअपडेट कॉल विभिन्न मापदंडों के साथ। - विवरण कॉलबैक
: JDBC विवरण पर काम करता है . इस कॉलबैक का उपयोग JdbcTemplate . द्वारा आंतरिक रूप से भी किया जाता है एक विवरण . पर एक से अधिक ऑपरेशन निष्पादित करने के लिए जैसे सिंगल या मल्टीपल SQL एक्जीक्यूटअपडेट कॉल।
एक साधारण स्प्रिंग बूट JDBC उदाहरण
आइए एक साधारण स्प्रिंग बूट उदाहरण का प्रयास करें। स्प्रिंग बूट प्रोजेक्ट स्वचालित रूप से कॉन्फ़िगरेशन की कई जटिलताओं को संभालता है जहां एक डेवलपर को मावेन फ़ाइल pom.xml में सही निर्भरता शामिल करने के बाद सभी परेशानियों से छुटकारा मिलता है। . लेख की लंबाई कम रखने के लिए, हम कोड स्पष्टीकरण शामिल नहीं करेंगे। अधिक विस्तृत विवरण के लिए कृपया लेख के अंत में दिए गए संदर्भों का उपयोग करें।
निम्नलिखित उदाहरण पर काम करने के लिए, MySQl में एक डेटाबेस और एक तालिका इस प्रकार बनाएं:
MySQL डेटाबेस में लॉग इन करें और निम्न कमांड के साथ एक डेटाबेस और एक टेबल बनाएं:
CREATE DATABASE testdb; USE testdb; CREATE TABLE candidate( id INT UNSIGNED NOT NULL AUTO_INCREMENT, fullname VARCHAR(100) NOT NULL, email VARCHAR(100) NOT NULL, phone VARCHAR(10) NOT NULL, PRIMARY KEY(id) );
निर्भरता JDBC और MySQL के साथ स्प्रिंग टूल सूट (STS) से स्प्रिंग स्टार्टर प्रोजेक्ट के रूप में प्रारंभ करें। मावेन कॉन्फ़िगरेशन फ़ाइल, pom.xml , परियोजना का विवरण इस प्रकार है:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns_xsi="http://www.w3.org/2001/XMLSchema-instance" xsi_schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.mano.springbootjdbc.demo</groupId> <artifactId>spring-boot-jdbc-demo</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>spring-boot-jdbc-demo</name> <description>Demo project for Spring Boot jdbc</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.10.RELEASE</version> <relativePath/> <!-- Look up parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8 </project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8 </project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven- plugin</artifactId> </plugin> </plugins> </build> </project>
मॉडल क्लास:Candidate.java
package org.mano.springbootjdbc.demo.model; public class Candidate { private int id; private String fullname; private String email; private String phone; public Candidate() { super(); } public Candidate(int id, String fullname, String email, String phone) { super(); setId(id); setFullname(fullname); setEmail(email); setPhone(phone); } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getFullname() { return fullname; } public void setFullname(String fullname) { this.fullname = fullname; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } @Override public String toString() { return "Candidate [id=" + id + ", fullname=" + fullname + ", email=" + email + ", phone=" + phone + "]"; } }
डेटा एक्सेस ऑब्जेक्ट इंटरफ़ेस:CandidateDao.java
package org.mano.springbootjdbc.demo.dao; import java.util.List; import org.mano.springbootjdbc.demo.model.Candidate; public interface CandidateDao { public void addCandidate(Candidate candidate); public void modifyCandidate(Candidate candidate, int candidateId); public void deleteCandidate(int candidateId); public Candidate find(int candidateId); public List<Candidate> findAll(); }
डेटा एक्सेस ऑब्जेक्ट इम्प्लीमेंटेशन क्लास:CandidateDaoImpl.java
package org.mano.springbootjdbc.demo.dao; import java.util.ArrayList; import java.util.List; import org.mano.springbootjdbc.demo.model.Candidate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.jdbc.core.BeanPropertyRowMapper; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Repository; @Repository @Qualifier("candidateDao") public class CandidateDaoImpl implements CandidateDao { @Autowired JdbcTemplate jdbcTemplate; @Override public void addCandidate(Candidate candidate) { jdbcTemplate.update("insert into candidate (id,fullname,email,phone) " + "values (?,?,?,?)", candidate.getId(), candidate.getFullname(), candidate.getEmail(), candidate.getPhone()); System.out.println(candidate+" is added successfully!"); } @Override public void modifyCandidate(Candidate candidate, int candidateId) { jdbcTemplate.update("update candidate fullname=?, email=?,phone=? " + "where id=? values (?,?,?,?)",candidate.getFullname(), candidate.getEmail(), candidateId); System.out.println("Candidate with id="+candidateId+ " modified successfully!"); } @Override public void deleteCandidate(int candidateId) { jdbcTemplate.update("delete from candidate where id=?", candidateId); System.out.println("Candidate with id="+candidateId+ " deleted successfully!"); } @Override public Candidate find(int candidateId) { Candidate c = null; c = (Candidate) jdbcTemplate.queryForObject("select * from candidate " + "where id=?", new Object[] { candidateId }, new BeanPropertyRowMapper<Candidate>(Candidate. class)); return c; } @Override public List<Candidate> findAll() { List<Candidate> candidates = new ArrayList<>(); candidates = jdbcTemplate.query("select * from candidate", new BeanPropertyRowMapper<Candidate> (Candidate.class)); return candidates; } }
स्प्रिंग बूट लोडर क्लास:SpringBootJdbcDemoApplication.java
package org.mano.springbootjdbc.demo; import java.util.List; import org.mano.springbootjdbc.demo.dao.CandidateDao; import org.mano.springbootjdbc.demo.model.Candidate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure. SpringBootApplication; @SpringBootApplication public class SpringBootJdbcDemoApplication implements CommandLineRunner { @Autowired private CandidateDao cdao; public static void main(String[] args) { SpringApplication.run(SpringBootJdbcDemoApplication. class, args); } @Override public void run(String... arg0) throws Exception { Candidate c1 = new Candidate(1, "Sachin Tendulkar", "[email protected]", "1234567890"); Candidate c2 = new Candidate(2, "Amit Saha", "[email protected]", "9632587410"); Candidate c3 = new Candidate(3, "Sandip Paul", "[email protected]", "8527419630"); Candidate c4 = new Candidate(4, "Rajib Kakkar", "[email protected]", "9876543210"); Candidate c5 = new Candidate(5, "Rini Simon", "[email protected]", "8624793150"); cdao.addCandidate(c1); cdao.addCandidate(c2); cdao.addCandidate(c3); cdao.addCandidate(c4); cdao.addCandidate(c5); List<Candidate> candidates = cdao.findAll(); for (Candidate candidate : candidates) { System.out.println(candidate); } cdao.deleteCandidate(3); candidates = cdao.findAll(); for (Candidate cc : candidates) { System.out.println(cc); } } }
Application.properties
spring.driverClassName=com.mysql.jdbc.Driver spring.url=jdbc:mysql://localhost:3306/testdb spring.username=root spring.password=secret
एप्लिकेशन चलाएँ
एप्लिकेशन को चलाने के लिए, प्रोजेक्ट एक्सप्लोरर . में प्रोजेक्ट पर राइट-क्लिक करें फलक और इस रूप में चलाएँ . चुनें -> स्प्रिंग बूट ऐप . बस इतना ही।
निष्कर्ष
स्प्रिंग के साथ रिलेशनल डेटाबेस प्रोग्रामिंग के साथ काम करने के लिए हमारे पास तीन विकल्प हैं:
- वसंत के साथ पुराने जमाने का JDBC। इसका मतलब है कि स्प्रिंग के डेटा समर्थन को छोड़कर कार्यक्रम में सभी व्यावहारिक उद्देश्यों के लिए स्प्रिंग फ्रेमवर्क का उपयोग करना।
- JDBC टेम्प्लेट क्लासेस का उपयोग करना। स्प्रिंग रिलेशनल डेटाबेस को क्वेरी करने के लिए JDBC एब्स्ट्रैक्शन क्लासेस प्रदान करता है; ये देशी JDBC कोड के साथ काम करने की तुलना में कहीं अधिक सरल हैं।
- वसंत को ओआरएम (ऑब्जेक्ट रिलेशनल मैपिंग) ढांचे के लिए भी उत्कृष्ट समर्थन है और जेपीए (जावा पर्सिस्टेंट एनोटेशन) एपीआई जैसे हाइबरनेट के प्रमुख कार्यान्वयन के साथ अच्छी तरह से एकीकृत हो सकता है। इसकी अपनी स्प्रिंग डेटा जेपीए सहायता भी है जो रनटाइम पर स्वचालित रूप से रिपोजिटरी कार्यान्वयन उत्पन्न कर सकती है।
यदि कोई किसी कारण से JDBC का विकल्प चुनता है, तो स्प्रिंग टेम्पलेट समर्थन जैसे JdbcTemplate का उपयोग करना बेहतर है। ओआरएम का उपयोग करने के अलावा।
संदर्भ
- दीवारें, क्रैग। स्प्रिंग इन एक्शन 4 , मैनिंग प्रकाशन
- स्प्रिंग 5 एपीआई दस्तावेज़ीकरण