• 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的主键方式
     
    测试操作
     



  • 相关阅读:
    python中的GIL
    centos7 安装docker
    ORACLE INSERT INTO SELECT
    Java substring几个用例
    Java Date类型转换、操作等(util.Date sql.Date,)
    ORACLE 按字段去除重复数据
    OFFICE技巧汇编
    ORACLE自动类型转换的坑
    ubuntu下,pycharm svn 版本控制,svn服务器在win下
    【草稿】pip重要命令;python 变量命名规则
  • 原文地址:https://www.cnblogs.com/toby-ruan/p/8510351.html
Copyright © 2020-2023  润新知