一、单向多对一关联关系
一)、使用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 类
①、
②、