Hibernate一对多关系操作

1、创建两个实体类。

    一个实体类是商品类,另一个实体类是商品的分类类。

    在一对多关系的两个实体中,在编写实体类时必须要遵循以下规则:

      (1)在一的那一方的实体中,必须要有一个私有的多那一方的实体对象属性,并且提供公有的getter和setter方法。

        

    private Integer gid;
    private String gname;
    private String gmessage;
    
    /**
     * 在一对多关系中,在一的这一方,必须要有一个多的对象的私有属性
     * 别提供共有的getter和setter方法。
     */
    private Sort sort;
    public Sort getSort() {
        return sort;
    }
    public void setSort(Sort sort) {
        this.sort = sort;
    }    

      (2)在多的那一方的实体类中,必须要有一个私有的set集合属性来保存一的那一方的对象,并提供公有的getter和setter属性。

   private Integer sid;
    private String gname;
    private String gmessage;
    
    /**
     * 在一对多关系中,在多的那一方,必须要有一个set集合属性来保存一个那个实体
     * 并提供共有的getter和setter方法。
     */
    private Set<Good> getSet = new HashSet<Good>();
    public Set<Good> getGetSet() {
        return getSet;
    }
    public void setGetSet(Set<Good> getSet) {
        this.getSet = getSet;
    }

2、编写两个实体类的映射文件。

   (1)一的那一方的映射文件。

      在一的这一方,需要使用<many-to-one>标签来配置对应关系。

<hibernate-mapping>
        <class name="com.jack.entity.Good" table="t_good">
            <id name="gid" column="gid">
                <generator class="native"></generator>
            </id>
            <property name="gname" column="gname"></property>
            <property name="gmessage" column="gmessage"></property>
            
            <!-- 
                表示商品所属的分类
                name属性的值:因为在Good商品实体中,用sort表示Sort实体类,所有这里写sort
                class属性的值:sort类的全路径
                column属性的值:外键的名称
             -->
            <many-to-one name="sort" class="com.jack.entity.Sort" column="gsid"></many-to-one>
        </class>
    </hibernate-mapping>

   (2)多的那一方的映射文件。

      在多的这一方,需要使用<set>标签来配置对应关系。

 <hibernate-mapping>
        <class name="com.jack.entity.Sort" table="t_sort">
            <id name="sid" column="sid">
                <generator class="native"></generator>
            </id>
            <property name="sname" column="sname"></property>
            <property name="smessage" column="smessage"></property>
            
            <!-- 
                在多的这一边使用set标签来设置对应关系
                name属性的值:因为在Sort中使用getSet保存good属性。
                column属性的值:外键的名称,由于在Hibernate使用双向维护主键
                所有在这边的column的值必须要和另一边的值一致
                class属性的值:Good实体类的全路径。
             -->
           <set name="getSet">
               <key column="gsid"></key>
               <one-to-many class="com.jack.entity.Good" />
           </set>
        </class>
    </hibernate-mapping>

3、编写核心配置文件

<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql:///hibernatetest</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">root</property>

<property name="hibernate.show_sql">true</property>
<property name="hibernate.format_sql">true</property>
<property name="hibernate.hbm2ddl.auto">update</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name=" hibernate.current_session_context_class">thread</property>

<mapping resource="com/jack/entity/Good.hbm.xml"/>
<mapping resource="com/jack/entity/Sort.hbm.xml"/>
</session-factory>
</hibernate-configuration>

4、编写工具类

public class HibernateUtils {
    private static Configuration configuration = null;
    private static SessionFactory sessionFactory = null;
    static{
        configuration = new Configuration().configure();
        sessionFactory = configuration.buildSessionFactory();
    }

    public static Session getSeeion() {
        return sessionFactory.getCurrentSession();
    }
}

5、编写级联保存代码

第一种代码(复杂):

@Test
    public void TestAdd(){
        Session session = null;
        Transaction tx = null;
        try {
            session = HibernateUtils.getSeeion();
            tx = session.beginTransaction();
            
            /**
             * 创建两个商品
             */
            Good good1 = new Good();
            good1.setGname("蛋糕");
            good1.setGmessage("奶油蛋糕");
            Good good2 =new Good();
            good2.setGname("牙膏");
            good2.setGmessage("冷酸灵牙膏");
            
            /**
             * 创建两个类别
             */
            Sort sort1 =new Sort();
            sort1.setSname("食品");
            sort1.setSmessage("食品类");
            Sort sort2 = new Sort();
            sort2.setSname("生活用品");
            sort2.setSmessage("生活用品类");
            
            /**
             * 将商品放到类别中
             */
            sort1.getGetSet().add(good1);
            sort2.getGetSet().add(good2);
            /**
             * 将类别设置到商品中
             */
            good1.setSort(sort1);
            good2.setSort(sort2);
            /**
             * 保存类别
             * 保存商品
             */
            session.save(sort1);
            session.save(sort2);
            session.save(good1);
            session.save(good2);
            tx.commit();
        } catch (Exception e) {
            tx.rollback();
        }finally{
            
        }    
    }

第二种代码(简单):

首先在多的那一方的配置文件的<set>标签内,写入cascade属性,其值为save-update。

 <set name="getSet" cascade="save-update">
               <key column="gsid"></key>
               <one-to-many class="com.jack.entity.Good" />
           </set>

然后编写代码

@Test
    public void TestAdd2(){
        Session session = null;
        Transaction tx = null;
        try {
            session = HibernateUtils.getSeeion();
            tx = session.beginTransaction();
            
            /**
             * 创建两个商品
             */
            Good good3 = new Good();
            good3.setGname("面包");
            good3.setGmessage("面包");
            /**
             * 获得食品类
             */
            Sort sort1 = session.get(Sort.class, 1);
            /**
             * 将商品放到类别中
             */
            sort1.getGetSet().add(good3);
            
            /**
             * 保存类别
             * 现在只需要保存类别,商品也会自动保存
             */
            session.save(sort1);
            
            tx.commit();
        } catch (Exception e) {
            tx.rollback();
        }finally{
            
        }    
    }
    

6、Hibernate默认双方都要维护主键,这样会降低效率,通过配置inverse属性可以让一方放弃维护主键,这样可以提高操作效率。一般让多的那一方放弃。

  

 <!-- 
                 true:表示不维护
                 false:表示维护主键
                 默认为false,维护主键
              -->
           <set name="getSet" cascade="save-update" inverse="true">
               <key column="gsid"></key>
               <one-to-many class="com.jack.entity.Good" />
           </set>

7、测试结果

     

8、级联删除

首先配置cascade属性,值为delete

 <set name="getSet" cascade="save-update,delete" inverse="true">
               <key column="gsid"></key>
               <one-to-many class="com.jack.entity.Good" />
           </set>

编写代码实现删除(删除食品类)

@Test
    public void TestDelete(){
        Session session = null;
        Transaction tx = null;
        try {
            session = HibernateUtils.getSeeion();
            tx = session.beginTransaction();
            
            /**
             * 找到食品类
             */
            Sort sort = session.get(Sort.class, 1);
            
            /**
                删除食品类
             */
            session.delete(sort);
            tx.commit();
        } catch (Exception e) {
            tx.rollback();
        }finally{
            
        }    
    }

测试结果:

9、级联修改

修改前数据库

  

修改代码(把蛋糕放到生活用品中):

    @Test
    public void TestUpdate(){
        Session session = null;
        Transaction tx = null;
        try {
            session = HibernateUtils.getSeeion();
            tx = session.beginTransaction();
            
            /**
             * 找到生活用品
             */
            Sort sort = session.get(Sort.class, 2);
            /**
             * 找到蛋糕
             */
            Good good =session.get(Good.class, 4);
            /**
             * 把蛋糕放到生活用品中去
             */
            sort.getGetSet().add(good);
            /**
             * 把生活用品设置到蛋糕中去
             */
            good.setSort(sort);
            tx.commit();
        } catch (Exception e) {
            tx.rollback();
        }finally{
            
        }    
    }

修改之后结果:

  

  

原文地址:https://www.cnblogs.com/jack1995/p/6942162.html