2019-06-12
Spring整合JDBC配置
Spring提供了对持久层的整合功能,包括对JDBC以及各种ORM映射工具(如Hibernate、MyBatis)的整合封装。Spring对JDBC的封装使用的是模板设计模式。原来直接使用JDBC所需要的重复性代码都可以在模板类中完成,极大地简化JDBC的使用。
<!--引入property配置文件 -->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!--初始化数据源 -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${driver}" />
<property name="url" value="${url}" />
<property name="username" value="${user}" />
<property name="password" value="${password}" />
</bean>
<!--初始化操作模板 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<constructor-arg><ref bean="dataSource"/></constructor-arg>
</bean>
JdbcTemplate类
org.springframework.jdbc.core.JdbcTemplate类是Spring提供的JDBC操作模板类,该类是线程安全的(使用ThreadLocal机制保证数据库连接或会话对象的线程安全),可以方便地执行CRUD操作。
主要方法:
- queryForMap:将查询结果封装为Map<String,Object>对象返回
- queryForList:将查询结果封装为List<Map<String, Object>>返回
- queryForObject:将查询结果封装为对象返回。可以使用RowMapper映射器将查询结果集映射到用户自定义类中。映射器通过名称匹配的方式,自动将一行数据映射到指定类的实例中,并支持下划线到驼峰的转换
- query:将查询结果封装为List集合返回。可以使用RowMapper映射器将查询结果集映射到用户自定义类中
- update:执行增、删、改,返回更新行数
- batchUpdate(sql, List<Object[]>:可以批量插入记录
//实例化JdbcTemplate类,传入dataSource对象
JdbcTemplate template = new JdbcTemplate(dataSource);
/********************** 查询单条数据,返回Map *************************/
String sql = "SELECT * FROM DEPT WHERE DEPTNO = ?";
Map<String, Object> result = template.queryForMap(sql,10);
/*********************** 查询多条数据,返回List<Map>*********************/
String sql = "SELECT * FROM DEPT";
List<Map<String, Object>> lists = template.queryForList(sql);
/************************查询单条数据,返回实体对象************************/
String sql = "SELECT * FROM DEPT WHERE DEPTNO = ?";
//指定数据表所对应的实体类
RowMapper<Dept> rowMapper = new BeanPropertyRowMapper<Dept>(Dept.class);
Dept dept = template.queryForObject(sql, rowMapper, 10);
if (dept != null) {
System.out.println(dept.getDeptno() + "\t" + dept.getDname()
+ "\t" + dept.getLoc());
}
/**************** 查询多条数据,返回List,泛型为实体对象 ************************/
String sql = "SELECT * FROM DEPT";
RowMapper<Dept> rowMapper = new BeanPropertyRowMapper<Dept>(Dept.class);
List<Dept> lists = template.query(sql, rowMapper);
if (lists != null) {
for (Dept item : lists)
System.out.println(item.getDeptno() + "\t" + item.getDname()
+ "\t" + item.getLoc());
}
/********************** 统计记录数量 ************************/
String sql = "SELECT COUNT(*) as 人数 FROM DEPT";
int result = template.queryForObject(sql, Integer.class);
System.out.println(result);
/************************ 增加操作 *****************************/
String sql = "INSERT INTO DEPT(DEPTNO, DNAME, LOC) VALUES( ?, ?, ? )";
int cnt = template.update(sql, new Object[] { 50, "中国分部", "中国" });
/************************ 删除操作 ****************************/
String sql = "DELETE FROM DEPT WHERE DEPTNO = ?";
cnt = template.update(sql, new Object[] { 50 });
注意事项:
- 使用BeanProperytRowMapper要求sql数据查询出来的列和实体属性需要一一对应。如果数据中列明和属性名不一致,在sql语句中需要用as重新取一个别名
- 使用JdbcTemplate对象不能获取关联对象
- 查询结果为空时,Spring不会返回null,而是抛出org.springframework.dao.EmptyResultDataAccessException异常
JdbcDaoSupport类
public class GenericDaoImpl extends JdbcDaoSupport implements GenericDao {
@Autowired
public void setDataSource(DriverManagerDataSource dataSource) {
super.setDataSource(dataSource);
}
}
------------------------------------------------------------------------------------------------
//使自己的dao类直接或间接继承JdbcDaoSupport类,传入dataSource对象
@Repository("deptDao")
public class DeptDaoImpl extends GenericDaoImpl implements DeptDao {
//可直接使用该方法获取JdbcTemplate对象
this.getJdbcTemplate();
}
注:Autowired注解可以实现对方法形参的自动装配。
@Autowired将查找被标注的方法的入参类型的Bean,并调用方法自动注入
Spring事务管理
Spring的声明式事务管理策略
Spring的事务管理建立在AOP基础之上,其本质是对目标方法执行前后进行拦截,在目标方法开始执行之前加入事务,在执行完目标方法之后根据执行情况(执行成功则提交,收到异常信息则回滚)处理事务。事务管理本身就是一个典型的AOP切面。
优点:代码耦合程度低,复用性强。
注意:实施事务的方法的修饰符必须是public,其它private、static、final均不可,否则不能使用AOP动态代理启动事务
1.配置Spring事务管理
<aop:aspectj-autoproxy />
<context:component-scan base-package="com" />
<!--配置事务管理器-->
<bean id="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!—为事务管理器注册注解驱动器-->
<tx:annotation-driven transaction-manager="txManager"/>
2.在service中加入事务控制
@Service("deptService")
//加入开启事务注解
@Transactional
public class DeptServiceImpl extends GenericServiceImpl implements DeptService {
@Autowired
private DeptDao deptDao;
public DeptDao getDeptDao() {
return deptDao;
}
public void setDeptDao(DeptDao deptDao) {
this.deptDao = deptDao;
}
//对不涉及写数据库写入操作的方法,可加入只读属性以提高速度
@Transactional(readOnly = true)
public List<Dept> findAll() {
return this.deptDao.findAll();
}
public void add() {
Dept d1 = new Dept(50, "中国销售部", "济南");
Dept d2 = new Dept(50, "中国研发部", "北京");
this.deptDao.insert(d1);
this.deptDao.insert(d2);
}
}
@Transactional注解常用属性
属性 | 类型 | 默认值 | 说明 |
---|---|---|---|
propagation | Propagation枚举 | REQUIRED | 事务传播属性 |
isolation | isolation枚举 | DEFAULT | 指定事务隔离级别。取值有ISOLATION_DEFAULT(默认值,使用数据库默认的事务隔离级别)、READ_UNCOMMITTED、READ_COMMITTED、REPEATABLE_READ、SERIALIZABLE。 |
readOnly | boolean | false | 是否只读。”只读事务”提示数据库驱动程序和数据库系统,这个事务并不包含更改数据的操作,JDBC驱动程序和数据库可以根据这种情况对该事务进行一些特定的优化,不启动数据库锁。 |
timeout | int | -1 | 指定事务超时时间(以秒为单位),-1意味着不超时。 |
rollbackFor | Class[] | {} | 指定触发事务回滚的异常类(应使用全限定类名),该属性可指定多个异常类,多个异常类之间以英文逗号隔开。 |
rollbackForClassName | String[] | {} | 需要回滚的异常类名 |
noRollbackFor | Class[] | {} | 指定不触发事务回滚的异常类(应使用全限定类名),该属性可指定多个异常类,多个异常类之间以英文逗号隔开。 |
noRollbackForClassName | String[] | {} | 不需要回滚的异常类名 |
事务传播属性
REQUIRED | 业务方法需要在一个事务中运行,如果方法运行时,已处在一个事务中,那么就加入该事务,否则自己创建一个新的事务.这是****spring****默认的传播行为****. |
---|---|
SUPPORTS | 如果业务方法在某个事务范围内被调用,则方法成为该事务的一部分,如果业务方法在事务范围外被调用,则方法在没有事务的环境下执行. |
MANDATORY | 只能在一个已存在事务中执行,业务方法不能发起自己的事务,如果业务方法在没有事务的环境下调用,就抛异常 |
REQUIRES_NEW | 业务方法总是会为自己发起一个新的事务,如果方法已运行在一个事务中,则原有事务被挂起,新的事务被创建,直到方法结束,新事务才结束,原先的事务才会恢复执行. |
NOT_SUPPORTED | 声明方法需要事务,如果方法没有关联到一个事务,容器不会为它开启事务.如果方法在一个事务中被调用,该事务会被挂起,在方法调用结束后,原先的事务便会恢复执行. |
NEVER | 声明方法绝对不能在事务范围内执行,如果方法在某个事务范围内执行,容器就抛异常.只有没关联到事务,才正常执行. |
NESTED | 如果一个活动的事务存在,则运行在一个嵌套的事务中.如果没有活动的事务,则按REQUIRED属性执行.它使用了一个单独的事务, 这个事务拥有多个可以回滚的保证点.内部事务回滚不会对外部事务造成影响, 它只对DataSourceTransactionManager 事务管理器起效. |
网友评论