无XML配置,注解实现Spring4集成Hibernate4(含事务管理)
引言
借助Spring的DI的强大支持,通过注解的方式,无任何XML配置,即可轻松实现Spring4集成hibernate4框架进行数据库表的操作,更重要的没有事务的开始、关闭、会话连接的提交等烦琐代码,将工作重点放在业务逻辑开发上,真正提高工作效率。
1. 预先生成entity
无需xml,参考另一篇博客文章:https://blog.youkuaiyun.com/hills/article/details/99974062
2. 创建hibernate配置类
借助spring的DI特性,添加@Configuration注解,创建hibernate配置类,具体代码片断如下:
@Configuration
@EnableTransactionManagement
public class Hibernate4DBConfig {
@Bean
public LocalSessionFactoryBean sessionFactory(DataSource dataSource) {
LocalSessionFactoryBean sfb = new LocalSessionFactoryBean();
sfb.setDataSource(dataSource);
sfb.setPackagesToScan("cn.aoe.tech.ylin.sprmvcmock.entity.hiber");
Properties ps = new Properties();
ps.setProperty("hibernate.dialect", "org.hibernate.dialect.Oracle10gDialect");
sfb.setHibernateProperties(ps);
return sfb;
}
@Bean
public HibernateTransactionManager transactionManager(SessionFactory s) {
HibernateTransactionManager txManager = new HibernateTransactionManager();
txManager.setSessionFactory(s);
return txManager;
}
}
对于步骤2的另一种替代方案是实现TransactionManagementConfigurer接口及其覆盖方法:PlatformTransactionManager annotationDrivenTransactionManager();
代码片断如下:
@Configuration
@EnableTransactionManagement
public class Hibernate4DBConfig implements TransactionManagementConfigurer {
@Autowired
private SessionFactory sfact;
@Bean
public LocalSessionFactoryBean sessionFactory(DataSource dataSource) {
LocalSessionFactoryBean sfb = new LocalSessionFactoryBean();
sfb.setDataSource(dataSource);
sfb.setPackagesToScan("cn.aoe.tech.ylin.sprmvcmock.entity.hiber");
Properties ps = new Properties();
// 数据库方言,这里用的是oracle
ps.setProperty("hibernate.dialect", "org.hibernate.dialect.Oracle10gDialect");
sfb.setHibernateProperties(ps);
return sfb;
}
@Override
public PlatformTransactionManager annotationDrivenTransactionManager() {
HibernateTransactionManager txManager = new HibernateTransactionManager();
txManager.setSessionFactory(sfact);
return txManager;
}
}
要集成hibernate,主要是声明session factory和事务(如果没必要的话取open session,后续有说明)两大类,即相当于XML中以下配置的(仅列简要项):
<tx:annotation-driven transaction-manager=”transactionManager”>
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
<!—其他属性略-->
</props>
</property>
<property name="packagesToScan">
<list>
<value> cn.aoe.tech.ylin.sprmvcmock.entity.hiber </value>
</list>
</property>
</bean>
具体详细说明如下:
2.1 SessionFactory
大家知道,Hibernate的Session接口提供了基本的数据访问功能,如保存、更新、删除以及从数据库加载对象的功能。通过Hibernate的Session接口,应用程序的Repository能够满足所有的持久化需求。而获取Hibernate Session对象的标准方式是借助于Hibernate SessionFactory接口的实现类。通常SessionFactory主要负责Hibernate Session的打开、关闭以及管理。
这里使用Hibernate 4的话,需要使用org.springframework.orm.hibernate4中的LocalSessionFactoryBean。
为了简要说明,对于本例,session factory最精简的是仅配置了数据库方言和实体类所被扫描的包名。
这里把扫描的entity的包图贴一下:
2.2 关于@EnableTransactionManagement
此注解表示开启基于注解的事务管理功能。有三个属性:
-
proxyTargetClass:默认值为false,表示不是CGLIB代理。为true,表示使用CGLIB代理;
-
mode:默认值为AdviceMode.PROXY,表示走代理实现事务;如果以AOP(切面拦截器)实现事务,则设置为ASPECTJ;
-
order:默认值是Ordered.LOWEST_PRECEDENCE(实际为Integer.MAX_VALUE),表示如果有多个切面拦截器,事务的拦截器执行优先级最低。
2.3 关于事务管理
public HibernateTransactionManager transactionManager(SessionFactory s);
常用的事务管理有:JpaTransactionManager,DataSourceTransactionManager,HibernateTransactionManager,JdoTransactionManager等,它们都是PlatformTransactionManager接口的子类,毫无疑问我们这里用的是HibernateTransactionManager。
3. 数据访问类
3.1 接口的例子:
public interface MockLotusStatisticRepository {
public LotusStatistic findOne(String id);
public boolean Update(LotusStatistic lotusStatistic);
public boolean Add(LotusStatistic lotusStatistic);
}
3.2 接口实现类的例子:
@Repository
public class HibernateMockLotusStatisticRepository implements MockLotusStatisticRepository{
private SessionFactory sessionFactory;
@Autowired
public HibernateMockLotusStatisticRepository(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
private Session currentSession() {
// 如果不要求事务管理,则用sessionFactory.openSession();
Session currentSession = sessionFactory.getCurrentSession();
return currentSession;
}
@Override
@Transactional(readOnly=true)
public LotusStatistic findOne(String id) {
return (LotusStatistic) currentSession().get(LotusStatistic.class, id);
}
@Override
@Transactional(rollbackFor=Throwable.class)
public boolean Update(LotusStatistic lotusStatistic) {
sessionFactory.getCurrentSession().update(lotusStatistic);
return true;
}
@Override
@Transactional(rollbackFor=Throwable.class)
public boolean Add(LotusStatistic lotusStatistic) {
sessionFactory.getCurrentSession().save(lotusStatistic);
return true;
}
3.3 关于@Transactional
即起事务作用(如一旦有错误可以自动回滚)。
因为注解@Transactional就是迎合@EnableTransactionManagement而生的,可以标注在class上(所有public方法具有事务作用),也可以标注在某个方法上(即当前方法具有事务作用,本例以此说明)