Hibernate注解开发

1. PO(简单)类注解配置
    在hibernate中我们使用注解,可以帮助我们简化hbm文件配置。
    导入的包是javax.persisitance 
    
    @Entity                //定义一个实体
    @Table                //来描述类与表对应
    @Id                      //来声明一个主键
    @JoinCoulumn(name = "外键") //用于指定外键类(在外键所在的类中配置)
    @JoinTable来描述中间表,并在中间表中描述外键分别与两个多表的映射关系
    @GenerateValue  //用它来声明一个主键生成策略
        默认情况下相当于native
    可以选择的主键生成策略 AUTO IDENTITY SEQUENCE
    @Column         //来定义列
    注意:对于PO类中所有属性,如果你不写注解,默认情况下也会在表中生成对应的列。
    列的名称就是属性的名称
    @Temporal来声明日期类型
        可以选择
        TemporalType.DATA   只有年月日  
        TemporalType.TIME   只有小时分钟秒
        TemporalType.TIMESTAMP 有年月日小时分钟秒
        我们最终需要在hibernate.cfg.xml文件中将我们类中的注解配置引用生效
package com.itheima.domain;
import java.util.Date;
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 javax.persistence.Temporal;
import javax.persistence.TemporalType;
@Entity   //声明一个实体
//描述与表对应
@Table(name = "t_book",catalog = "hibernateTest")
public class Book {
    @Id   //主键
    //声明主键生成策略,不写默认是native
    @GeneratedValue(strategy=GenerationType.IDENTITY)  //identity
    private Integer id;
    
    //声明列。name 对应数据库的列名,length 长度,nullable 是否为空
    @Column(name = "name",length=30,nullable =  true)
    private String name;
    
    //声明时间类型
    @Temporal(TemporalType.TIMESTAMP) //既有日期又有时分秒
    private Date publicactionDate;
 
    private Double price; //因为声明了@Entity 实体,所以这里价格就算不加注解们也会生成进表中,值都为默认值
    
    public Double getPrice() {
         return price;
    }
    public void setPrice(Double price) {
         this.price = price;
    }
    public Integer getId() {
         return id;
    }
    public void setId(Integer id) {
         this.id = id;
    }
    public String getName() {
         return name;
    }
    public void setName(String name) {
         this.name = name;
    }
    public Date getPublicactionDate() {
         return publicactionDate;
    }
    public void setPublicactionDate(Date  publicactionDate) {
         this.publicactionDate = publicactionDate;
    }
}
 
 
在实体类中使用注解声明后,还需要在hibernate.cfg.xml底下配置
<mapping class = "实体类的全类名">
编写测试类进行保存测试
import java.util.Date;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;
import com.itheima.domain.Book;
import com.itheima.utils.HibernateUtils;
public class HibernateAnnotionTest {
    @Test
    public void test1(){
         Session session =  HibernateUtils.openSession();
         Transaction transaction =  session.beginTransaction();
         
         Book book = new Book();
         book.setName("一言不合学java");
         book.setPrice(998d);
         book.setPublicactionDate(new Date());
         
         session.save(book);
         
         
         transaction.commit();
         session.close();
         
         
    }
}
 
问题:1.如果我们主键生成策略想使用UUID类型?
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Transient;
import org.hibernate.annotations.GenericGenerator;
@Entity
@Table(catalog = "hibernateTest")
public class Person {
    
    //问题一:问题:1.如果我们主键生成策略想使用UUID类型?
    @Id
    //主键成策略扩展的标签
    @GenericGenerator(name =  "myuuid",strategy="uuid")
    @GeneratedValue(generator="myuuid")
    private String id ;
    
    //问题二:问题2:如果设定类的属性不在表中映射?
    //使用@Transient
    @Transient
    private String msg;
}
 
对于我们以上讲解的关于属性配置的注解,我们也可以在其对应的getXxx方法去使用
 
 

一对多(多对一)

@OneToMany
@ManyToOne
以Customer与Order为例
 
Customer类
 
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
 
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
 
//客户的实体类  ------- 一的一方
@Entity
@Table(name = "t_customer",catalog = "hibernateTest")
public class Customer {
    @Id
    private Integer id ; //主键
    
    private String name ; //姓名
    
    // 描述客户可以有多个订单
        /*
         * targetEntity相当于<one-to-many class="">
         * mappedBy相当于inverse=true
         */
    @OneToMany(targetEntity=Customer.class,mappedBy="c",orphanRemoval=true)
    //描述客户可以有多个订单
    private Set<Order> order =  new HashSet<Order>();
 
    public Integer getId() {
        return id;
    }
 
    public void setId(Integer id) {
        this.id = id;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public Set<Order> getOrder() {
        return order;
    }
 
    public void setOrder(Set<Order> order) {
        this.order = order;
    }
    
    
}
 
 
Order类
 
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;
 
//订单-----多的一方
@Entity
@Table(name = "t_order")
public class Order {
 
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
 
    private Double money;
 
    private String receiverInfo; // 收货地址
    // 订单与客户关联
    @ManyToOne(targetEntity = Customer.class)
    @JoinColumn(name = "c_id") // 指定外键列
    private Customer c; // 描述订单属于某一个客户
 
    public Customer getC() {
        return c;
    }
 
    public void setC(Customer c) {
        this.c = c;
    }
 
    public Integer getId() {
        return id;
    }
 
    public void setId(Integer id) {
        this.id = id;
    }
 
    public Double getMoney() {
        return money;
    }
 
    public void setMoney(Double money) {
        this.money = money;
    }
 
    public String getReceiverInfo() {
        return receiverInfo;
    }
 
    public void setReceiverInfo(String receiverInfo) {
        this.receiverInfo = receiverInfo;
    }
 
}
 
 
 
示例:保存客户时,保存订单
对于这个示例我们需要在Customer中配置(级联)cascade操作,<save-update>
 
 
第一种方式,可以使用JPA提供的注解
(推荐使用)第二种方式:可以使用hibernate提供的注解
    @OneToMany(targetEntity=Customer.class,mappedBy="c")
    @Cascade(CascadeType.SAVE_UPDATE)
    //描述客户可以有多个订单
    private Set<Order> order =  new  HashSet<Order>();
 
以下是示例代码
将id设为自动增长
@Test
    //测试级联保客户时候自动保存订单
    public void test2(){
         Session session =  HibernateUtils.openSession();
         Transaction transaction =  session.beginTransaction();
         //订单1
         Order order1 = new Order();
         order1.setReceiverInfo("福建");
         order1.setMoney(998d);
         //订单2
         Order order2 = new Order();
         order2.setReceiverInfo("福建");
         order2.setMoney(100d);
         
         //顾客1
         Customer customer = new Customer();
         customer.setName("雷老虎");
         //建立关系
         order1.setC(customer);
         order2.setC(customer);
         
         customer.getOrder().add(order1);
         customer.getOrder().add(order2);
         
         session.save(customer);
         
         transaction.commit();
         session.close();
         
         
    }
 
 
订单中没有关联客户的id,为什么?
原因:我们在Customer中配置了mappedBy=c”(相当于inverse=true)它代表的是外键的维护由Order方来维护,而Customer不维护,这时你在保存客户时,级联保存订单,是可以的,但是不能维护外键,所以,我们必须在代码中添加订单与客户关系。
 
扩展:关于hibernate注解@Cascade中的DELETE_ORPHAN过时
s
使用下面方案来替换过时方案
 
     Hibernate关联映射-多对多
使用注解完成多对多配置.
描述学生与老师.
使用@ManyToMany来配置多对多,只需要在其中一端配置中间表,另一端使用mappedBy表示放置外键维护权。
        创建PO类
Teacher类中
 
import java.util.HashSet;
import java.util.Set;
 
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
 
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;
 
@Entity
@Table(name = "t_teacher")
public class Teacher {
 
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    private String name;
 
    @ManyToMany(targetEntity = Student.class, mappedBy = "teachers") // 代表由对方来维护外键
    @Cascade(CascadeType.ALL)
    private Set<Student> students = new HashSet<Student>();
 
    public Integer getId() {
        return id;
    }
 
    public void setId(Integer id) {
        this.id = id;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public Set<Student> getStudents() {
        return students;
    }
 
    public void setStudents(Set<Student> students) {
        this.students = students;
    }
 
}
 
 
Student类中
 
import java.util.HashSet;
import java.util.Set;
 
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
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;
 
@Entity
@Table(name = "t_student")
public class Student {
 
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
 
    private String name;
    @ManyToMany(targetEntity = Teacher.class)
    // 使用JoinTabl来描述中间表,并描述中间表中外键与Student,Teacher的映射关系
    // joinColumns它是用来描述(本方)Student与中间表中的映射关系
    // inverseJoinColums它是用来描述对方(Teacher)与中间表中的映射关系
    // 其中referencedColumnName = "id"可以省略,因为默认就是和主键关联
    @JoinTable(name = "s_t", joinColumns = {
            @JoinColumn(name = "c_student_id", referencedColumnName = "id") }, inverseJoinColumns = {
                    @JoinColumn(name = "c_teacher_id", referencedColumnName = "id") })
    @Cascade(CascadeType.ALL)
    private Set<Teacher> teachers = new HashSet<Teacher>();
 
    public Integer getId() {
        return id;
    }
 
    public void setId(Integer id) {
        this.id = id;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public Set<Teacher> getTeachers() {
        return teachers;
    }
 
    public void setTeachers(Set<Teacher> teachers) {
        this.teachers = teachers;
    }
 
}
总结:
一对多和多对多的配置步骤:
    1.添加关联关系的注解:@ManyToOne,@OneToMany,ManyToMany
        配置targetEntity(对方的类.class)
    2.哪方维护外键:mappedBy="对方中,表示本方的名称"
    3.在维护关系的一方添加外键映射
 
级联保存操作测试
 因为我们将外键的维护权利由Student来维护,我们演示保存学生时,将都也级联保存。
 
 
我们在Student类中配置了级联
 
  1.  

    级联删除操作测试

 Hibernate关联映射-一对一
    以人与身份证号为例
 
一对一操作有两种映射方式:

  1. 在任意一方添加外键

  2. 主键映射
                外键映射
 
        创建实体
User类
上述配置,t_user表放弃对外键的维护权利
 
IDCard类
joinColumn指定外键列名称,当前配置外键是在t_idcard表中
 
测试代码
  1.  

    主键映射

以Husband与Wife为例
 
Wife的主键生成策略是identity
@PrimaryKeyJoinColumn 说明husband与wife是使用主键映射
 
Husband的主键我们设置成参考wife的主键方式
 
测试操作
 



原文地址:https://www.cnblogs.com/toby-ruan/p/8510351.html