• 关于SessionFactory的不同实现类分别通过getCurrentSession()方法 和 openSession() 方法获取的Session对象在保存对象时的一些区别


    一、单向多对一关联关系

      一)、使用LocalSessionFactoryBean类,即在applicationContext中配置的

    <!-- 配置SessionFactory 使用LocalSessionFactoryBean-->
        <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
            <property name="dataSource" ref="dataSource"></property>
            <property name="configLocation" value="classpath:hibernate.cfg.xml"></property>
            <property name="mappingLocations" >
                <list>
                    <value>classpath:com/zcd/hibernate/manyToOne/*.hbm.xml</value>
                    <value>classpath:com/zcd/hibernate/manyToOneBoth/*.hbm.xml</value>
                    <value>classpath:com/zcd/hibernate/oneToMany/*.hbm.xml</value>
                    <value>classpath:com/zcd/hibernate/oneToOneForeign/*.hbm.xml</value>
                    <value>classpath:com/zcd/hibernate/oneToOnePrimary/*.hbm.xml</value>
                </list>
            </property>
        </bean>

        ①、以上配置的这个SessionFactory 类的对象的getCurrentSession()方法获取的Session 对象

          先保存一端再保存多端:正常

          先保存多端再保存一端:异常

        ②、但是如果使用这个对象的openSession() 方法

          先保存一端再保存多端:正常

          先保存多端再保存一端:没有异常,但不能保存外键列

    ====================================================================

      二)、如果通过以下方式获取的SessionFactory ,我看了一下底层代码,如果没错的话这个SessionFactory 指的是SessionFactoryImpl 这个类。

        private SessionFactory sessionFactory;
        private Session session;
        private Transaction transaction;
        
        @Before
        public void init()
        {
            //创建一个Configuration对象:对应于hibernate的配置信息和对象关系映射
            Configuration configuration = new Configuration().configure();
            
            //创建一个ServiceRegistry对象,所有的hibernate配置和服务都要注册到这个对象中才有效
            ServiceRegistry serviceRegistry = 
                    new ServiceRegistryBuilder().applySettings(configuration.getProperties())
                    .buildServiceRegistry();
            
            //创建SessionFactory对象
            sessionFactory = configuration.buildSessionFactory(serviceRegistry);
            
            //创建Session
            session = sessionFactory.openSession();
    //        session = sessionFactory.getCurrentSession();
            
            //开启事务
            transaction = session.beginTransaction();
            System.out.println(transaction);
        }    

        ①、这个SessionFactory 类的对象的getCurrentSession()方法获取的Session对象

          先保存一端再保存多端:异常

          先保存多端再保存一端:异常

        ②、但是如果通过openSession()方法获取的Session对象,

          先保存一端再保存多端:正常

          先保存多端再保存一端:正常, 但是会多出UPDATE语句。

    =======================================================================

    总结:在保存单向多对一关联关系的对象的时候,最好是先保存一端,再保存多端,这样既可以提高数据库的性能,又可以减少异常的发生。

    二、一对一关联关系,基于主键映射。

    跟上面的一样两种方式获取不同的SessionFactory 的实现类的实例

      一)、LocalSessionFactoryBean 实现类

        ①、getCurrentSession()方法获取的Session 对象。

          举例子:有Boss 和Company 两个类。Boss类对应的表主键类又做为外键列。

          先保存有外键的一端。

            //设定关联关系
            company.setBoss(boss);
            boss.setCompany(company);
            
            //先保存有外键的一端
            oneToOnePrimaryService.saveBoss(boss);
            oneToOnePrimaryService.saveCompany(company);      

          此时会重复保存两次 Company 对象,个人猜测:可能是因为boss中已经持有了company 的引用,所以在保存boss 的时候也保存了company对象,接着又保存了一次company,所以才会出现保存两次的情况。但是在保存boss对象的时候也是先保存了boss引用的company对象。

          先保存没有外键的一端

            //设定关联关系
            company.setBoss(boss);
            boss.setCompany(company);
            
            //先保存没有外键的一端
            oneToOnePrimaryService.saveCompany(company);
            oneToOnePrimaryService.saveBoss(boss);

    此时先保存company,在保存boss,属于正常,而且company 也不会重复保存。

    ===================================================================

        ②、如果是使用openSession()方法获取的session对象

          先保存有外键的一端:虽然没有发生异常,但是不能正常保存

      

          先保存没有外键的一端:虽然没有发生异常,但是不能正常保存

      二)、SessionFactoryImpl 实现类获取的

        ①、使用getCurrentSession() 方法获取session对象。 

          先保存有外键的一端: 异常

          先保存没有外键的一端:异常

        ②、使用openSession()方法获取Session对象。

          先保存有外键的一端: 正常保存

          先保存没有外键的一端:正常保存

          而且基于主键映射的使用openSession()方法获取的 Session 保存对象,不论先保存哪一端都不会发送update 语句

    ---------------------------------------------------------------------------------------------------------------------

    总结:所以以后一对一映射最好保存没有外键的一端。

    三、一对一关联关系基于外键映射

      跟上面一样的方式获取不同的SessionFactory 的实现类的实例

      一)、LocalSessionFactoryBean 类

        ①、使用getSessionFactory()方法

          先保存有外键的一端:  异常

          先保存没有外键的一端: 正常保存

        ②、使用openSession()方法

          先保存有外键的一端: 不能正常保存,有外键的一端不能正常保存外键列,因为没有发送update语句。

          先保存没有外键的一端: 正常保存,没有update语句

      二)、SessionFactoryImpl 类

        ①、使用getSessionFactory()方法

          先保存有外键的一端:发生异常

          先保存没有外键的一端:发生异常

        ②、使用openSession()方法

          先保存有外键的一端:正常保存,但会发送update语句

          先保存没有外键的一端:正常保存,而且不会发送update语句。

    ---------------------------------------------------------------------------------------------------------------------------------

    总结:在使用一对一关联关系时,保存对象不管使用哪个SessionFactory的实现类的哪个方法获取Session,在保存对象时最好先保存没有外键列的一端。

    四、双向多对一关联关系

      一)、LocalSessionFactoryBean 类

        ①、

        ②、

      二)、SessionFactoryImpl 类

        ①、

        ②、

    五、双向多对多关联关系

      一)、LocalSessionFactoryBean 类

        ①、

        ②、

      二)、SessionFactoryImpl 类

        ①、

        ②、

  • 相关阅读:
    Firefly是什么?有什么特点?
    windows7下启动mysql服务出现服务名无效
    win7系统64位eclipse环境超详细暗黑1.4服务器搭建
    Python安装模块出错(ImportError: No module named setuptools)解决方法
    Error format not a string literal and no format arguments解决方案
    DropFileName = "svchost.exe" 问题解决方案
    javascript
    Javascript
    PHP 命名空间namespace 和 use
    css
  • 原文地址:https://www.cnblogs.com/GooPolaris/p/7919628.html
Copyright © 2020-2023  润新知