我们一般说的事务是来源于关系数据库,当有数据持久化需求时一般都需要事务控制。
关系数据库:支持事务控制,mysql数据库存储引擎为InnoDB支持事务,存储引擎为MyIsam不支持事务。
jdbc:支持事务控制,设置CommitAuto(false)
Hibernate:支持事务,使用session.beginTransaction(),再session.getTransaction().commit()提交事务
spring如果控制事务:由于使用hibernate,spring对Hibernate中session进行管理,支持事务。
spring针对持久层框架提供了模板类封装数据库操作方法:
1、可以简化数据访问的开发
2、支持事务控制,spring对Hibernate中session进行管理
spring提供了很多模板:
1、JdbcTemplate,针对jdbc操作数据库模板,相当于DbUtil
2、HibernateTemplate,针对Hibernate操作数据库模板。
spring-orm-4.2.4.RELEASE.jar:spring针对orm框架整合包
spring-tx-4.2.4.RELEASE.jar:spring提供事务管理的包
spring-jdbc-4.2.4.RELEASE.jar:spring提供jdbc操作方法包,此包为事务控制的基础包
dao实现类继承HibenrateDaoSupport(选择hibernate对应版本)
public class CustomerTestDaoImpl extends HibernateDaoSupport implements CustomerTestDao {
@Override
public CstCustomer findCustomerById(Long custId) {
return this.getHibernateTemplate().get(CstCustomer.class, custId);
}
@Override
public void insert(CstCustomer cstCustomer) {
this.getHibernateTemplate().save(cstCustomer);
}
}
直接运行报错:
‘sessionFactory’ or ‘hibernateTemplate’ is required
由于dao继承HibernateDaoSupport运行需要‘sessionFactory’或‘hibernateTemplate’。
解决:
将’sessionFactory’ or ‘hibernateTemplate’注入到dao中。
<context:property-placeholder location="classpath:db.properties"/>
<bean id="customerTestDao" class="cn.itcast.crm.dao.impl.CustomerTestDaoImpl">
<property name="hibernateTemplate" ref="hibernateTemplate"/>
bean>
<bean id="hibernateTemplate" class="org.springframework.orm.hibernate5.HibernateTemplate">
<property name="sessionFactory" ref="sessionFactory">property>
bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
bean>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driver}" />
<property name="jdbcUrl" value="${jdbc.url}" />
<property name="user" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
bean>
db.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/crm_spring
jdbc.username=root
jdbc.password=123456
运行报错
Unable to locate persister: cn.itcast.crm.domain.CstCustomer
CstCustomer不是一个被hibenate管理的实体类型。
解决:
在创建SessionFacotry时候加载Hibenate 映射文件:
注意:hibernate.cfg.xml中不用配置数据库连接参数,因为spring管理数据源。
<context:property-placeholder location="classpath:db.properties"/>
<bean id="customerTestDao" class="cn.itcast.crm.dao.impl.CustomerTestDaoImpl">
<property name="sessionFactory" ref="sessionFactory"/>
bean>
<bean id="hibernateTemplate" class="org.springframework.orm.hibernate5.HibernateTemplate">
<property name="sessionFactory" ref="sessionFactory">property>
<property name="checkWriteOperations" value="false"/>
bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="configLocations" value="classpath:hibernate/hibernate.cfg.xml"/>
bean>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driver}" />
<property name="jdbcUrl" value="${jdbc.url}" />
<property name="user" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
bean>
private ApplicationContext applicationContext;
@Before
public void setUp(){
applicationContext = new ClassPathXmlApplicationContext("bean.xml");
}
//测试HibernateTemplate查询方法
@Test
public void test1() {
CustomerTestDao customerTestDao = (CustomerTestDao) applicationContext.getBean("customerTestDao");
CstCustomer customer = customerTestDao.findCustomerById(97l);
//System.out.println(customer);
}
可查,运行成功
//测试HibernateTemplate插入方法
@Test
public void test2() {
CustomerTestDao customerTestDao = (CustomerTestDao) applicationContext.getBean("customerTestDao");
CstCustomer customer = new CstCustomer();
customer.setCustName("詹姆斯");
customerTestDao.insert(customer);
System.out.println(customer);
}
运行报错:
org.springframework.dao.InvalidDataAccessApiUsageException: Write operations are not allowed in read-only mode (FlushMode.MANUAL): Turn your Session into FlushMode.COMMIT/AUTO or remove ‘readOnly’ marker from transaction definition.
原因:
1、当前事务控制没有交给spring托管,spring进行事务控制,session刷新数据的模式为只读。
2、要使用HibernateTemplate,继承HibernateDaoSupport,HibernateTemplate方法中对插入操作、更新操作、删除操作默认使用事务控制。HibernateTemplate类检查session的刷新数据的模式,如果为只读的报错。
解决方案:
1、spring进行事务控制
2、HibernateTemplate不检查session的刷新数据的模式(当前先使用此方式)
由于dao继承HibernateDaoSupport运行需
要’sessionFactory’或’hibernateTemplate’,
解决方案:
1、向dao注入’hibernateTemplate’
2、向dao注入’sessionFactory’
建议注入’hibernateTemplate’,灵活配置’hibernateTemplate’属性值。