Spring通过JdbcTmplate模板操作数据库详解

一,准备工作,导入所需架包


二,通过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;
		}
		
	}
}

我们已经看出了效果。具体我们来解释一下

queryForObject(String sql, RowMapper<User> rowMapper, Object... args)参数的意义,以及用法
sql:表示你要执行的sql语句
args:表示你要往sql中传递的参数
rowMapper可以理解为对象与数据库中数据映射的接口。

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下载

猜你喜欢

转载自blog.csdn.net/mister_yang/article/details/80665203