文档章节

Spring框架笔记(二十四)——Spring中的JDBC的两种使用方式

HappyBKs
 HappyBKs
发布于 2015/08/26 20:41
字数 1972
阅读 2269
收藏 17

为了使 JDBC 更加易于使用, Spring 在 JDBC API 上定义了一个抽象层, 以此建立一个 JDBC 存取框架.

作为 Spring JDBC 框架的核心, JDBC 模板的设计目的是为不同类型的 JDBC 操作提供模板方法. 每个模板方法都能控制整个过程, 并允许覆盖过程中的特定任务. 通过这种方式, 可以在尽可能保留灵活性的情况下, 将数据库存取的工作量降到最低.

现在我们来介绍一下,各种CRUD可能用到的Spring JDBC的API:

使用 JdbcTemplate 更新数据库

用 sql 语句和参数更新数据库:

public int update(String sql, Object... args) throws DataAccessException

批量更新数据库: 

public int[] batchUpdate(String sql, List<Object[]> batchArgs) throws DataAccessException


使用 JdbcTemplate 查询数据库

查询单行: 

public <T> T queryForObject(String sql, RowMapper<T> rowMapper, Object... args) throws DataAccessException

查询多行:

public <T> List<T> query(String sql, RowMapper<T> rowMapper, Object... args) throws DataAccessException

单值查询:

public <T> T queryForObject(String sql, Class<T> requiredType) throws DataAccessException

使用Spring JDBC的好处——简化 JDBC 模板查询

每次使用都创建一个 JdbcTemplate 的新实例, 这种做法效率很低下.

JdbcTemplate 类被设计成为线程安全的, 所以可以再 IOC 容器中声明它的单个实例, 并将这个实例注入到所有的 DAO 实例中.

JdbcTemplate 也利用了 Java 1.5 的特定(自动装箱, 泛型, 可变长度等)来简化开发

Spring JDBC 框架还提供了一个 JdbcDaoSupport 类来简化 DAO 实现. 该类声明了 jdbcTemplate 属性, 它可以从 IOC 容器中注入, 或者自动从数据源中创建.


好我们还是给出例子吧。

一开始,我们给出所有我们需要的spring jdbc所需要的jar的pom,宁多勿少。

<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>com.happBKs.spring</groupId>
	<artifactId>jdbcSpring</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>jdbcSpring</name>
	<url>http://maven.apache.org</url>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	</properties>

	<dependencies>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.10</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>4.1.7.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-aspects</artifactId>
			<version>4.1.7.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>com.mchange</groupId>
			<artifactId>c3p0</artifactId>
			<version>0.9.5.1</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-jdbc</artifactId>
			<version>4.2.0.RELEASE</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-web</artifactId>
			<version>4.2.0.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>4.2.0.RELEASE</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-orm</artifactId>
			<version>4.2.0.RELEASE</version>
		</dependency>

		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.1.36</version>
		</dependency>
	</dependencies>
</project>

首先我们需要建立一个数据库springjdbc。然后创建两张表employee和department。

然后,我们插入几组数据:

department:

employee:

之后,我们定义相关的bean类:

package com.happBKs.spring.jdbcSpring;

public class DepartmentBean {
	String id;
	String departmentName;
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getDepartmentName() {
		return departmentName;
	}
	public void setDepartmentName(String departmentName) {
		this.departmentName = departmentName;
	}
	public DepartmentBean(String id, String departmentName) {
		super();
		this.id = id;
		this.departmentName = departmentName;
	}
	public DepartmentBean() {
		super();
		// TODO Auto-generated constructor stub
	}
	@Override
	public String toString() {
		return "DepartmentBean [id=" + id + ", departmentName="
				+ departmentName + "]";
	}
	
	
}
package com.happBKs.spring.jdbcSpring;

public class EmployeeBean {
	Integer id;
	String lastName;
	String email;
	DepartmentBean department;
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getLastName() {
		return lastName;
	}
	public void setLastName(String lastName) {
		this.lastName = lastName;
	}
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
	public DepartmentBean getDepartment() {
		return department;
	}
	public void setDepartment(DepartmentBean department) {
		this.department = department;
	}
	public EmployeeBean(Integer id, String lastName, String email,
			DepartmentBean department) {
		super();
		this.id = id;
		this.lastName = lastName;
		this.email = email;
		this.department = department;
	}
	public EmployeeBean() {
		super();
		// TODO Auto-generated constructor stub
	}
	@Override
	public String toString() {
		return "EmployeeBean [id=" + id + ", lastName=" + lastName + ", email="
				+ email + ", department=" + department + "]";
	}

	
}

注意,这里我们预想把dept_id对应改成一个成员DepartmentBean类型的对象。看看是否可以用Spring Jdbc实现。

然后,我们来定义Spring IOC容器配置文件applicationContext.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd
		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-4.1.xsd">

	<!-- 自动扫描的包 -->
	<context:component-scan base-package="com.happBKs.spring.jdbcSpring"></context:component-scan>



	<!-- 导入资源文件 -->
	<context:property-placeholder location="classpath:db.properties" />

	<!-- 配置c3p0数据源 -->
	<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
		<property name="user" value="${jdbc.user}"></property>
		<property name="password" value="${jdbc.password}"></property>
		<property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
		<property name="driverClass" value="${jdbc.driverClass}"></property>
		<property name="initialPoolSize" value="${jdbc.initPoolSize}"></property>
		<property name="maxPoolSize" value="${jdbc.maxPoolSize}"></property>
	</bean>
	
	<!-- 配置jdbc模板类 -->
	<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	
</beans>

以及db.properties:

jdbc.user=root
jdbc.password=
jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.jdbcUrl=jdbc:mysql:///springjdbc?useUnicode=true&characterEncoding=utf8

jdbc.initPoolSize=5
jdbc.maxPoolSize=10


好,下面我们尝试更新操作和查询操作:

package com.happBKs.spring.jdbcSpring;

import static org.junit.Assert.*;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import javax.sql.DataSource;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;

public class JDBCTest {

	ApplicationContext ctx=null;
	JdbcTemplate jdbcTemplate;
	{
		ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
		jdbcTemplate=(JdbcTemplate)ctx.getBean("jdbcTemplate");
	}
	@Test
	public void test() throws SQLException {
		DataSource dataSource=ctx.getBean(DataSource.class);
		//DataSource dataSource=(DataSource)ctx.getBean("dataSource");
		System.out.println(dataSource.getConnection());
	}
	/*
	 * 执行update、 insert、delete
	 */
	@Test
	public void testUpdate(){
		String sql="Update employee set last_name=? where id=?";
		jdbcTemplate.update(sql,"姚鼓励",5);
		
	}
	
	/*
	 * 执行批量更新、插入、删除
	 */
	@Test
	public void testBatchUpdate() {
		String sql="insert employee(last_name,email,dept_id) values(?,?,?)";
		List<Object[]> batchArgs=new ArrayList<Object[]>();
		batchArgs.add(new Object[]{"临时工1","1@qq.com",4});
		batchArgs.add(new Object[]{"临时工2","2@qq.com",4});
		batchArgs.add(new Object[]{"临时工3","3@qq.com",4});
		jdbcTemplate.batchUpdate(sql, batchArgs);
	}
	/*
	 * 从数据库中获得一条记录,实际得到对应的一个对象
	 * 注意:应该用的方法是<EmployeeBean> EmployeeBean org.springframework.jdbc.core.JdbcTemplate.queryForObject(String sql, RowMapper<EmployeeBean> rowMapper, Object... args) throws DataAccessException
	 * 而不是<EmployeeBean> EmployeeBean org.springframework.jdbc.core.JdbcTemplate.queryForObject(String sql, Class<EmployeeBean> requiredType, Object... args) throws DataAccessException
	 * 
	 * 1. 其中RowMapper指定如何映射结果集的行,常用的实现类为BeanPropertyRowMapper
	 *     这里插一句,当以后应用某个类的方法中有参数是接口类型时,我们需要创建一个该接口的实现类对象,但是不知道具体的实现类有哪些,这时候可以用Ctrl+T来查看该接口的实现类的树状图
	 * 2. 使用SQL语句中查询字段的别名来完成数据库表的字段名与类对象的属性名之间的映射,例如这里的last_name lastName
	 * 3. 不支持级联属性。即不支持String sql="select id,last_name lastName, email, dept_id as \"department.id\" from employee where id=?";
	 *     因为JdbcTemplate到底只是一个jdbc工具,而不是一个ORM框架
	 */
	@Test
	public void testQueryForObject(){
		String sql="select id,last_name lastName, email from employee where id=?";
		RowMapper<EmployeeBean> rowMapper=new BeanPropertyRowMapper<EmployeeBean>(EmployeeBean.class);
		EmployeeBean employee=jdbcTemplate.queryForObject(sql, rowMapper,1); 
		System.out.println(employee);
		
	}
	
	@Test
	public void testQueryForList(){
		String sql="select id,last_name lastName, email from employee where id>?";
		RowMapper<EmployeeBean> rowMapper=new BeanPropertyRowMapper<EmployeeBean>(EmployeeBean.class);
		List<EmployeeBean> employeeList=jdbcTemplate.query(sql, rowMapper,5); 
		System.out.println(employeeList);
		
	}
	
	/*
	 * 获取单个列的值,可以用SQL中的sum、count、avg函数
	 */
	@Test
	public void testQueryForObjectField(){
		String sql="select count(id) from employee";
		int count=jdbcTemplate.queryForObject(sql,Integer.class); 
		System.out.println(count);
		
	}
}

这里,输出的结果,我就不一一罗列,只挑几个吧:

void testBatchUpdate() 的结果:

void testQueryForObject()的结果:

EmployeeBean [id=1, lastName=王会计, email=wangkuaiji@126.com, department=null]

好吧,spring jdbc毕竟还是jdbc不是orm,所以级联对象时空的。


那么,我们在实际开发时应该如何使用Spring JDBC编写DAO模块呢?

直接给代码吧。

package com.happBKs.spring.jdbcSpring;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;

@Repository
public class EmployeeDAO {

	@Autowired
	private JdbcTemplate jdbcTemplate;
	
	public EmployeeBean get(int id)
	{
		String sql="select id,last_name lastName, email from employee where id=?";
		RowMapper<EmployeeBean> rowMapper=new BeanPropertyRowMapper<EmployeeBean>(EmployeeBean.class);
		EmployeeBean employee=jdbcTemplate.queryForObject(sql, rowMapper,id); 
		return employee;
	}
}

测试代码:

EmployeeDAO employeeDAO;
	{
		employeeDAO=ctx.getBean(EmployeeDAO.class);
		
	}
	
	@Test
	public void testEmployeeDAO(){
		System.out.println(employeeDAO.get(1));
		
	}

以上我们介绍的都是应用的JdbcTemplate类的对象创建,来帮助我们完成JDBC的各个功能。正如本文副标题所提到的,还有另一个类和另一种用法可以帮助我们实现这样的功能,那就是JdbcDaoSupport。

这里,我们定义DepartmentDAO类用这种方式实现,来看看吧:

package com.happBKs.spring.jdbcSpring;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
import org.springframework.stereotype.Repository;


/*
 * 不推荐使用JdbcDaoSupport,而推荐直接使用JdbcTemplate作为DAO类成员变量的方式
 */

@Repository
public class DepartmentDAO extends JdbcDaoSupport {
	
	@Autowired
	public void setDataSource2(DataSource dataSource){
		setDataSource(dataSource);//public final void setDataSource(DataSource dataSource) {
	}
	//注意:因为JdbcDaoSupport的setDataSource方法是final的所以不能重写,
	//这里采用了一种变通的方法,新设立了一个域dataSource2,实际用到了JdbcDaoSupport的setDataSource方法
	
	public DepartmentBean get(Integer id) {
		String sql = "";
		RowMapper<DepartmentBean> rowMapper = new BeanPropertyRowMapper<DepartmentBean>(
				DepartmentBean.class);
		DepartmentBean department = getJdbcTemplate().queryForObject(sql,
				rowMapper, id);
		return department;
	}

}

测试代码:

DepartmentDAO departmentDAO;
	{
		departmentDAO = ctx.getBean(DepartmentDAO.class);
	}
	
	@Test
	public void testDepartmentDAO(){
		System.out.println(departmentDAO.get(1));
		
	}






© 著作权归作者所有

共有 人打赏支持
HappyBKs

HappyBKs

粉丝 622
博文 301
码字总数 471696
作品 0
浦东
程序员
Spring实战读书笔记(1)

Spring的根本使命是? 简化Java开发 为了降低Java开发的复杂性,Spring采取了哪4种关键策略? 1、基于POJO的轻量级和最小侵入性编程 2、通过依赖注入和面向接口实现松耦合 3、基于切面和惯例...

祥林会跟你远走高飞
2014/12/30
0
0
Spring学习笔记1——基础知识

1.在java开发领域,Spring相对于EJB来说是一种轻量级的,非侵入性的Java开发框架,曾经有两本很畅销的书《Expert one-on-one J2EE Design and Development》和《Expert one-on-one J2EE deve...

李长春
2011/10/09
0
0
【第1章 Spring概述与结构】1.1 Spring起源与概述

Rod Johson在2002年编著的《Expert one to one J2EE design and development》一书中,对Java EE正统框架臃肿、低效、脱离现实的种种现状提出了质疑,并积极寻求探索革新之道。以此书为指导思...

陶邦仁
2015/05/15
0
0
Spring Boot 2.0 新特性解读

点击上方“程序员小灰”,选择“置顶公众号” 有趣有内涵的文章第一时间送达! 本文转载自公众号 InfoQ 作者|翟永超编辑|郭蕾Spring Boot 2.0 来啦,有哪些新特性?升级吗?写在前面 北京时...

bjweimengshu
04/13
0
0
Spring AOP 实现原理与 CGLIB 应用

AOP(Aspect Orient Programming),作为面向对象编程的一种补充,广泛应用于处理一些具有横切性质的系统级服务,如事务管理、安全检查、缓存、对象池管理等。AOP 实现的关键就在于 AOP 框架...

只想一个人静一静
2014/02/27
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

阿里云API网关使用教程

API 网关(API Gateway)提供高性能、高可用的 API 托管服务,帮助用户对外开放其部署在 ECS、容器服务等阿里云产品上的应用,提供完整的 API 发布、管理、维护生命周期管理。用户只需进行简...

mcy0425
35分钟前
4
0
解决远程登陆误按ctrl+s锁屏假死恢复

使用putty时,偶尔发生屏幕假死,不能输入等情况。 后来发现,只要数据ctrl+s,就会假死;输入ctrl+q就可以恢复过来。 很多刚从windows转移到linux上来工作的朋友,在用vi/vim编辑文件时,常常...

HJCui
38分钟前
0
0
@Transactional

事务管理是应用系统开发中必不可少的一部分。Spring 为事务管理提供了丰富的功能支持。Spring 事务管理分为编程式和声明式的两种方式。编程式事务指的是通过编码方式实现事务;声明式事务基于...

asdf08442a
42分钟前
2
0
widows下强制解除8080端口占用问题

使用win+R打开命令窗口 输入以下命令查看哪个任务占用了8080端口 netstat -ano |findstr "8080" 然后通过任务id强制关闭占用该端口的进程 tskill 10044 // 自己的试情况而定,这个ID是LISTE...

_Artisan
52分钟前
2
0
productFlavors简单实用

最近项目中,不同环境需要配置的参数越来越多,为了减少修改代码次数。研究了一下productFlavors的使用方式,总结如下 1. as3.0以上版本使用productFlavors时需要指定一个flavorDimensions,...

火云
54分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部