zoukankan      html  css  js  c++  java
  • spring整合hibernate

    spring整合hibernate包括三部分:hibernate的配置、hibernate核心对象交给spring管理、事务由AOP控制 好处:

    • 由java代码进行配置,摆脱硬编码,连接数据库等信息更灵活
    • session等生命周期得到更好的控制,session和事务依赖注入到DAO中,更爽
    • 事务由AOP管理更加清晰,自动管理事务

    hibernate的配置

    spring提供了一个sessionfactory的实现,LocalSessionFactoryBean 通过在LocalSessionFactoryBean中set值来达到配置的效果 注意,LocalSessionFactoryBean有几种:

    • org.springframework.orm.hibernate5.LocalSessionFactoryBean
    • org.springframework.orm.hibernate4.LocalSessionFactoryBean
    • org.springframework.orm.hibernate3.LocalSessionFactoryBean

    他们的区别就是在不同版本的hibernate包中,根据自己的hibernate版本去选择

    @Configuration
    @PropertySource("classpath:/application.properties")
    public class HibernateConf {
     //Enviroment对象可以取到被@PropertySource标记的文件数据
     //通过拿到properties文件中的属性来摆脱硬编码
     @Autowired
     public Environment env;
    
     
     //DataSource对象是用来配置连接数据库的信息
     //在稍后配置LocalSessionFactoryBean会用到datasource来连接数据库
     @Bean
     public DataSource dataSource() throws ClassNotFoundException{
      DataSource ds=new DataSource();
      //通过Environment对象再Properties文件中拿到配置信息
      ds.setUsername(env.getProperty("dataSource.username","root"));
      ds.setPassword(env.getProperty("dataSource.password","null"));
      ds.setAddress(env.getProperty("dataSource.address"));
      ds.setDriver(env.getProperty("dataSource.driver"));
      return ds;
     }
     
     //LocalSessionFactoryBean同SessionBean
     //用来配置hibernate
     @Bean
     @Autowired
     public LocalSessionFactoryBean sessionFactory(DataSource dataSource){
      LocalSessionFactoryBean sessionFactory=new LocalSessionFactoryBean();
      sessionFactory.setDataSource(dataSource);
      //设置扫描orm对象锁崽的包
      sessionFactory.setPackagesToScan("weibo.po");
      Properties prop=new Properties();
      prop.setProperty("hibernate.dialect",env.getProperty("hibernate.dialect"));//设置hibernate方言
      prop.setProperty("hibernate.show_sql", env.getProperty("hibernate.show_sql"));//设置显示sql
      prop.setProperty("hibernate.format_sql",env.getProperty("hibernate.format_sql"));//格式化sql
      prop.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto"));//自动建表
      sessionFactory.setHibernateProperties(prop);
      return sessionFactory;
     }

    精髓是,摆脱硬编码,连接数据库的信息(username,password,driver,address....)通过spring提供的Enviroment对象去读取外置数据文件(application.properties)得到连接信息,这样子数据库配置就直接在application.properties中配置就可以了要注意的是,LocalSessionFactoryBean和SessionFactory并不是多态的关系,但是LocalSessionFactoryBean中持有一个SessionFactory对象,spring在运行期会自动实例化LocalSessionFactoryBean中的SessionFactory对象,所以我们从spring容器拿LocalSessionFactoryBean对象实际上是拿到了LocalSessionFactoryBean的SessionFactory

    session等交给spring容器

    把SessionFactory、Session、Transcation对象交给Spring容器管理

    • 更好的管理生命周期,避免资源浪费
    • 利用依赖注入,不再手动开启连接
    • 利用AOP管理事务,不再手动管理事务

    SessionFactory在刚才配置hibernate的时候已经标识为Bean了,就不用再配置了

     //session
     @Bean
     //request作用域+通过类实现代理
     @Scope(scopeName=WebApplicationContext.SCOPE_REQUEST,proxyMode=ScopedProxyMode.TARGET_CLASS)
     //自动装配已经装配好的SessionFactory
     @Autowired
     public Session session(SessionFactory sessionFactory){
       return sessionFactory.openSession();
     }
     
     //transaction
     @Bean
     @Scope(scopeName=WebApplicationContext.SCOPE_REQUEST,proxyMode=ScopedProxyMode.TARGET_CLASS)
     //自动装配已经装配好的Session
     @Autowired
     public Transaction transction(Session session){
       return session.beginTransaction();
     }

    这里有几个需要注意的地方

    • 设置好scope,作用域一般都是request或者是session,避免长期连接数据库
    • 设置好代理,因为要将Session和Transcation注入DAO中,DAO一般都是单例的,而Session和事务是短作用域的。所以要使用代理对象先注入到DAO中,待使用时再调用真正对象
    • 通过已经装配好的SessionFactory来开启Session
    • 通过已经装配好的Session来开启事务(才能达到session和transcation对象一一对应)

    事务通过AOP控制

    当不用AOP的时候,我们会写这样的代码

     public void crud() throws SQLException{
      try{
        //操作数据库的代码
        transaction.submit();//提交
      }catch(SQLException e){
        transaction.rollback();//回滚
        throw e;
      }finally{
        session.close();//关闭连接
      }
     }

    一般crud都需要有这几步:提交事务、出错时回滚事务、关闭连接 

    这种重复性,且无关业务逻辑的代码何不用aop完成呢
    
    
    当通过AOP管理事务的时候只需要
    • 设置curd为切点
    • 在切点处写一个环绕通知,在环绕通知中实现事务的几个步骤
    //声明切面
    @Aspect
    public class DAOAspect {
     //自动装配session和transcation
     @Autowired
     private Session session;
     @Autowired
     private Transaction transaction;
     //声明切点
     @Pointcut("execution(* *.dao.*.crud(*))")//这样子所有dao包下的crud方法都会被标记为切点
     public void crud(){}
     
     //在crud地方环绕通知
     @Around("crud()")
     public void aroundCrud(ProceedingJoinPoint p) throws Throwable{
       try{
         p.proceed();//执行crud动作
         transaction.commit();//提交事务
       }catch(Throwable e){
         transaction.rollback();//出错回滚
         throw e;
       }finally{
         session.close();//关闭连接
       }
     }
    }
    这样一看是不是方便多啦,从此事务管理只用写一次有几个需要注意的地方
    • p.proceed()一定要写,不写就不会调用切点(crud)的方法了,就像切点(crud)被拦截过滤了一样
    • throw e一定要写,因为aop实际就是一个代理对象,不然操作数据库错误了也不会抛出错误(错误被代理对象捕获catch处理了)
    • 不要在crud原方法中,提交事务、关闭连接了,不然aop层面会报错的(连接已关闭,事务已提交)
    • 因为session和transcation最小作用域都是请求级别的,所以不用担心自动装配进来的对象是不是原来那个

    查看原文:http://zswlib.com/2016/07/14/spring%e6%95%b4%e5%90%88hibernate/
  • 相关阅读:
    C# 实现 Snowflake算法生成唯一性Id
    kafka可视化客户端工具(Kafka Tool)的基本使用(转)
    docker 安装kafka
    Model类代码生成器
    使用docker 部署rabbitmq 镜像
    Vue 增删改查 demo
    git 提交代码到库
    Android ble蓝牙问题
    mac 配置 ssh 到git (Could not resolve hostname github.com, Failed to connect to github.com port 443 Operation timed out)
    okhttp
  • 原文地址:https://www.cnblogs.com/wewill/p/5671973.html
Copyright © 2011-2022 走看看