一,准备工作,导入所需架包
二,通过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下载