Hibernate一对多关系操作

1、创建两个实体类。

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

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

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

        

hibernate hibernate_sequence 注解 MySQL hibernate注解一对多_主键

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;
    }

hibernate hibernate_sequence 注解 MySQL hibernate注解一对多_主键

 

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

hibernate hibernate_sequence 注解 MySQL hibernate注解一对多_主键

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;
    }

hibernate hibernate_sequence 注解 MySQL hibernate注解一对多_主键

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

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

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

hibernate hibernate_sequence 注解 MySQL hibernate注解一对多_主键

<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>

hibernate hibernate_sequence 注解 MySQL hibernate注解一对多_主键

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

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

hibernate hibernate_sequence 注解 MySQL hibernate注解一对多_主键

<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>

hibernate hibernate_sequence 注解 MySQL hibernate注解一对多_主键

3、编写核心配置文件

hibernate hibernate_sequence 注解 MySQL hibernate注解一对多_主键

<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>

hibernate hibernate_sequence 注解 MySQL hibernate注解一对多_主键

4、编写工具类

hibernate hibernate_sequence 注解 MySQL hibernate注解一对多_主键

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();
    }
}

hibernate hibernate_sequence 注解 MySQL hibernate注解一对多_主键

5、编写级联保存代码

第一种代码(复杂):

hibernate hibernate_sequence 注解 MySQL hibernate注解一对多_主键

@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{
            
        }    
    }

hibernate hibernate_sequence 注解 MySQL hibernate注解一对多_主键

第二种代码(简单):

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

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

然后编写代码

hibernate hibernate_sequence 注解 MySQL hibernate注解一对多_主键

@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{
            
        }    
    }

hibernate hibernate_sequence 注解 MySQL hibernate注解一对多_主键

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

  

hibernate hibernate_sequence 注解 MySQL hibernate注解一对多_主键

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

hibernate hibernate_sequence 注解 MySQL hibernate注解一对多_主键

7、测试结果

 

hibernate hibernate_sequence 注解 MySQL hibernate注解一对多_主键_19

    

hibernate hibernate_sequence 注解 MySQL hibernate注解一对多_hibernate_20

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>

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

hibernate hibernate_sequence 注解 MySQL hibernate注解一对多_主键

@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{
            
        }    
    }

hibernate hibernate_sequence 注解 MySQL hibernate注解一对多_主键

测试结果:

hibernate hibernate_sequence 注解 MySQL hibernate注解一对多_实体类_23

hibernate hibernate_sequence 注解 MySQL hibernate注解一对多_hibernate_24

9、级联修改

修改前数据库

hibernate hibernate_sequence 注解 MySQL hibernate注解一对多_主键_25

  

hibernate hibernate_sequence 注解 MySQL hibernate注解一对多_hibernate_26

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

hibernate hibernate_sequence 注解 MySQL hibernate注解一对多_主键

@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{
            
        }    
    }

hibernate hibernate_sequence 注解 MySQL hibernate注解一对多_主键

修改之后结果:

hibernate hibernate_sequence 注解 MySQL hibernate注解一对多_hibernate_29

  

hibernate hibernate_sequence 注解 MySQL hibernate注解一对多_实体类_30

 

 

 

 

JPA(Java Persistence API)通过注解或XML描述对象与关系表的映射关系,并将运行期的实体对象持久化到数据库中。

JPA是一个规范,是一个标准,Hibernate是实现了这个标准的开源框架。

1、引入hibernate-jpa-2.0-api-1.0.0.Final.jar JPA规范对应的hibernate的jar包

2、修改配置文件hibernate.cfg.xml 的映射关系<Mapping class="">

hibernate hibernate_sequence 注解 MySQL hibernate注解一对多_主键

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-configuration
    PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN"
    "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
    <session-factory>
        <!-- thread:一个线程中使用一个。获取session会话时使用-->
        <property name="current_session_context_class">thread</property>
        <!-- 是否显示SQL语句,值为布尔型,默认false -->
        <property name="hibernate.show_sql">true</property>
        <!-- 是否格式化显示sql语句,让显示更美观,值为布尔型,默认false -->
        <property name="hibernate.format_sql">false </property>
        <!-- 自动建表
            update:每次执行时,无表则建表,无列则建列,只增不减 
            create:每次启动的时候,删除原表,再次创建
            create-drop:每次启动时创建新表,当显式关闭sessionFactory时,删除表
        -->
        <property name="hibernate.hbm2ddl.auto">update</property>
        <!-- 连接数据库 -->
        <property name="hibernate.connection.url">jdbc:mysql://127.0.0.1:3306/zxd_db</property>
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="hibernate.connection.username">zxd</property>
        <property name="hibernate.connection.password">123456</property>
        <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
        
        <!-- 读取注解 -->
        <mapping class="demo.entity.Book" />
            
    </session-factory>
</hibernate-configuration>

hibernate hibernate_sequence 注解 MySQL hibernate注解一对多_主键

 3、实体配置

hibernate hibernate_sequence 注解 MySQL hibernate注解一对多_主键

package demo.entity;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

import org.hibernate.annotations.GenericGenerator;
/**
 * 注解实体配置
 * JPA通过注解或XML描述对象与关系表的映射关系,并将运行期的实体对象持久化到数据库中。
 * @author Don
 * @date:日期:2017年4月19日 时间:上午10:43:00*
 * @version 1.0
 */

//标注实体
@Entity
//实体对应的表名,自动建库(若不写name,则表名与实体名保持一致)
@Table(name="tb_book")
public class Book {
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    //主键ID注解
    private int id;
    @Id
    @GenericGenerator(name="pk_uuid",strategy="uuid")
    @GeneratedValue(generator="pk_uuid")
    //生成UUID的主键注解
    private String uuid;
    @Column
    //列注解
    private String name;
    @Column
    private double price;
    
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public double getPrice() {
        return price;
    }
    public void setPrice(double price) {
        this.price = price;
    }
    public String getUuid() {
        return uuid;
    }
    public void setUuid(String uuid) {
        this.uuid = uuid;
    }
}

hibernate hibernate_sequence 注解 MySQL hibernate注解一对多_主键

4、数据库实务session创建

hibernate hibernate_sequence 注解 MySQL hibernate注解一对多_主键

package demo.util;

import java.text.Annotation;

import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.cfg.Configuration;
import org.hibernate.classic.Session;

public class HibernateUtil {

    public static Session getCurrentSession() {

        /*注解调用使用AnnotationConfiguration 对象创建*/
        // 加载Hibernate配置信息,默认读取src下的hibernate.cfg.xml
        Configuration cfg = new AnnotationConfiguration().configure();
        // 也可以指定hibernate.cfg.xml 的路径加载
        // Configuration cfg1 = new Configuration().configure(Path);

        /*
         * 应用程序从SessionFactory(会话工厂)里获得Session(会话)实例。它在多个应用线程间进行共享。
         * 通常情况下,整个应用只有唯一的一个会话工厂,SessionFactory由Configuration对象创建,
         * 每个Hibernate配置文件,实际上是对SessionFactory的配置
         */
        // 试用配置信息构建sessionFactory
        SessionFactory factory = cfg.buildSessionFactory();
        
        Session session =factory.getCurrentSession();
        
        return session;
    }

}

hibernate hibernate_sequence 注解 MySQL hibernate注解一对多_主键

5、测试建表和增删改查和XML配置映射一致

(一)、 一对一映射(主键关联)

Card实体类

hibernate hibernate_sequence 注解 MySQL hibernate注解一对多_主键_37

 View Code

Person实体类

hibernate hibernate_sequence 注解 MySQL hibernate注解一对多_主键_37

 View Code

 (二)、一对一映射(唯一外键)

 Card实体类

hibernate hibernate_sequence 注解 MySQL hibernate注解一对多_主键_37

 View Code

Person实体类

hibernate hibernate_sequence 注解 MySQL hibernate注解一对多_主键_37

 View Code

 (三)、一对多映射

Classes实体类(课程)

hibernate hibernate_sequence 注解 MySQL hibernate注解一对多_主键_41

hibernate hibernate_sequence 注解 MySQL hibernate注解一对多_主键

package demo.entity;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;

import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;



@Entity
@Table(name="ann_m2o_Classes")
public class Classes {
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private int id;
    @Column
    private String name;
    @OneToMany(mappedBy="cal")
    @Cascade(CascadeType.ALL)
    //一对多关系配置(配置Student实体中的Class实体映射对象,设计级联关系)
    private List<Student> list = new ArrayList<Student>();
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public List<Student> getList() {
        return list;
    }
    public void setList(List<Student> list) {
        this.list = list;
    }
}

hibernate hibernate_sequence 注解 MySQL hibernate注解一对多_主键

Student实体类(学生)

hibernate hibernate_sequence 注解 MySQL hibernate注解一对多_主键_41

hibernate hibernate_sequence 注解 MySQL hibernate注解一对多_主键

package demo.entity;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;

@Entity
@Table(name="ann_m2o_Student")
public class Student {
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private int id;
    @Column
    private String name;
    @ManyToOne
    @JoinColumn(name="cid")
    @Cascade(CascadeType.SAVE_UPDATE)
    private Classes cal;
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Classes getCal() {
        return cal;
    }
    public void setCal(Classes cal) {
        this.cal = cal;
    }
    
}

hibernate hibernate_sequence 注解 MySQL hibernate注解一对多_主键

(四)、多对多映射(中间表)

Course实体类(选课)

hibernate hibernate_sequence 注解 MySQL hibernate注解一对多_主键_41

hibernate hibernate_sequence 注解 MySQL hibernate注解一对多_主键

package demo.entity;

import java.util.HashSet;
import java.util.Set;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;

import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;
import org.hibernate.annotations.GenericGenerator;

/**
 * 课程实体
 * @author Don
 * @date:日期:2017年4月11日 时间:下午2:25:45*
 * @version 1.0
 */

@Entity
@Table(name="ann_m2m_Course")
public class Course {
    @Id
    @GenericGenerator(name="pk_key",strategy="uuid")
    @GeneratedValue(generator="pk_key")
    private String id;
    @Column
    private String name; 
    @ManyToMany
    //级联关系
    @Cascade(CascadeType.SAVE_UPDATE)
    //中间表
    @JoinTable(name="ann_m2m_stu_course",
    //链接当前对象的Id
    joinColumns={@JoinColumn(name="cid",referencedColumnName="id")},
    //链接对方的表的Id
    inverseJoinColumns={@JoinColumn(name="stuId",referencedColumnName="id")})
    private Set<Student> stus = new HashSet<>();
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Set<Student> getStus() {
        return stus;
    }
    public void setStus(Set<Student> stus) {
        this.stus = stus;
    }
    
    public Course(){}
    
    public Course(String name) {
        this.setName(name);
    }
}

hibernate hibernate_sequence 注解 MySQL hibernate注解一对多_主键

Student实体类(选课人员)

hibernate hibernate_sequence 注解 MySQL hibernate注解一对多_主键_41

hibernate hibernate_sequence 注解 MySQL hibernate注解一对多_主键

package demo.entity;

import java.util.HashSet;
import java.util.Set;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinColumns;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;

import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;
import org.hibernate.annotations.GenericGenerator;

/**
 * 学生实体
 * @author Don
 * @date:日期:2017年4月11日 时间:下午2:25:15*
 * @version 1.0
 */
@Entity
@Table(name="ann_m2m_Student")
public class Student {
    @Id
    //生成UUID
    @GenericGenerator(name="pk_key",strategy="uuid")
    @GeneratedValue(generator="pk_key")
    private String id;
    @Column
    private String name;
    
    @ManyToMany
    //级联关系
    @Cascade(CascadeType.SAVE_UPDATE)
    //中间表
    @JoinTable(name="ann_m2m_stu_course",
    //链接当前对象的Id
    joinColumns={@JoinColumn(name="stuId",referencedColumnName="id")},
    //链接对方的表的Id
    inverseJoinColumns={@JoinColumn(name="cid",referencedColumnName="id")})
    private Set<Course> cous=new HashSet<>();
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Set<Course> getCous() {
        return cous;
    }
    public void setCous(Set<Course> cous) {
        this.cous = cous;
    }
    
    public Student() {
        
    }
    
    public Student(String name) {
        this.setName(name);
    }
}