This Blog instruction will help us to access database for performing search, create, read, update and delete (SCRUD) using Spring framework JDBC.
Pre-requsite
Instructions assume that jdk is installed without any error.
Implemenation instructions
- Required Software
- Developemnt
- Testing
- Java test class used for testing.
- Create a Simple spring project name. Following image will guide us. Add the required libraries in classpath. - mysql-connector-java-5.1.34.jar - spring-aop-4.1.3.RELEASE.jar - spring-beans-4.1.3.RELEASE.jar - spring-context-4.1.3.RELEASE.jar - spring-context-support-4.1.3.RELEASE.jar - spring-core-4.1.3.RELEASE.jar - spring-expression-4.1.3.RELEASE.jar - spring-jdbc-4.1.3.RELEASE.jar - spring-tx-4.1.3.RELEASE.jar - aopalliance-1.0.jar - log4j-1.2.14.jar - slf4j-jcl-1.7.5.jar Workspace will look like following.
- Create folder name resource and add in classpath. Create test_data.sql in resource folder and following snippet. This sql script is used to prepare test table and procedure.
- Create package spring.jdbc.template.example
- Create simple pojo class Member and following snippet.
- Create customize RowMapper implements RowMapper<Member> and add following snippet.
- Create interface StudentDAOIntf and add following snippet. We will define all following methods to implements example of SCRUD functions.
- Create class StudentDAOImpl it implements interface StudentDAOIntf and add following snippet.
- Following table will explain the methods that used to SCRUD functionalities.
- Following table will explain the methods that used to batch functionalities.
- Create class MemberStoredProcedureDAOImpl and add following snippet.
- Create spring bean configuration Beans.xml in resource folder.
- propLoader bean (org.springframework.beans.factory.config.PropertyPlaceholderConfigurer) is used to load n number of properties file. In following example I mentioned only one file (db.properties) within <value> under <list> . Please not that in path section config.dir is a system Environment. In default scenario spring can read system variable all we need to do where we are mentioning system envrionment we have to mention it in following syntactical way. a) for system variable #{ systemEnvironment['<environment variable name>'] } . b) for system properties #{ systemProperties['<property variable name>'] } .
- Create db.properties in any location and set environment variable config.dir = "location".
- Following part is important for creating datasource and jdbcTemplate instances that is used in MemberDAOImpl.
- Following part is important for enable @Transactional that is used in MemberDAOImpl.
- Create log4j.xml in resource folder and add following snippet.
-- ####################################### -- Copyright © Kaustuv Maji , 2014 -- Repos - https://github.com/kaustuvmaji -- Blog - http://kaustuvmaji.blogspot.in -- ####################################### DROP TABLE if exists `TEST`.`Member` ; COMMIT; CREATE TABLE `TEST`.`Member` ( ID INT NOT NULL AUTO_INCREMENT, NAME VARCHAR(20) NOT NULL, AGE INT NOT NULL, PRIMARY KEY (ID) ); COMMIT; SELECT * FROM `TEST`.`Member` ; DELIMITER // DROP PROCEDURE IF EXISTS `TEST`.`fetchRecord` // CREATE PROCEDURE `TEST`.`fetchRecord` ( IN in_id INTEGER, OUT out_name VARCHAR(20), OUT out_age INTEGER) BEGIN SELECT NAME, age INTO out_name, out_age FROM Member WHERE id = in_id; END // DELIMITER ; COMMIT;
/** * * Copyright © Kaustuv Maji , 2014 * Repos - https://github.com/kaustuvmaji * Blog - http://kaustuvmaji.blogspot.in * */ package spring.jdbc.template.example; import java.io.Serializable; /** * @author KMaji * */ public class Member implements Serializable { /** * */ private static final long serialVersionUID = 8944832256293484687L; private String name; private Integer id; private Integer age; /** * Default constructor */ public Member() { } /** * Constructor with argument * @param name * @param age */ public Member(String name, Integer age) { super(); this.name = name; this.age = age; } /** * @return the name */ public final String getName() { return name; } /** * @param name the name to set */ public final void setName(String name) { this.name = name; } /** * @return the id */ public final Integer getId() { return id; } /** * @param id the id to set */ public final void setId(Integer id) { this.id = id; } /** * @return the age */ public final Integer getAge() { return age; } /** * @param age the age to set */ public final void setAge(Integer age) { this.age = age; } /* (non-Javadoc) * @see java.lang.Object#toString() */ @Override public String toString() { StringBuilder builder = new StringBuilder(); builder.append("Member ["); if (name != null) builder.append("name=").append(name).append(", "); if (id != null) builder.append("id=").append(id).append(", "); if (age != null) builder.append("age=").append(age); builder.append("]"); return builder.toString(); } }
/** * * Copyright © Kaustuv Maji , 2014 * Repos - https://github.com/kaustuvmaji * Blog - http://kaustuvmaji.blogspot.in * */ package spring.jdbc.template.example; import java.sql.ResultSet; import java.sql.SQLException; import org.springframework.jdbc.core.RowMapper; /** * This is custom row mapper for member class. * @author KMaji * */ public class MemberMapper implements RowMapper{ /** * (non-Javadoc) * * @see org.springframework.jdbc.core.RowMapper#mapRow(java.sql.ResultSet, * int) */ @Override public Member mapRow(ResultSet rs, int rowNum) throws SQLException { Member member = new Member(); member.setId(rs.getInt("id")); member.setName(rs.getString("name")); member.setAge(rs.getInt("age")); return member; } }
/** * * Copyright © Kaustuv Maji , 2014 * Repos - https://github.com/kaustuvmaji * Blog - http://kaustuvmaji.blogspot.in * */ package spring.jdbc.template.example; import java.util.List; /** * This interface is used to show-case example of SCRUD. * * @author KMaji * */ public interface MemberDAOIntf { /** * This is the method to be used to create a record in the Member table. */ public void create(String name, Integer age); /** * This is the method to be used to list down a record from the Member * table corresponding to a passed member id. * * @return {@link Member} */ public Member getMember(Integer id); /** * This is the method to be used to list down a record from the Member * table corresponding to a passed member id. print record as string * */ public void getMemberAsString(Integer id); /** * This method is used to retrieve row set size. * @param sql * @return size of row set. */ public int getRowSetSize(String sql); /** * This is the method to be used to list down all the records from the * Member table. * * @return List of {@link Member} */ public List<Member> listMembers(); /** * This is the method to be used to delete a record from the Member table * corresponding to a passed member id. */ public void delete(Integer id); /** * This is the method to be used to update a record into the Member table. */ public void update(Integer id, Integer age); /** * This method is example of inserting mass data in table. * * @param members */ public void insertBatch(final List<Member> members); /** * This method is example of inserting mass data in table using sql. * * @param sql */ public void batchSql(final String sql); }
/** * * Copyright © Kaustuv Maji , 2014 * Repos - https://github.com/kaustuvmaji * Blog - http://kaustuvmaji.blogspot.in * */ package spring.jdbc.template.example; import java.sql.PreparedStatement; import java.sql.SQLException; import java.util.List; import org.apache.log4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.BatchPreparedStatementSetter; import org.springframework.jdbc.core.BeanPropertyRowMapper; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; /** * This class is used to show-case example of SCRUD functions. This class will * also show example of use spring jdbc batch functions. * * @author KMaji * */ @Component public class MemberDAOImpl implements MemberDAOIntf { private static Logger log = Logger.getLogger(MemberDAOImpl.class); @Autowired private JdbcTemplate jdbcTemplate; @Autowired private MemberMapper memberMapper; /** * */ public MemberDAOImpl() { } /** * (non-Javadoc) * * @see spring.jdbc.template.example.MemberDAOIntf#create(java.lang.String, * java.lang.Integer) */ @Override @Transactional public void create(String name, Integer age) { final String SQL = "insert into Member (name, age) values (?, ?)"; // Issue a single SQL update operation (such as an insert, update or // delete statement) via a prepared statement, binding the given // arguments. jdbcTemplate.update(SQL, name, age); log.info("Created Record Name = " + name + " Age = " + age); return; } /** * (non-Javadoc) * * @see spring.jdbc.template.example.MemberDAOIntf#getMember(java.lang.Integer) */ @Override @Transactional(readOnly = true) public Member getMember(Integer id) { String SQL = "select * from Member where id = ?"; // Query given SQL to create a prepared statement from SQL and a list of // arguments to bind to the query, expecting a result object. Member member = jdbcTemplate.queryForObject(SQL, new Object[]{id}, memberMapper); return member; } /** * (non-Javadoc) * * @see spring.jdbc.template.example.MemberDAOIntf#listMembers() */ @Override @Transactional public List<Member> listMembers() { String SQL = "select * from Member"; // perfect example for BeanPropertyRowMapper <> List<Member> members = jdbcTemplate.query(SQL, new BeanPropertyRowMapper<Member>(Member.class)); return members; } /** * (non-Javadoc) * * @see spring.jdbc.template.example.MemberDAOIntf#delete(java.lang.Integer) */ @Override @Transactional public void delete(Integer id) { String SQL = "delete from Member where id = ?"; // Issue a single SQL update operation (such as an insert, update or // delete statement) via a prepared statement, binding the given // arguments. jdbcTemplate.update(SQL, id); log.info("Deleted Record with ID = " + id); return; } /** * (non-Javadoc) * * @see spring.jdbc.template.example.MemberDAOIntf#update(java.lang.Integer, * java.lang.Integer) */ @Override @Transactional public void update(Integer id, Integer age) { String SQL = "update Member set age = ? where id = ?"; // Issue a single SQL update operation (such as an insert, update or // delete statement) via a prepared statement, binding the given // arguments. jdbcTemplate.update(SQL, age, id); log.info("Updated Record with ID = " + id); return; } /** * (non-Javadoc) * * @see spring.jdbc.template.example.MemberDAOIntf#getMemberAsString(java.lang. * Integer) */ @Override @Transactional(readOnly = true) public void getMemberAsString(Integer id) { String SQL = "select NAME from Member where id = ?"; log.info(jdbcTemplate.queryForObject(SQL, new Object[]{id}, String.class)); } /** * (non-Javadoc) * * @see spring.jdbc.template.example.MemberDAOIntf#insertBatch(java.util.List) */ @Override public void insertBatch(final List<Member> members) { String sql = "INSERT INTO Member " + "( NAME, AGE) VALUES ( ?, ?)"; // Issue multiple update statements on a single PreparedStatement, using // batch updates and a BatchPreparedStatementSetter to set values. jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() { @Override public void setValues(PreparedStatement ps, int arg1) throws SQLException { Member member = members.get(arg1); ps.setString(1, member.getName()); ps.setInt(2, member.getAge()); } @Override public int getBatchSize() { return members.size(); } }); } /** * (non-Javadoc) * * @see spring.jdbc.template.example.MemberDAOIntf#batchSql(java.lang.String) */ @Override public void batchSql(final String sql) { // Issue multiple SQL updates on a single JDBC Statement using batching. jdbcTemplate.batchUpdate(new String[]{sql}); } /** * (non-Javadoc) * * @see spring.jdbc.template.example.MemberDAOIntf#getRowSetSize(java.lang.String * ) */ @Override public int getRowSetSize(String sql) { @SuppressWarnings("deprecation") // Query given SQL to create a prepared statement from SQL and a list of // arguments to bind to the query, resulting in an int value. int total = jdbcTemplate.queryForInt(sql); return total; } }
Methods name | Description |
---|---|
create | This method is used to create a record in the Member table. - jdbcTemplate.update() is used to insert data into member table. - @Transactional is used to identify this method transaction enable. |
update | This method is used to update a record into the Member table. - jdbcTemplate.update() is used to update data into member table based on given id. - @Transactional is used to identify this method transaction enable. |
delete | This method is used to delete a record from the Member table, corresponding to a passed member id. - jdbcTemplate.update() is used to delete data into member table based on given id. - @Transactional is used to identify this method transaction enable. |
listMembers | This method is used to fetch all the records from the Member table. This is example of classic select * from. - Example of BeanPropertyRowMapper<T> |
getMember | This method is used to fetch member details(Member Object) information corresponding to a passed member id. - jdbcTemplate.queryForObject() is used to fetch data. - Example of customize RowMapper<T>. |
getMemberAsString | This method is used to fetch member details(String Object) information corresponding to a passed member id. - jdbcTemplate.queryForObject() is used to fetch data. |
getRowSetSize | This method is used to retrieve size table. - jdbcTemplate.queryForInt () is fetch the data |
Methods name | Description |
---|---|
insertBatch | This method is used to create huge number of record in the Member table. - jdbcTemplate.batchUpdate() is used to insert data into member table. |
batchSql | This method is example of inserting huge number of data in table using sql query. |
/** * * Copyright © Kaustuv Maji , 2014 * Repos - https://github.com/kaustuvmaji * Blog - http://kaustuvmaji.blogspot.in * */ package spring.jdbc.template.example; import java.util.Map; import javax.sql.DataSource; import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; import org.springframework.jdbc.core.namedparam.SqlParameterSource; import org.springframework.jdbc.core.simple.SimpleJdbcCall; /** * This class is used to show-case example of calling stored procedure. * * @author kmaji * */ public class MemberStoredProcedureDAOImpl { private DataSource dataSource; private SimpleJdbcCall jdbcCall; /** * Example of calling stored procedure. * * @param id * @return */ public Member getMembers(Integer id) { SqlParameterSource in = new MapSqlParameterSource(). addValue("in_id", id); Map<String, Object> out = jdbcCall.execute(in); Member member = new Member(); member.setId(id); member.setName((String) out.get("out_name")); member.setAge((Integer) out.get("out_age")); return member; } /** * Setter method for datasource and {@link SimpleJdbcCall}. * * @param dataSource */ public void setDataSource(DataSource dataSource) { this.jdbcCall = new SimpleJdbcCall(dataSource). withProcedureName("fetchRecord"); } }
<?xml version="1.0" encoding="UTF-8"?> <!-- # # Copyright © Kaustuv Maji , 2014 # Repos - https://github.com/kaustuvmaji # Blog - http://kaustuvmaji.blogspot.in # --> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:c="http://www.springframework.org/schema/c" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:p="http://www.springframework.org/schema/p" xmlns:repository="http://www.springframework.org/schema/data/repository" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd http://www.springframework.org/schema/data/repository http://www.springframework.org/schema/data/repository/spring-repository.xsd"> <!-- Scans the classpath for annotated components that will be auto-registered as Spring beans. By default, the Spring-provided @Component, @Repository, @Service, and @Controller stereotypes will be detected. Here in base-package section I mentioned spring.jdbc.template.example --> <context:component-scan base-package="spring.jdbc.template.example" /> <!-- Indicates whether the implicit annotation post-processors should be enabled. Default is "true". --> <context:annotation-config/> <!-- This bean is used to load properties files. --> <bean id="propLoader" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="locations"> <list> <value> file:#{ systemEnvironment['config.dir'] }/db.properties </value> </list> </property> </bean> <!-- This bean is used to connect mySql database. --> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" p:driverClassName="${jdbc.driverClassName}" p:url="${jdbc.url}" p:username="${jdbc.username}" p:password="${jdbc.password}" /> <!-- Database script execution maybe we can use it for embed schema --> <!-- <jdbc:initialize-database data-source="dataSource"> <jdbc:script location="classpath:test-data_1.sql" /> </jdbc:initialize-database> --> <!-- this beans is going to manage transaction --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean> <tx:annotation-driven proxy-target-class="true" transaction-manager="transactionManager" /> <!-- It simplifies the use of JDBC and helps to avoid common errors. It executes core JDBC workflow, leaving application code to provide SQL and extract results. This class executes SQL queries or updates, initiating iteration over ResultSets and catching JDBC exceptions and translating them to the generic, more informative exception hierarchy defined in the org.springframework.dao package. --> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate" p:dataSource-ref="dataSource" /> <bean id="memberMapper" class="spring.jdbc.template.example.MemberMapper" /> <bean id="memberJDBCTemplate" class="spring.jdbc.template.example.MemberDAOImpl" /> <bean id="memberJDBCImpl" class="spring.jdbc.template.example.MemberStoredProcedureDAOImpl" p:dataSource-ref="dataSource" /> </beans>
<!-- This bean is used to load properties files. --> <bean id="propLoader" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="locations"> <list> <!-- Mention n number of file paths--> <value> file:#{ systemEnvironment['config.dir'] }/db.properties </value> </list> </property> </bean>
jdbc.driverClassName=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost/test jdbc.username=root jdbc.password=
<!-- This bean is used to connect mySql database. --> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" p:driverClassName="${jdbc.driverClassName}" p:url="${jdbc.url}" p:username="${jdbc.username}" p:password="${jdbc.password}" /> <!-- Database script execution maybe we can use it for embed schema --> <!-- <jdbc:initialize-database data-source="dataSource"> <jdbc:script location="classpath:test-data_1.sql" /> </jdbc:initialize-database> --> lt;!-- It simplifies the use of JDBC and helps to avoid common errors. It executes core JDBC workflow, leaving application code to provide SQL and extract results. This class executes SQL queries or updates, initiating iteration over ResultSets and catching JDBC exceptions and translating them to the generic, more informative exception hierarchy defined in the org.springframework.dao package. --> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate" p:dataSource-ref="dataSource" />
<!-- this beans is going to manage transaction --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean> <tx:annotation-driven proxy-target-class="true" transaction-manager="transactionManager" />
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE log4j:configuration PUBLIC "-//APACHE//DTD LOG4J 1.2//EN" "log4j.dtd"> <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="true"> <!-- Appenders --> <appender name="console" class="org.apache.log4j.ConsoleAppender"> <param name="Target" value="System.out" /> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%d{ISO8601} %-5p %-1X{TID} %t [%c] %m%n" /> </layout> </appender> <!-- Appenders --> <appender name="file" class="org.apache.log4j.RollingFileAppender"> <param name="Threshold" value="ALL" /> <param name="File" value="diag.log" /> <param name="Append" value="true" /> <param name="MaxFileSize" value="500000KB" /> <param name="MaxBackupIndex" value="10" /> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%d{ISO8601} %-5p %-1X{TID} %t [%c] %m%n" /> </layout> </appender> <!-- Root Logger --> <root> <priority value="ALL" /> <appender-ref ref="console" /> <appender-ref ref="file" /> </root> </log4j:configuration>
Post Development testing
Following class will be used to test spring jdbc template examples.
/** * * Copyright © Kaustuv Maji , 2014 * Repos - https://github.com/kaustuvmaji * Blog - http://kaustuvmaji.blogspot.in * */ package spring.jdbc.template.example; import java.util.ArrayList; import java.util.List; import org.apache.log4j.Logger; import org.springframework.context.support.AbstractApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * @author KMaji * */ public class ExampleApp { private static Logger log = Logger.getLogger(ExampleApp.class); /** * */ static { // System.out.println(System.getenv()); } /** * @param args */ public static void main(String... args) { @SuppressWarnings("resource") AbstractApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml", ExampleApp.class); MemberDAOIntf memberDaoImpl = null; if (context.containsBean("memberJDBCTemplate")) { memberDaoImpl = (MemberDAOIntf) context.getBean("memberJDBCTemplate"); } MemberStoredProcedureDAOImpl sspDao = null; if (context.containsBean("memberJDBCImpl")) { sspDao = (MemberStoredProcedureDAOImpl) context.getBean("memberJDBCImpl"); } log.info(memberDaoImpl.getRowSetSize("select COUNT(*) from Member")); { // SCRUD Example. { // Create log.info("{Executing} ------Records Creation--------"); memberDaoImpl.create("member_1", 11); memberDaoImpl.create("member_2", 2); memberDaoImpl.create("member_3", 15); } { // Retrieve log.info("{Executing} ------Listing Multiple Records--------"); List<Member> members = memberDaoImpl.listMembers(); for (Member record : members) { log.info("ID : " + record.getId() + " , Name : " + record.getName() + " , Age : " + record.getAge()); } log.info("{Executing} ----Listing Record with ID = 3 -----"); Member member = memberDaoImpl.getMember(3); log.info("ID : " + member.getId() + " , Name : " + member.getName() + " , Age : " + member.getAge()); memberDaoImpl.getMemberAsString(3); } { // Update log.info("{Executing} ---- Updating Record with ID = 3 -----"); memberDaoImpl.update(3, 20); } { // Delete log.info("{Executing} ---- Deleting Record with ID = 2 -----"); memberDaoImpl.delete(2); log.info("Deleted member with " + "ID : "); } } { // Batch Example { // Insert log.info("{Executing} ---- Records Creation as a batch process -----"); List<Member> members = new ArrayList<>(); for (int i = 0; i < 10; i++) { members.add(new Member("member_batch_" + i, i * 5)); } memberDaoImpl.insertBatch(members); log.info(memberDaoImpl.listMembers()); } { // Update log.info("{Executing} ---- Records update as a batch process -----"); memberDaoImpl.batchSql("UPDATE Member SET NAME ='Mary' where AGE > 35"); log.info(memberDaoImpl.listMembers()); } } { // calling stored procedure log.info("{Executing} ---- Records according to stored procedure -----"); log.info(sspDao.getMembers(3)); } // register shutdownhook context.registerShutdownHook(); } }
Source Code
- References:
European Union laws require you to give European Union visitors information about cookies used on your blog. In many cases, these laws also require you to obtain consent.
As a courtesy, we have added a notice on your blog to explain Google's use of certain Blogger and Google cookies, including use of Google Analytics and AdSense cookies.
No comments:
Post a Comment