Hibernate 注解 (Annotations 三)多对一双向注解

Posted 刘二雄

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Hibernate 注解 (Annotations 三)多对一双向注解相关的知识,希望对你有一定的参考价值。

注解(Annotation),也叫元数据。一种代码级别的说明。它是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。

接下来我们讲解一下多对一双向注解:

我以部门表和员工表作为示例讲解。

第一步:创建实体类

Dept(部门表)

 

package cn.onetomanydouble.entity;


import org.hibernate.annotations.*;
import org.hibernate.annotations.Cache;



import javax.persistence.*;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.Table;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;

/**
 * Created by accp on 2017/2/8.
 */
@Entity

@Table(name = "DEPT1")

public class Dept implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO,generator="PROMOTION_SEQ")
    @SequenceGenerator(name="PROMOTION_SEQ",sequenceName="PROMOTION_SEQ",initialValue = 1,allocationSize = 10)
    /*
       对于oracle想使用各自的Sequence,设置如下:
       @GeneratedValue(strategy = GenerationType.AUTO,generator="PROMOTION_SEQ")
       @SequenceGenerator(name="PROMOTION_SEQ",sequenceName="PROMOTION_SEQ")
       另外:
        对于自动增长后,在数据表中的相应字段,要设置字段为auto_increment.
    */
    private Integer deptno;
    @Column
    private String deptname;
    @OneToMany(mappedBy ="dept",cascade = {CascadeType.ALL},fetch = FetchType.LAZY)
    //mappedBy 属性主要针对外键而言,与之对应的是.xml中的inverse属性
    //mappedBy="dept" 是把维护权交给多的一方
    @LazyCollection(LazyCollectionOption.FALSE)
    private Set<Emp> emps=new HashSet<Emp>();
    @Column
    private  String location;

    public String getLocation() {
        return location;
    }

    public void setLocation(String location) {
        this.location = location;
    }

    public Integer getDeptno() {
        return deptno;
    }

    public void setDeptno(Integer deptno) {
        this.deptno = deptno;
    }

    public String getDeptname() {
        return deptname;
    }

    public void setDeptname(String deptname) {
        this.deptname = deptname;
    }

    public Set<Emp> getEmps() {
        return emps;
    }

    public void setEmps(Set<Emp> emps) {
        this.emps = emps;
    }


}

Emp(员工表)

 

package cn.onetomanydouble.entity;

import org.hibernate.annotations.*;
import org.hibernate.annotations.Cache;

import javax.persistence.*;
import javax.persistence.Entity;
import javax.persistence.Table;
import java.io.Serializable;

/**
 * Created by accp on 2017/2/8.
 */
@Entity
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
@Table(name = "EMP1")
public class Emp implements Serializable {
    @Id
    @GeneratedValue
    private Integer empno;
    @Column
    private String ename;
    @ManyToOne
    @JoinColumn(name = "deptno")
    private Dept dept;
   /* @Column
    private Double salary;
    @Column
    private String job;*/

    /*public Double getSalary() {
        return salary;
    }

    public void setSalary(Double salary) {
        this.salary = salary;
    }

    public String getJob() {
        return job;
    }

    public void setJob(String job) {
        this.job = job;
    }*/

    public Integer getEmpno() {
        return empno;
    }

    public void setEmpno(Integer empno) {
        this.empno = empno;
    }

    public String getEname() {
        return ename;
    }

    public void setEname(String ename) {
        this.ename = ename;
    }

    public Dept getDept() {
        return dept;
    }

    public void setDept(Dept dept) {
        this.dept = dept;
    }


}

在配置一对多双向的时候一定要搞清楚主外键关系。

第二步:在hibernate.cfg.xml文件中配置<mapping>节点

 <mapping class="cn.onetomanydouble.entity.Dept"/>
 <mapping class="cn.onetomanydouble.entity.Emp"/>

第三步:书写测试类

package cn.onetomanydouble.test;

import cn.onetomanydouble.entity.Dept;
import cn.onetomanydouble.entity.Emp;
import org.hibernate.Hibernate;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

/**
 * Created by accp on 2017/2/8.
 */
public class ManyToOneTest {

    Configuration cfg;
    Session session;
    Transaction tx;
    SessionFactory factory;
    @Before
    public void mybefore(){
        cfg=new Configuration().configure();
        factory=cfg.buildSessionFactory();
        session=factory.openSession();
         tx=session.beginTransaction();
    }

    @After
    public void myafter(){
       tx.commit();
        session.close();
    }

    @Test
    public void demo(){
        System.out.println(123);
    }

     @Test
   public void select(){


         /**
          * load()方法
          * fetch = FetchType.EAGER(立即加载)    fetch = FetchType.LAZY(懒加载)
          * 情况一:当在一的一方设置是否加载时
          *   fetch = FetchType.EAGER (立即加载)
          *   不查询不发送sql语句
          *   左外连接  两表查询
          *   查询关联表的属性时 不在重新发送sql
          *
          *
          *   fetch = FetchType.LAZY(懒加载)
          *   不查询不发送sql语句
          *   查询单一属性时   只查询当前表的   当查询关联属性时
          *   重新向数据库发送sql
          *
          *   get()方法
          *   fetch = FetchType.EAGER (立即加载) fetch = FetchType.LAZY(懒加载)
          *  (1) 情况一:当在多的一方设置
          *   fetch = FetchType.EAGER (立即加载)
          *   先向数据库查询一次
          *   左外连接   两表查询
          *   当用到属性时  直接打印对应的属性值
          *
          *   fetch = FetchType.LAZY(懒加载)
          *   只加载当前类的语句
          *   当查询当前表的属性时  只向数据库发送查询当前表的sql
          *
          *   当查询关联表的属性时  发送关联表的sql语句
          *
          */


         /*Transaction tx = factory.getCurrentSession().beginTransaction();
         Dept dept = factory.getCurrentSession().get(Dept.class, 1);
         for (Emp emp:dept.getEmps()) {
             System.out.println(emp.getEname());
         }

         tx.commit();
         factory.getCurrentSession().close();

         System.out.println("=====================");
         Transaction tx2 = factory.getCurrentSession().beginTransaction();
         Dept dept2 = factory.getCurrentSession().get(Dept.class, 1);
         for (Emp emp:dept2.getEmps()) {
             System.out.println(emp.getEname());
         }
         tx2.commit();
*/
         Dept dept = session.get(Dept.class, 1);
         System.out.println("=============");
         System.out.println(dept.getClass());
         System.out.println(dept.getDeptname());
         System.out.println(dept.getEmps().iterator().next().getEname());

       /*  Emp emp = session.get(Emp.class, 2);
        System.out.println("===========");*/
       /* System.out.println(emp.getEname());
        System.out.println(emp.getDept().getDeptname());*/

    }


    @Test
    public void add(){
        /*//创建部门
        Dept dept=new Dept();
        dept.setDeptname("产品部");

        //创建员工
        Emp emp=new Emp();
        emp.setEname("刘二雄");
        emp.setDept(dept);
        dept.getEmps().add(emp);
        //因为cascade级联只需保存部门即可保存员工
        session.save(dept);*/

        Dept dept=new Dept();
        dept.setDeptname("清洁部");

        //创建员工
        Emp emp=new Emp();
        emp.setEname("飘哥");
        emp.setDept(dept);
        dept.getEmps().add(emp);
        session.save(dept);
    }
}

执行完代码后一定要看看生成的sql语句,加深印象。

 

以上是关于Hibernate 注解 (Annotations 三)多对一双向注解的主要内容,如果未能解决你的问题,请参考以下文章

Hibernate 注解 (Annotations 三)多对一双向注解

Hibernate注解配置与XML配置区别

Spring注解之实体类常用注解

[Hibernate] 注解映射例子

关于使用hibernate注解总结

何时在 hibernate 中使用 DiscriminatorValue 注解