关于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 类

    ①、

    ②、

原文地址:https://www.cnblogs.com/GooPolaris/p/7919628.html