• SSH组合之Spring3整合Hibernate4(一)


    1、在Spring里,Hibernate的资源要交给Spring来管理。Hibernate及其SessionFactory等只是Spring一个特殊的Bean,由Spring负责实例化与销毁。

    由于Hibernate全部交给Spring来管理,HIbernate不再需要自己的配置文件,所有的参数都在Spring的src/applicationContext.xml中配置

    2、详细步骤

    (1)新建web project

    -->Add Spring Capabilities(勾选前5个)

    -->Add Hibernate Capabilities(core、advanced support)

    -->配置文件选择放在Spring的applicationContext.xml

    -->配置DataSource

    jdbc:mysql://localhost:3306/hibernate?characterEncoding=UTF-8

    com.mysql.jdbc.Driver

    -->不创建Session Factorry class

    -->finish !

    (2)加入mysql的驱动lib,否则“Cannot load JDBC driver class 'com.mysql.jdbc.Driver”

    (3)applicationContext.xml

    配置数据库的dataSource

    配置sessionFactory

    配置Dao层

    配置Spring的Hibernate事务管理器 (Aop:aspect)

    配置事务的传播特性

    配置事务的管理位置(Aop:pointcut)

    <?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: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-2.5.xsd 
               http://www.springframework.org/schema/tx 
               http://www.springframework.org/schema/tx/spring-tx-2.5.xsd 
               http://www.springframework.org/schema/aop 
                http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">
    
        <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
            <property name="driverClassName" value="com.mysql.jdbc.Driver">
            </property>
            <property name="url"
                value="jdbc:mysql://localhost:3306/ztravel?characterEncoding=UTF-8">
            </property>
            <property name="username" value="root"></property>
            <property name="password" value="123456"></property>
        </bean>
        <bean id="sessionFactory"
            class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
            <property name="dataSource">
                <ref bean="dataSource" />
            </property>
            <property name="hibernateProperties">
                <props>
                    <prop key="hibernate.dialect">
                        org.hibernate.dialect.MySQLDialect
                    </prop>
                    <prop key="hibernate.show_sql">true</prop>
                    <prop key="hibernate.current_session_context_class">
                        org.springframework.orm.hibernate4.SpringSessionContext
                    </prop>
                    <prop key="hibernate.hbm2ddl.auto">update</prop>
                    <!-- 解决nested exception is org.hibernate.HibernateException: Error applying 
                        BeanValidation relational constraints -->
                    <prop key="javax.persistence.validation.mode">none</prop>
                </props>
            </property>
            <!-- 配置实体类,与数据库的表有关 -->
            <property name="annotatedClasses">
                <list>
                    <!-- 注意大小写 -->
                    <value>com.z.hibernate.bean.Agency</value>
                    <value>com.z.hibernate.bean.Discount</value>
                    <value>com.z.hibernate.bean.Group</value>
    
                    <value>com.z.hibernate.bean.Manager</value>
    
                </list>
            </property>
        </bean>
    
        <!-- 配置Dao ,class是实现接口的类-->
        <bean id="dao" class="com.z.hibernate.dao.impl.DaoImpl">
            <property name="sessionFactory" ref="sessionFactory"></property>
        </bean>
        
            <!-- struts2的Action -->
        <!-- scope默认为singleston,这里一定要设置 成prototype。这样浏览器每次请求一次,spring都会生成一个新的Action对象-->
        <bean id="viewAction" scope="prototype" class="com.z.strust2.action.ViewAction">
        <!--iDao是操作数据库的接口,dao是一个bean的id名  -->
        <property name="iDao" ref="dao"></property>
        </bean>
        
        <!-- 配置事务管理Spring的Hibernate事务管理器 (Aop:aspect) 责任:负责session的开启和关闭,负责事物的开启,管理和回滚(遇到RunTimeException会自动回滚,其他异常不会) -->
        <bean id="txManager"
            class="org.springframework.orm.hibernate4.HibernateTransactionManager">
            <property name="sessionFactory" ref="sessionFactory" />
            <property name="dataSource" ref="dataSource" />
        </bean>
    
        <!-- 配置事务的传播特性 -->
        <tx:advice id="txAdvice" transaction-manager="txManager">
            <tx:attributes>
                <tx:method name="save*" propagation="REQUIRED" />
                <tx:method name="add*" propagation="REQUIRED" />
                <tx:method name="create*" propagation="REQUIRED" />
                <tx:method name="insert*" propagation="REQUIRED" />
                <tx:method name="update*" propagation="REQUIRED" />
                <tx:method name="merge*" propagation="REQUIRED" />
                <tx:method name="del*" propagation="REQUIRED" />
                <tx:method name="remove*" propagation="REQUIRED" />
                <tx:method name="put*" propagation="REQUIRED" />
                <tx:method name="use*" propagation="REQUIRED" />
                <!--hibernate4必须配置为开启事务 否则 getCurrentSession()获取不到 -->
                <tx:method name="get*" propagation="REQUIRED" read-only="true" />
                <tx:method name="count*" propagation="REQUIRED" read-only="true" />
                <tx:method name="find*" propagation="REQUIRED" read-only="true" />
                <tx:method name="list*" propagation="REQUIRED" read-only="true" />
                <tx:method name="*" read-only="true" />
            </tx:attributes>
        </tx:advice>
    
        <!-- 配置事务的管理位置(Aop:pointcut) 。在哪些地方切入事务的管理 -->
        <aop:config expose-proxy="true">
            <!-- 只对业务逻辑层实施事务 -->
            <!-- 添加实现了接口的类到里面 -->
            <aop:pointcut id="txPointcut"
                expression="execution(* com.z.hibernate.dao..*.*(..)) OR execution(* com.xp.common..*.*(..))" />
            <!-- pointcut-ref的值要与 aop:pointcut的id一致 -->
            <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut" />
        </aop:config>
    </beans>

    需要注意的问题:

    1、execution(* com.dao..*.*(..))表示com.dao包里面的类都在事务管理范围之内,需要根据情况改动

    如果一个类有getSession().save(cat);类似操作,则必须被包含

    2、别忘了在annotatedClasses配置实体类

    3、如果需要根据2中的实体类自动建表,别忘了

    <prop key="hibernate.hbm2ddl.auto">update</prop>

    4、dao记得配置

    5、<!-- 解决nested exception is org.hibernate.HibernateException: Error applying BeanValidation relational constraints -->

    <prop key="javax.persistence.validation.mode">none</prop>

    6、在开发Spring的过程中,有时会出现Eclipse不能识别<tx:advice/>标签。 

    这个错误的原因是:我们在定义申明AOP的时候,没有加载schema。 

    7. cannot simultaneously fetch multiple bags  

    当一个实体对象中包含多于一个non-lazy获取策略时,比如@OneToMany,@ManyToMany或者@ElementCollection时,获取策略为(fetch = FetchType.EAGER)

    出现问题的原因:

    当(fetch = FetchType.EAGER)多余一个时,持久框架抓取一方的对象时,同时又将多方的对象加载进容器中,多方又可能关联其它对象,Hibernate实现的JPA,默认最高抓取深度含本身级为四级(它有个属性配置是0-3),若多方(第二级)存在重复值,则第三级中抓取的值就无法映射,就会出现 multiple bags。

    解决方法:

    1、将(fetch = FetchType.EAGER)改为(fetch = FetchType.LAZY)

    2、将List修改成Set集合,即推荐@ManyToMany或@OneToMany的Many方此时用Set容器来存放,而不用List集合。

    3、改变FetchMode为@Fetch(FetchMode.SUBSELECT),即发送另外一条select语句抓取前面查询到的所有实体对象的关联实体。

    4、在对应的属性上添加@IndexColumn,该注解允许你指明存放索引值的字段,目的跟Set容器不允许重复元素的道理一样。

    推荐的处理办法:

    方法2;

    方法3和方法4是Hibernate特有的,非JPA标准;

    如果可以用方法1,那就不会出现这个问题。

     8、org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.life.hibernate.bean.Coupon.users, no session or session was closed

    方法:在onttomany端设置fetch=FetchType.EAGER

    9、org.hibernate.PersistentObjectException: detached entity passed to persist: com.life.hibernate.bean.Store

    是级联配置不对:
    把cascade = CascadeType.ALL 改成 cascade=CascadeType.REFRESH 。

    3、接口IDao

    package com.z.hibernate.dao;
    import java.util.List;
    public interface IDao<T> {
    
        /**
         * 增加
         * @param object
         */
        public void save(T object);
        /**
         * 删除
         * @param object
         */
        public void delete(T object);
        /**
         * 增加
         * @param object
         */
        public void update(T object);
        /**
         * 根据传进来的HQL语句更新,返回受影响行数
         * @param hql
         * @return
         */
        public int updateByQuery(String hql);
        /**
         * 查询
         * @param hql
         * @param parameter
         * @return
         */
        public List<T> list(String hql,Object... parameter);
        /**
         * 获取记录总数
         * @param hql
         * @param params
         * @return
         */
        public int getTotalCount(String hql,Object...params);
    }

    4、实现接口DaoImpl<T>

    package com.z.hibernate.dao.impl;
    
    import java.util.List;
    
    import org.hibernate.Query;
    import org.hibernate.Session;
    import org.hibernate.SessionFactory;
    
    import com.z.hibernate.dao.IDao;
    
    public class DaoImpl<T> implements IDao<T> {
        private SessionFactory sessionFactory;
    
        @Override
        public void save(T object) {
            // TODO Auto-generated method stub
            getSession().save(object);
        }
    
        @Override
        public void delete(T object) {
            // TODO Auto-generated method stub
            getSession().delete(object);
        }
    
        @Override
        public void update(T object) {
            // TODO Auto-generated method stub
            getSession().saveOrUpdate(object);
        }
    
        @Override
        public List<T> list(String hql, Object... parameter) {
            // TODO Auto-generated method stub
            Query query = getSession().createQuery(hql);
            if (parameter != null) {
                for (int i = 0; i < parameter.length; i++) {
                    query.setParameter(i, parameter[i]);
                }
            }
            List<T> list = query.list();
            return list;
        }
    
        @Override
        public int getTotalCount(String hql, Object... params) {
            // TODO Auto-generated method stub
            return 0;
        }
    
        public Session getSession() {
            return sessionFactory.getCurrentSession();
        }
    
        // 必须要有get-set,不然会Error creating bean with name 'sessionFactory' defined in
        // class path resource
        public SessionFactory getSessionFactory() {
            return sessionFactory;
        }
    
        public void setSessionFactory(SessionFactory sessionFactory) {
            this.sessionFactory = sessionFactory;
        }
    
        @Override
        public int updateByQuery(String hql) {
            // TODO Auto-generated method stub
            int k = sessionFactory.getCurrentSession().createQuery(hql)
                    .executeUpdate();
            return k;
        }
    }

    需要注意的问题

    1、SessionFactory 必须要有get/set

    4、得到并调用Dao的方法

    注意

    IDao<Manager>是接口,在xml配置”dao“的bean的class是实现接口的类
            BeanFactory factory=new ClassPathXmlApplicationContext("applicationContext.xml");
            IDao<Manager> iDao=factory.getBean("dao",IDao.class);
            Manager manager=new Manager();
            manager.setM_account("11");
            manager.setM_pwd("gtg");
            iDao.save(manager);

    如果项目导入了struts2框架并进行了相关配置,则不需要通过factory.getBean("catDao",CatDao.class);这种方式获取对象

    Done!

  • 相关阅读:
    (转)把hadoop源码关联到eclipse工程
    windows 系统下git 的使用
    windows 系统下git 的安装
    windows 系统下TortoiseGit 的安装
    windows 安装 mysql
    windows 下 mySQL 镜像安装文件下载
    vs2012 有效产品密钥
    mac 安装 visual studio 配置
    mac 安装 nodeJs&npm 配置
    macOS Sierra 如何打开任何来源
  • 原文地址:https://www.cnblogs.com/xingyyy/p/3596246.html
Copyright © 2020-2023  润新知