第一篇:《Spring4纯注解启动》的博客https://my.oschina.net/u/1757198/blog/815940
第二篇:《SpringSecurity安全性框架实战》的博客https://my.oschina.net/u/1757198/blog/827628
大家好,继前面两篇文章之后,今天跟大家分享一下注解版的Spring4Hibernate实战,以及对事务的控制。本demo基于第一篇文章的基础上实现的。之后我会开放项目的git地址。
目录:(红色)
DbConfig:
package com.spittr.config;
import java.util.Properties;
import javax.sql.DataSource;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.hibernate4.HibernateTransactionManager;
import org.springframework.orm.hibernate4.LocalSessionFactoryBean;
/**
* 数据库连接配置
* 实现事务
* @author zoe
* 2017年2月9日
*/
@Configuration
public class DbConfig {
/**
* 数据库连接
* jdbc驱动
* @return
*/
@Bean
public DataSource developDataSource(){
DriverManagerDataSource ds = new DriverManagerDataSource();
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost:3306/app?characterEncoding=utf8");
ds.setUsername("root");
ds.setPassword("zoe13120");
return ds;
}
/**
* 装配sessionFactory
* @param dataSource
* @return
*/
@Bean
public LocalSessionFactoryBean sessionFactory(DataSource dataSource){
LocalSessionFactoryBean sfb = new LocalSessionFactoryBean();
sfb.setDataSource(dataSource);
sfb.setPackagesToScan("com.spittr.web.model");
Properties properties = new Properties();
properties.setProperty("hibernate.dialect","org.hibernate.dialect.MySQLDialect");
properties.setProperty("hibernate.show_sql","true");
properties.setProperty("hibernate.format_sql","false");
sfb.setHibernateProperties(properties);
return sfb;
}
/**
* 装配hibernat事务管理器
* @param sessionFactory
* @return
*/
@Bean
public HibernateTransactionManager hibernateTransactionManager(SessionFactory sessionFactory){
HibernateTransactionManager htm = new HibernateTransactionManager(sessionFactory);
return htm;
}
}
WebConfig:
package com.spittr.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
/**
* web启动配置文件
* @author zoe
*
*/
@Configuration
@EnableWebMvc
@ComponentScan("com.spittr.web")
@EnableTransactionManagement
public class WebConfig extends WebMvcConfigurerAdapter {
@Bean
public ViewResolver viewResolver(){
InternalResourceViewResolver resolver = new InternalResourceViewResolver();//jsp视图解析器
resolver.setPrefix("/WEB-INF/view/");
resolver.setSuffix(".jsp");
resolver.setExposeContextBeansAsAttributes(true);
return resolver;
}
/**
* 配置静态资源的处理
* 将请求交由Servlet处理,不经过DispatchServlet
*/
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer){
configurer.enable();
}
}
在这个类上一定要加@EnableTransactionManagement注解,否则事务无法开启。
将这两个类配置好,tomcat应该就可以启动了。剩下的就是创建Repository,然后再Repository上配置事务。
HibernateRepository:
package com.spittr.web.repository;
import org.hibernate.Session;
/**
* hibernate仓库
* @author zoe
* 2017年2月9日
* @param <T>
*/
public interface HibernateRepository<T> {
public Session currentSession();
/**
* 查询对象通过ID
* @param clazz
* @param id
* @return
*/
public T queryEntityById(Class<T> clazz,String id);
/**
* 保存&更新对象
* @param t
*/
public void saveOrUpdateEntity(T t);
}
HibernateRepositoryImpl:
package com.spittr.web.repository;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Repository
@Transactional
@SuppressWarnings("unchecked")
public class HibernateRepositoryImpl<T> implements HibernateRepository<T> {
@Autowired
private SessionFactory sessionFactory;
@Override
public Session currentSession() {
return sessionFactory.getCurrentSession();
}
@Override
@Transactional(readOnly=true)
public T queryEntityById(Class<T> clazz,String id) {
return (T) currentSession().get(clazz, id);
}
@Override
@Transactional(propagation=Propagation.REQUIRED)
public void saveOrUpdateEntity(T t) {
currentSession().saveOrUpdate(t);
}
}
注意,在这个实现类中,是控制事务的关键。在@Transactional这个注解里,有多个属性可以配置,如propagation控制的是“传播行为”,readOnly控制的是“只读”等;
数据库连接成功,Repository事务已加入,剩下的就是具体的业务代码。这一块我写的比较简单,测试用。
有一点要注意,我整合出了一个新的注解类@ServiceWithTransaction,主要内容是Spring的@Service加上@Transactional。
package com.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
/**
* 带事务控制的service注解
* @author zoe
* 2017年2月9日
*/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
@Transactional
public @interface ServiceWithTransaction {
String value() default "";
}
控制层我就不提供了,大家随便找一个controller就可以了。
RepositoryService:
package com.spittr.web;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.annotation.ServiceWithTransaction;
import com.spittr.web.model.SysMenu;
import com.spittr.web.repository.HibernateRepository;
/**
*
* @author zoe
* 2017年2月9日
*/
@ServiceWithTransaction
//或者如下
//@Service
//@Transactional
public class RepositoryService {
@Autowired
private HibernateRepository<SysMenu> hibernateRepository;
public String repository() {
SysMenu entity = hibernateRepository.queryEntityById(SysMenu.class,"1");
SysMenu t = new SysMenu();
t.setId("134");
hibernateRepository.saveOrUpdateEntity(t);
SysMenu t2 = new SysMenu();
t2.setId("138");
hibernateRepository.saveOrUpdateEntity(t2);
return "repository";
}
}