前面写了这么久的持久层框架存储数据,今天来记录下 Spring 框架对于事物管理的配置,顺带记录下 Spring 框架与 Hibernate 和 Mybatis 这些持久层框架的整合。
Spring 为事务管理提供了一致的编程模版,在高层次建立了统一的事务抽象,不管用户选择 Spring JDBC、Hibernate、JPA还是选择 MyBatis,Spring 都可以让用户用统一的编程模型进行事务管理。这种统一处理的方式带来的好处是不可估量的,用户完全可以抛开事务管理的问题编写程序,并在 Spring 中通过配置完成事务的管理工作。
一、Spring事务管理实现类
Spring 将事务管理委托给底层具体的持久化框架来完成。因此,Spring 为不同的持久化框架提供了不同的 PlantformTransactionManager
接口的实现类。
事务类 | 说明 |
---|---|
org.springframework.jdbc.datasource.DataSourceTransactionManager | 使用Spring JDBC 或者 MyBatis 等基于 DataSource 数据源的持久化技术时,使用该事务管理器 |
org.springframework.orm.hibernateX.HibernateTemplate | 使用Hibernate X.0版本进行持久化时,使用该事务管理器 |
org.springframework.orm.jpa.JpaTransactionManager | 使用JPA进行持久化时候,使用该事务管理器 |
二、Spring JDBC 事务管理配置
Dao 层实现
public class ContactDaoImpl implements ContactDao {
private JdbcTemplate jdbcTemplate;
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
@Override
public Contact findObjectById(int id) throws Exception {
String sql = "select * from contact where id=?";
return jdbcTemplate.queryForObject(sql, new RowMapper<Contact>() {
@Override
public Contact mapRow(ResultSet rs, int rowNum) throws SQLException {
Contact contact = new Contact();
contact.setId(rs.getInt("id"));
contact.setName(rs.getString("name"));
contact.setBirthday(rs.getDate("birthday"));
return contact;
}
}, id);
}
@Override
public List<Contact> findAll() throws Exception {
String sql = "select * from contact";
return jdbcTemplate.query(sql, new RowMapper<Contact>() {
@Override
public Contact mapRow(ResultSet rs, int rowNum) throws SQLException {
Contact contact = new Contact();
contact.setId(rs.getInt("id"));
contact.setName(rs.getString("name"));
contact.setBirthday(rs.getDate("birthday"));
return contact;
}
});
}
@Override
public int insertObject(Contact contact) throws Exception {
String sql = "insert into contact (name, birthday) values (?, ?)";
return jdbcTemplate.update(sql, contact.getName(), contact.getBirthday());
}
@Override
public int updateObject(Contact contact) throws Exception {
String sql = "update contact set name = ?, birthday = ? where id = ?";
return jdbcTemplate.update(sql, contact.getName(), contact.getBirthday(), contact.getId());
}
@Override
public int deleteObjectById(int id) throws Exception {
String sql = "delete from contact where id=?";
return jdbcTemplate.update(sql, id);
}
}
Service 层实现
public class ContactServiceImpl implements ContactService {
private ContactDao contactDao;
public void setContactDao(ContactDao contactDao) {
this.contactDao = contactDao;
}
@Override
public Contact findObjectById(int id) throws Exception {
return contactDao.findObjectById(id);
}
@Override
public List<Contact> findAll() throws Exception {
return contactDao.findAll();
}
@Override
public int insertObject(Contact contact) throws Exception {
int count = contactDao.insertObject(contact);
return count;
}
@Override
public int updateObject(Contact contact) throws Exception {
return contactDao.updateObject(contact);
}
@Override
public int deleteObjectById(int id) throws Exception {
return contactDao.deleteObjectById(id);
}
}
<?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:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
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.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<context:property-placeholder location="jdbc.properties"></context:property-placeholder>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${driver}"></property>
<property name="jdbcUrl" value="${url}"></property>
<property name="user" value="${username}"></property>
<property name="password" value="${password}"></property>
<property name="initialPoolSize" value="${initialPoolSize}"></property>
<property name="minPoolSize" value="${minPoolSize}"></property>
<property name="maxPoolSize" value="${maxPoolSize}"></property>
<property name="maxIdleTime" value="${maxIdleTime}"></property>
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<constructor-arg ref="dataSource"></constructor-arg>
</bean>
<bean id="contactDao" class="com.ogemray.jdbc.dao.impl.ContactDaoImpl">
<property name="jdbcTemplate" ref="jdbcTemplate"></property>
</bean>
<bean id="contactService" class="com.ogemray.jdbc.service.impl.ContactServiceImpl">
<property name="contactDao" ref="contactDao"></property>
</bean>
<!--开始事务配置-->
<!--事务管理类-->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--事务增强配置-->
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="find*" read-only="true"/>
<tx:method name="*" read-only="false"/>
</tx:attributes>
</tx:advice>
<!--AOP配置-->
<aop:config>
<aop:pointcut id="pt" expression="execution(* com.ogemray.jdbc.service.*.*(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="pt"></aop:advisor>
</aop:config>
</beans>
注意: 只要将 jdbcTemplate
注入到 Dao 的实现层就能实现接下来的JDBC操作,同时需要注意的是,事务管理配置在 Service 层,所以不管是 Dao 层还是 Service 层,都要将异常往上抛,这样才能达到事务管理效果,如果在 Service 层或者下层进行错误抛出,则到不到事务管理效果。
三、Spring 与 MyBatis整合 事务管理配置
Dao 层接口
public interface ContactMapper {
public List<Contact> findAll() throws Exception;
public Contact findObjectById(int id) throws Exception;
public int insertObject(Contact contact) throws Exception;
public int updateObject(@Param("contact") Contact contact) throws Exception;
public int deleteObjectById(int id) throws Exception;
}
Mapper XML文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ogemray.mybatis.mapper.ContactMapper">
<resultMap id="contactMap" type="com.ogemray.mybatis.entity.Contact">
<id property="id" column="id"></id>
<result property="name" column="name"></result>
<result property="birthday" column="birthday"></result>
</resultMap>
<select id="findAll" resultMap="contactMap">
select * from contact
</select>
<select id="findObjectById" resultMap="contactMap">
select * from contact where id = #{id}
</select>
<insert id="insertObject"
parameterType="com.ogemray.mybatis.entity.Contact"
useGeneratedKeys="true"
keyProperty="id">
insert into contact (name, birthday) values (#{name}, #{birthday})
</insert>
<update id="updateObject">
update contact
<set>
<trim suffixOverrides=",">
<if test="contact.name != null">name = #{contact.name}, </if>
<if test="contact.birthday != null">birthday = #{contact.birthday}</if>
</trim>
</set>
where id = #{contact.id}
</update>
<delete id="deleteObjectById">
delete from contact where id = #{id}
</delete>
</mapper>
Service 层实现
public class ContactServiceImpl implements ContactService {
private ContactMapper contactMapper;
public void setContactMapper(ContactMapper contactMapper) {
this.contactMapper = contactMapper;
}
@Override
public List<Contact> findAll() throws Exception {
return contactMapper.findAll();
}
@Override
public Contact findObjectById(int id) throws Exception {
return contactMapper.findObjectById(id);
}
@Override
public int insertObject(Contact contact) throws Exception {
int count = contactMapper.insertObject(contact);
return count;
}
@Override
public int updateObject(Contact contact) throws Exception {
return contactMapper.updateObject(contact);
}
@Override
public int deleteObjectById(int id) throws Exception {
return contactMapper.deleteObjectById(id);
}
}
<?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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="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.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${driver}"></property>
<property name="jdbcUrl" value="${url}"></property>
<property name="user" value="${username}"></property>
<property name="password" value="${password}"></property>
<property name="initialPoolSize" value="${initialPoolSize}"></property>
<property name="minPoolSize" value="${minPoolSize}"></property>
<property name="maxPoolSize" value="${maxPoolSize}"></property>
<property name="maxIdleTime" value="${maxIdleTime}"></property>
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="mapperLocations" value="classpath*:com/ogemray/mybatis/mapper/*.xml"></property>
<property name="configLocation" value="classpath:mybaitis-config.xml"></property>
</bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.ogemray.mybatis.mapper"></property>
</bean>
<bean id="contactService" class="com.ogemray.mybatis.service.ContactServiceImpl">
<property name="contactMapper" ref="contactMapper"></property>
</bean>
<!--事务配置注入-->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--事务增强配置-->
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="find*" read-only="true"/>
<tx:method name="get*" read-only="true"/>
<tx:method name="*" read-only="false" no-rollback-for="java.lang.ArithmeticException"/>
</tx:attributes>
</tx:advice>
<!--配置事务及切点-->
<aop:config>
<aop:pointcut id="txPointcut" expression="execution(* com.ogemray.mybatis.service.*.*(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut" />
</aop:config>
</beans>
四、Spring 与 Hibernate整合 事务管理配置
Dao 层实现类
public class ContactDaoImpl implements ContactDao {
private SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
private Session getSession() {
return sessionFactory.getCurrentSession();
}
@Override
public List<Contact> findAll() throws Exception {
String sql = "from " + Contact.class.getSimpleName();
List<Contact> list = getSession().createQuery(sql).getResultList();
return list;
}
@Override
public Contact findById(int id) throws Exception {
return getSession().get(Contact.class, id);
}
@Override
public Serializable insertObject(Contact contact) throws Exception {
return getSession().save(contact);
}
@Override
public void updateObject(Contact contact) throws Exception {
getSession().update(contact);
}
@Override
public void deleteObject(Contact contact) throws Exception {
getSession().delete(contact);
}
}
Service 层实现
public class ContactServiceImpl implements ContactService {
private ContactDao contactDao;
public void setContactDao(ContactDao contactDao) {
this.contactDao = contactDao;
}
public List<Contact> findAll() throws Exception {
return contactDao.findAll();
}
public Contact findById(int id) throws Exception {
return contactDao.findById(id);
}
public Serializable insertObject(Contact contact) throws Exception {
Serializable serializable = contactDao.insertObject(contact);
return serializable;
}
public void updateObject(Contact contact) throws Exception {
contactDao.updateObject(contact);
}
public void deleteObject(Contact contact) throws Exception {
contactDao.deleteObject(contact);
}
}
<?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:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="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.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<context:property-placeholder location="jdbc.properties"></context:property-placeholder>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${driver}"></property>
<property name="jdbcUrl" value="${url}"></property>
<property name="user" value="${username}"></property>
<property name="password" value="${password}"></property>
<property name="initialPoolSize" value="${initialPoolSize}"></property>
<property name="minPoolSize" value="${minPoolSize}"></property>
<property name="maxPoolSize" value="${maxPoolSize}"></property>
<property name="maxIdleTime" value="${maxIdleTime}"></property>
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<!--<property name="configLocation" value="hibernate.cfg.xml"></property>-->
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL55Dialect</prop>
<prop key="hibernate.hbm2ddl.auto">validate</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">false</prop>
</props>
</property>
<property name="mappingLocations">
<list>
<value>classpath:com/ogemray/hibernate/entity/*.hbm.xml</value>
</list>
</property>
</bean>
<bean id="contactDao" class="com.ogemray.hibernate.dao.impl.ContactDaoImpl">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<bean id="contactService" class="com.ogemray.hibernate.service.ContactServiceImpl">
<property name="contactDao" ref="contactDao"></property>
</bean>
<!--事务配置-->
<bean id="txManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="find*" read-only="true"/>
<tx:method name="*" read-only="false"></tx:method>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="pt" expression="execution(* com.ogemray.hibernate.service.*.*(..))"></aop:pointcut>
<aop:advisor advice-ref="txAdvice" pointcut-ref="pt"></aop:advisor>
</aop:config>
</beans>
另外也可以在 Spring 中注入 HibernateTempate 来完成持久层操作
<bean id="hibernateTemplate" class="org.springframework.orm.hibernate5.HibernateTemplate">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<bean id="contactDao" class="com.ogemray.hibernate.dao.impl.ContactDaoImpl">
<property name="hibernateTemplate" ref="hibernateTemplate"></property>
</bean>
持久层代码修改
public class ContactDaoImpl implements ContactDao {
private HibernateTemplate hibernateTemplate;
public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {
this.hibernateTemplate = hibernateTemplate;
}
@Override
public List<Contact> findAll() throws Exception {
String sql = "from " + Contact.class.getSimpleName();
List<Contact> list = (List<Contact>) hibernateTemplate.find(sql);
return list;
}
@Override
public Contact findById(int id) throws Exception {
return hibernateTemplate.get(Contact.class, id);
}
@Override
public void updateObject(Contact contact) throws Exception {
hibernateTemplate.update(contact);
}
}
网友评论