Spring企业级程序设计 • 【第4章 Spring持久化层和事务管理】

时间:2023-03-10 00:27:03
Spring企业级程序设计 • 【第4章 Spring持久化层和事务管理】

全部章节   >>>>


本章目录

4.1 配置数据源资源

4.1.1 JdbcTemplate介绍

4.1.2通过ComboPooledDataSource创建数据源

4.1.3 通过Spring配置创建数据源

4.1.4 读取外部properties文件配置创建数据源

4.1.5 实践练习

4.2  JdbcTemplate的单表操作

4.2.1 通过JdbcTemplate模板对象修改数据

4.2.2 通过JdbcTemplate模板对象删除数据

4.2.3 通过JdbcTemplate模板对象查询数据

4.2.4 实践练习

4.3 Spring的事务管理

4.3.1 Spring事务管理的核心接口

4.3.1 事务属性的定义

4.3.2 XML方式配置AOP完成Spring事务管理

4.3.3 注解方式配置AOP完成Spring事务管理

4.3.4 实践练习

4.4 综合案例

4.4.1 需求说明

4.4.1 实现思路

4.4.2 实践练习

总结


4.1 配置数据源资源

4.1.1 JdbcTemplate介绍

JdbcTemplate简介

传统的JDBC操作方法比较繁琐,为了使JDBC更加易于使用,Spring框架整合了JDBC,以此建立一个JDBC存取框架。

JdbcTemplate对象包含五类方法:

Execute()方法:可以用于执行任何SQL语句,一般用于执行DDL语句。

update()方法:update()方法用于执行新增、修改和删除等语句。

batchUpdate()方法:batchUpdate()方法用于执行批处理相关语句。

query()方法及queryForXXX()方法:用于执行查询相关语句。

call()方法:用于执行存储过程、函数相关语句。

4.1.2通过ComboPooledDataSource创建数据源

在实际开发中,通过C3P0连接池配置来获取数据源是现在比较流行的做法。C3P0提供核心工具类:ComboPooledDataSource存储数据源连接池。

示例:通过编码式的方法来创建数据源,然后获取JdbcTemplate对象,操作数据库中的t00_book表。

Spring企业级程序设计 • 【第4章 Spring持久化层和事务管理】

4.1.3 通过Spring配置创建数据源

示例:使用Spring配置方式来获取数据源

	<!-- 开启注解扫描功能 -->
<context:component-scan base-package="com.mhys"></context:component-scan>
<!-- 将连接池注册到容器 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql://127.0.0.1:3306/mysql"></property>
<property name="user" value="root"></property>
<property name="password" value="1q2w3e"></property>
</bean>
<!-- 将JdbcTemplate对象注册到容器 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
@Override
public int insertBook(Book book) {
String sql = "insert into t00_book values (?,?,?,?,?)";
int row = template.update(sql,book.getBookId(),book.getBookName(),book.getAuthor(),book.getPages(),book.getFlag()); return row;
}

Spring企业级程序设计 • 【第4章 Spring持久化层和事务管理】

4.1.4 读取外部properties文件配置创建数据源

在企业开发中,程序员开发的代码会放到多套环境中运行,比如:开发环境,多套测试环境,准生产环境,生产环境等,这样的话,数据源的配置会经常的更改,为了便于维护,经常会将数据源的信息保存在.properties配置文件中

示例:读取外部properties配置文件来获取数据源

jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.jdbcUrl=jdbc:mysql://127.0.0.1:3306/mysql
jdbc.user=root
jdbc.password=1q2w3e
	<!-- 指定Spring容器读取db.properties文件 -->
<context:property-placeholder location="classpath:db.properties"/>
<!-- 将连接池注册到容器 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driverClass}"></property>
<property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
<property name="user" value="${jdbc.user}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>

4.1.5 实践练习

4.2  JdbcTemplate的单表操作

创建数据源的几种方式已经讲解完成,在后面的课程中都将使用读取外部properties文件的方式配置数据源。

Spring对数据库的操作在JDBC上面做了深层次的封装,使用Spring的注入功能,可以把DataSource注册到JdbcTemplate之中。

4.2.1 通过JdbcTemplate模板对象修改数据

示例:在MySQL数据库中创建t00_customer表,添加customerId、customerName、telphone和address四个字段,录入初始化数据;然后在applicationContext.xml配置文件中配置数据源;接着编写业务方法;最后执行业务方法,查看结果

@Repository("customerDao")
public class CustomerDaoImpl implements CustomerDao {
@Resource(name="jdbcTemplate")
private JdbcTemplate template; @Override
// 根据客户编号修改电话号码
public int modifyCustomerById(Customer customer) {
String telphone = customer.getTelphone();
String customerId= customer.getCustomerId();
String sql = "update t00_customer set telphone=? where customerId=?";
int row = template.update(sql, customer.getTelphone(), customer.getCustomerId());
return row;
}
}

Spring企业级程序设计 • 【第4章 Spring持久化层和事务管理】

4.2.2 通过JdbcTemplate模板对象删除数据

示例:通过JdbcTemplate模板对象根据客户编号删除一条客户信息

@Repository("customerDao")
public class CustomerDaoImpl implements CustomerDao {
// 原有代码省略
@Override
// 根据客户编号删除一条数据
public int deleteCustomerById(Customer customer) {
String customerId= customer.getCustomerId();
String sql = "delete from t00_customer where customerId=?";
int row = template.update(sql,customer.getCustomerId());
return row;
}
}

Spring企业级程序设计 • 【第4章 Spring持久化层和事务管理】

4.2.3 通过JdbcTemplate模板对象查询数据

通过JdbcTemplate模板对象根据客户编号查询一条客户信息

public Customer getCustomerById(String customerId) {
String sql =
"select customerId,customerName,telphone,address from t00_customer where customerId=?";
Customer customerTemp = template.queryForObject(sql,
new RowMapper<Customer>(){
@Override
public Customer mapRow(ResultSet rs, int arg1)
throws SQLException {
Customer customer = new Customer();
customer.setCustomerId(rs.getString("customerId"));
customer.setCustomerName(rs.getString("customerName"));
customer.setTelphone(rs.getString("telphone"));
customer.setAddress(rs.getString("address"));
return customer;
}
},
customerId); return customerTemp;
}

Spring企业级程序设计 • 【第4章 Spring持久化层和事务管理】

4.2.4 实践练习

4.3 Spring的事务管理

4.3.1 Spring事务管理的核心接口

学习Spring事务管理需要了解Spring事务管理涉及的接口,如果对整个接口框架有个大体了解会非常有利于学习Spring事务管理。

Spring事物管理高层抽象主要包括3个接口:PlatformTransactionManager(事务管理器)、TransactionDefinition(事物定义信息)和TransactionStatus(事物具体运行状态)。

Spring企业级程序设计 • 【第4章 Spring持久化层和事务管理】

Spring事务管理器的接口是org.springframework.transaction.PlatformTransactionManager,通过这个接口,Spring为各个平台如JDBC、Hibernate等都提供了对应的事务管理器,但是具体的实现是各个平台自己的事情。

事务管理器派生类型

对应持久层版本

org.springframework.jdbc.datasource.DataSourceTransactionManager

使用Spring JDBC或者MyBatis时使用

org.springframework.orm.hibernate3.HibernateTransactionManager

使用Hibernate3.0时使用

org.springframework.orm.jpa.JpaTransactionManager

使用JPA时使用

org.springframework.transaction.jta.JtaTransactionManager

使用JTA时使用

4.3.1 事务属性的定义

事务属性可以理解成事务的一些基本配置,描述了事务策略如何应用到方法上。事务属性包含了5个方面。

Spring企业级程序设计 • 【第4章 Spring持久化层和事务管理】

最常用的传播行为是PROPAGATION_REQUIRED传播行为,表示当前方法必须运行在事务中。如果当前事务存在,方法将会在该事务中运行。否则,会启动一个新的事务

4.3.2 XML方式配置AOP完成Spring事务管理

Spring提供了对事务控制的实现。用户如果想用Spring的声明式事务管理,只需要在配置文件中配置即可; 不想使用时直接移除配置,这个实现了对事务控制的最大程度的解耦。

示例:通过Spring事务管理,模拟银行转账的功能。

@Repository("t00_accountDao")
public class T00_accountDaoImpl implements T00_accountDao {
@Resource(name="jdbcTemplate")
private JdbcTemplate template; @Override
public void increaseMoney(String accountid, double money) {
String sql = "update t00_account set money=money+? where accountid=?";
template.update(sql, money, accountid);
}
@Override
public void decreaseMoney(String accountid, double money) {
String sql = "update t00_account set money=money-? where accountid=?";
template.update(sql, money, accountid);
}
}
@Service("t00_accountService")
public class T00_accountServiceImpl implements T00_accountService {
@Resource(name="t00_accountDao")
private T00_accountDao t00_accountDao; @Override
public void transferMoney(String from, String to, double money) {
t00_accountDao.decreaseMoney(from, money);
t00_accountDao.increaseMoney(to, money);
}
}
<!-- 事务核心管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean> <!-- 配置事务通知 -->
<tx:advice transaction-manager="transactionManager" id="txAdvice">
<tx:attributes>
<tx:method name="*Money" isolation="DEFAULT" read-only="false" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice> <!-- 配置织入 -->
<aop:config>
<aop:pointcut expression="execution(* com.mhys.demo.service..*ServiceImpl.*Money(..))" id="txPointcut"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/>
</aop:config>

4.3.3 注解方式配置AOP完成Spring事务管理

在实际开发中,注解方式配置AOP事务也是常见的一种方式,只需要在配置文件中,开启注解管理AOP事务的驱动,在通过@Transactional注解就实现了声明式事务的管理。

示例:通过注解方式配置AOP事务,模拟银行转账的功能。

@Service("t00_accountService")
@Transactional
public class T00_accountServiceImpl implements T00_accountService {
@Resource(name="t00_accountDao")
private T00_accountDao t00_accountDao; @Override
public void transferMoney(String from, String to, double money) {
t00_accountDao.decreaseMoney(from, money);
// 增减异常
int i= 1/0;
t00_accountDao.increaseMoney(to, money);
}
}
<!-- 配置数据源 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${db.driverClass}"></property>
<property name="jdbcUrl" value="${db.jdbcUrl}"></property>
<property name="user" value="${db.user}"></property>
<property name="password" value="${db.password}"></property>
</bean>
<!-- 配置JdbcTemplate对象 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 配置事务核心管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 开启注解方式管理AOP事务 -->
<tx:annotation-driven />

@Transactional注解可以作用于接口、接口方法、类以及类方法上。当作用于类上时,该类的所有public方法将都具有该类型的事务属性,同时也可以在方法级别使用该标注来覆盖类级别的定义。

4.3.4 实践练习

4.4 综合案例

4.4.1 需求说明

根据本章所学知识,开发一个简易的学生信息模块,实现学生信息录入功能、学生信息删除功能以及学生信息查询功能。

要求:

使用外部properties文件获取数据源。

使用Template对象操作数据库。

使用注解方式开启事务管理。

Spring企业级程序设计 • 【第4章 Spring持久化层和事务管理】

4.4.1 实现思路

需求说明解决思路:

创建学生表,并创建学生实体类。

在applicaioinContext.xml配置文件中开启注解扫描、配置数据源、注册JdbcTemplate对象、配置事务核心管理器和开启注解方式管理AOP事务。

创建学生数据访问接口及实现类。

创建学生业务接口类及实现类。

编写主方法完成业务接口方法调用,并模拟异常回滚。

4.4.2 实践练习

总结

JdbcTemplate对象主要提供的五类方法。

  • Execute()方法:可以用于执行任何SQL语句,一般用于执行DDL语句。
  • update()方法:update()方法用于执行新增、修改以及删除等语句。
  • batchUpdate()方法:batchUpdate()方法用于执行批处理相关语句。
  • query()方法及queryForXXX()方法:用于执行查询相关语句。
  • call()方法:用于执行存储过程、函数相关语句。

通过ComboPooledDataSource创建数据源、通过Spring配置创建数据源和读取外部properties文件配置创建数据源