一,准备工作,导入所需架包
二,通过java元代码的形式使用JdbcTemplate操作。
首先我们创建我们的数据库和表
create database mydb3; use mydb3; create table user( username varchar(20) not null, age int not null, primary key key_username(`username`) )
然后我们看一下我们通过java代码测试jdbcTemplate的操作。
1.插入一条数据
/* * 插入操作 * */ @Test public void testInsert() { //创建链接,相当于jdbc的加载驱动等 DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName("com.mysql.jdbc.Driver"); dataSource.setUrl("jdbc:mysql:///mydb3"); dataSource.setUsername("root"); dataSource.setPassword("000000"); //创建JdbcTemplate对象 JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); /* * update(String sql, Object... args) * sql:表示执行的sql * args表示需要传进去的参数,可以为多个,与sql的?个数一致 */ String sql = "insert into user value(?,?)"; int rows = jdbcTemplate.update(sql,"tom",10); System.out.println(rows); }
2.更新一条数据
/* *更新操作 */ @Test public void testUpdate() { //创建链接,相当于jdbc的加载驱动等 DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName("com.mysql.jdbc.Driver"); dataSource.setUrl("jdbc:mysql:///mydb3"); dataSource.setUsername("root"); dataSource.setPassword("000000"); //创建JdbcTemplate对象 JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); /* * update(String sql, Object... args) * sql:表示执行的sql * args表示需要传进去的参数,可以为多个,与sql的?个数一致 */ String sql = "update user set age=? where username=?"; int rows = jdbcTemplate.update(sql,100,"tt"); System.out.println(rows); }
3.删除一条数据
/* *删除操作 */ @Test public void testDelete() { DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName("com.mysql.jdbc.Driver"); dataSource.setUrl("jdbc:mysql:///mydb3"); dataSource.setUsername("root"); dataSource.setPassword("000000"); //创建JdbcTemplate对象 JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); /* * update(String sql, Object... args) * sql:表示执行的sql * args表示需要传进去的参数,可以为多个,与sql的?个数一致 */ String sql = "delete from user where username=?"; int rows = jdbcTemplate.update(sql,"tt"); System.out.println(rows); }
4.查询数据记录数
/* *查询记录数 */ @Test public void testCount() { DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName("com.mysql.jdbc.Driver"); dataSource.setUrl("jdbc:mysql:///mydb3"); dataSource.setUsername("root"); dataSource.setPassword("000000"); //创建JdbcTemplate对象 JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); /* * queryForObject(String sql, Class<Integer> requiredType) * sql:表示执行的sql * requiredType:返回值类型、 */ String sql = "select count(*) from user"; int count = jdbcTemplate.queryForObject(sql, Integer.class); System.out.println(count); }
删改查操作已经详细贴出代码,他们主要是使用了jdbcTemplate.update(...)方法,具体方法的参数已经给出说明,下面我们看一下jdbcTemplate的查询方法。
5.查询单个对象
@Test public void testObject() { DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName("com.mysql.jdbc.Driver"); dataSource.setUrl("jdbc:mysql:///mydb3"); dataSource.setUsername("root"); dataSource.setPassword("000000"); //创建JdbcTemplate对象 JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); String sql = "select * from user where username=?"; User user = null; // try { user= jdbcTemplate.queryForObject(sql, new MyMapper(),new Object[] {"ytk"}); // }catch (Exception e) { // System.out.println("test"); // } System.out.println(user); }
创建RowMapper接口的实现类。
class MyMapper implements RowMapper<User>{ @Override public User mapRow(ResultSet set, int index) throws SQLException { if(set!=null) { User user = new User(); user.setUsername(set.getString("username")); user.setAge(set.getInt(2)); System.out.println(1); return user; }else { return null; } } }
我们已经看出了效果。具体我们来解释一下
6.查询结果为多个对象。
@Test public void testList() { DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName("com.mysql.jdbc.Driver"); dataSource.setUrl("jdbc:mysql:///mydb3"); dataSource.setUsername("root"); dataSource.setPassword("000000"); //创建JdbcTemplate对象 JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); String sql = "select * from user where username in(?,?)"; List<User> users = jdbcTemplate.query(sql, new MyMapper(),new Object[] {"tem","a"}); System.out.println(users); }
由上面可以看出呢,每个测试单元中都有数据库的链接设置,以及jdbcTemplate的对象的创建,那么我们有什么简单的方法来是实现代码的复用吗?spring的配置可以帮助我们解决这个问题,那么我们看一下jdbcTemplate在spring配置中的使用
三,JdbcTemplate在spring文件的配置及使用
首先我们创建一下web项目的结构
1.创建UserService类,注入UserDao的对象。
package cn.ies.c3p0; import java.util.List; import cn.ies.jdbc.User; public class UserService { private UserDao userDao; public void setUserDao(UserDao userDao) { this.userDao = userDao; } public void testInsert() { userDao.insert("ytk", 10); } public void testUpdate() { userDao.update("ytk",20); } public void testDelete() { userDao.delete("ytk"); } public int testCount() { return userDao.count(); } public User testObject(String username) { return userDao.testObject(username); } public List<User> testList(String key) { return userDao.testList(key); } }
2.创建测试类。
package cn.ies.c3p0; import java.util.List; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import cn.ies.jdbc.User; public class TestUserService { @Test public void testInsert() { ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml"); UserService userService = (UserService) context.getBean("userService"); userService.testInsert(); } @Test public void testUpdate() { ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml"); UserService userService = (UserService) context.getBean("userService"); userService.testUpdate(); } @Test public void testDelete() { ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml"); UserService userService = (UserService) context.getBean("userService"); userService.testDelete(); } @Test public void testCount() { ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml"); UserService userService = (UserService) context.getBean("userService"); int count =userService.testCount(); System.out.println(count); } @Test public void testObject() { ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml"); UserService userService = (UserService) context.getBean("userService"); User user = userService.testObject("ytek"); System.out.println(user==null); } @Test public void testList() { ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml"); UserService userService = (UserService) context.getBean("userService"); List<User> list = userService.testList("tt"); System.out.println(list.toString()); } }
3.创建UserDao类,注入jdbcTemplate对象
package cn.ies.c3p0; import java.sql.ResultSet; import java.sql.SQLException; import java.util.List; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.RowMapper; import cn.ies.jdbc.User; public class UserDao { private JdbcTemplate jdbctemplate; public void setJdbcTemplate(JdbcTemplate jdbctemplate) { this.jdbctemplate = jdbctemplate; } public void test(String sql,Object...args) { int rows = jdbctemplate.update(sql,args); System.out.println(rows); } public void insert(String username,int age) { String sql = "insert into user value(?,?)"; test(sql, new Object[] {username,age}); } public void update(String username, int age) { String sql = "update user set age = ? where username=?"; test(sql, new Object[] {age,username}); } public void delete(String username) { String sql = "delete from user where username=?"; test(sql, username); } public int count() { String sql = "select count(*) from user"; return jdbctemplate.queryForObject(sql,Integer.class); } public User testObject(String username) { String sql = "select * from user where username=?"; User user = null; try { user = jdbctemplate.queryForObject(sql, new MyRowMapper(), new Object[] {username}); }catch (Exception e) { return user; } return user; } public List<User> testList(String key) { String sql = "select * from user where username = ?"; List<User> users = null; try { users = jdbctemplate.query(sql, new Object[] {key},new MyRowMapper()); }catch (Exception e) { return null; } return users; } } class MyRowMapper implements RowMapper<User>{ @Override public User mapRow(ResultSet set, int index) throws SQLException { User user = new User(); user.setUsername(set.getString("username")); user.setAge(set.getInt(2)); return user; } }
4.接下来我们重点看一下配置文件是如何实现的。
首先是c3p0config.properties的文件
jdbc.driverClass=com.mysql.jdbc.Driver jdbc.jdbcUrl = jdbc:mysql:///mydb3 jdbc.user = root jdbc.password = 000000 jdbc.initialPoolSize=10 jdbc.maxIdleTime=60 jdbc.maxPoolSize=30 jdbc.minPoolSize=10
然后看一下spring的配置文件、
<!-- 加载配置文件 --> <context:property-placeholder location="classpath:c3p0config.properties"/> <!-- 配置链接池 --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"> <property name="driverClass" value="${jdbc.driverClass}"/> <property name="jdbcUrl" value="${jdbc.jdbcUrl}"/> <property name="user" value="${jdbc.user}"/> <property name="password" value="${jdbc.password}"/> <!-- 初始化链接数 --> <property name="initialPoolSize" value="${jdbc.initialPoolSize}"></property> <!-- 最大空闲时间为60s,超过60s就放回连接池 --> <property name="maxIdleTime" value="${jdbc.maxIdleTime}"></property> <!-- 最大链接数 --> <property name="maxPoolSize" value="${jdbc.maxPoolSize}"></property> <!-- 最小链接数 --> <property name="minPoolSize" value="${jdbc.minPoolSize}"></property> </bean> <!-- jdbcTemplate配置 --> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"></property> </bean> <!-- dao配置 --> <bean id="userDao" class="cn.ies.c3p0.UserDao"> <property name="jdbcTemplate" ref="jdbcTemplate"></property> </bean> <!-- service配置 --> <bean id="userService" class="cn.ies.c3p0.UserService"> <property name="userDao" ref="userDao"></property> </bean>
四,jdbcTemplate的常见的一个异常EmptyResultDataAccessException以及解决方案
org.springframework.dao.EmptyResultDataAccessException: Incorrect result size: expected 1, actual 0 at org.springframework.dao.support.DataAccessUtils.requiredSingleResult(DataAccessUtils.java:71) at org.springframework.jdbc.core.JdbcTemplate.queryForObject(JdbcTemplate.java:801) at cn.ies.jdbc.JdbcTemplateTest.testObject(JdbcTemplateTest.java:122) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) at org.junit.runners.ParentRunner.run(ParentRunner.java:363) at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86) at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:539) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:761) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:461) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:207)
原因:当我们查询的数据条数为0条时,或者我们使用jdbcTemplate.queryforObjet();查询的数据条数不唯一时,会抛出此异常,一般是因为查询的记录数为空抛出,只要用try-catch捕捉一下就可以解决。
案例下载链接:JdbcTemplate详细demo下载