zoukankan      html  css  js  c++  java
  • JPA

    1.映射

    1.一般映射是指两两之间的关系,在指明映射关系时以一方为主,在主类中通过注解来对另一个对象进行关系映射,注解标注在get方法上面

    2.注解

    1.@fetch 是用来定义级联查询的方式,@cascade 用来管理级联插入和修改。
    2.@JsonIgnore:被定义的属性将会被忽视,不被引用
      上个实体User中的  department属性就在getDepartment属性上加了  @JsonIgnore,这个时候从后台推数据到前台的时候,就会把department这个引用属性给忽略掉。
    3.@Basic标记可以指定实体属性的加载方式:

    最近学习hibernate注解形式配置POJO类,将注解的解析记下来,以备以后使用。

    例1.

    复制代码
    @Entity
    @Table(name="user")  public class Flight implements Serializable {    Long id; @Id
    @GeneratedValue(generator="generator")
    @GenericGenerator(name="generator", strategy = "native") public Long getId() { return id; }  public void setId(Long id) { this.id = id; }  }
    复制代码

    Hibernate 可以对类的属性或者方法进行注解。属性对应field类别,方法的 getXxx()对应property类别。

    @Entity

    声明一个类为实体Bean。

    @Table

    说明此实体类映射的表名,目录,schema的名字。

    @Id

    声明此表的主键。

    @GeneratedValue

    定义主键的增长策略。我这里一般交给底层数据库处理,所以调用了名叫generator的增长方式,由下边的@GenericGenerator实现

    @GenericGenerator

    hibernate内部的主键增长方式.

    关于@GeneratedValue@GenericGenerator的详细说明,在我的另一篇转载的文章里边有。
    @GeneratedValue 与 @GenericGenerator

    例2.

    @Table(name="tbl_sky", 
      uniqueConstraints = {@UniqueConstraint(columnNames={"month", "day"})} )

    @UniqueConstraint

    将对应的字段设置唯一性标识

    (注:UniqueConstraint只在hibernate.hbm2ddl.auto设置为create-drop才会起作用)

    例3.

    1 public class Flight implements Serializable {
    2    @Version 
    3    @Column(name="OPTLOCK") 
    4     public Integer getVersion() {} } 

    @Version 

    注解用于支持乐观锁版本控制。一般可以用 数字 或者 timestamp 类型来支持 version.

    @Column

    用于映射对应的字段,其中参数详解如下:

            name = "columnName";                                (1)
            boolean unique() default false;                      (2)
            boolean nullable() default true;                     (3)
            boolean insertable() default true;                  (4)
            boolean updatable() default true;                 (5)
            String columnDefinition() default "";            (6)
            String table() default "";                                (7)
            int length() default 255;                                (8)
            int precision() default 0;                               (9)
            int scale() default 0;                                     (10)
    (1)     name 可选,列名(默认值是属性名)
    (2)     unique 可选,是否在该列上设置唯一约束(默认值false)
    (3)     nullable 可选,是否设置该列的值可以为空(默认值true)
    (4)     insertable 可选,该列是否作为生成的insert语句中的一个列(默认值true)
    (5)     updatable 可选,该列是否作为生成的update语句中的一个列(默认值true)
    (6)     columnDefinition 可选,为这个特定列覆盖SQL DDL片段 (这可能导致无法在不同数据库间移植)
    (7)     table 可选,定义对应的表(默认为主表)
    (8)     length 可选,列长度(默认值255)
    (9)     precision 可选,列十进制精度(decimal precision)(默认值0)
    (10)   scale 可选,如果列十进制数值范围(decimal scale)可用,在此设置(默认值0)

     例4.

    复制代码
    public class user
    {
        @Transient    
        private Integer id;
        @Basic(fetch=FetchType.LAZY,optional=true)
        private String name;
    
        @Transient
        public Integer getId() {}
    @Temporal(TemporalType.TIME)
    public java.util.Date getDatetime() {};
    }
    复制代码

    @Transient
         被注解成 @Transient 的 getter 方法或属性,将不会被持久化(自己测试,只有放在getter方法内才起作用)

    @Basic
        所有没有定义注解的属性,等价于在其上面添加了 @Basic注解可以声明属性的获取策略 ( fetch strategy )

        fetch:抓取策略,延时加载与立即加载,optional:指定在生成数据库结构时字段是否允许为 null.

    @Temporal

        在核心的 Java API 中并没有定义时间精度 ( temporal precision )。因此处理时间类型数据时,你还需要定义将其存储在数据库中所预期的精度。
        在数据库中,表示时间类型的数据有 DATE,TIME,和 TIMESTAMP 三种精度 ( 即单纯的日期,时间,或者两者兼备 )。 可使用 @Temporal 注解来调整精度。

     

     

    映射实体Bean的关联关系

    •  一对一

    使用 @OneToOne 注解可以建立实体Bean之间的一对一关系。一对一关系有3种情况。

    • 关联的实体都共享同样的主键。

    复制代码
     @Entity
    public class Body {
    @Id
    public Long getId() { return id; }
    @OneToOne(cascade = CascadeType.ALL)
    @PrimaryKeyJoinColumn
    public Heart getHeart() {
    return heart;
    }
    ...
    }
    
    @Entity
    public class Heart {
    @Id
    public Long getId() { ...}
    }
    复制代码

     

    通过@PrimaryKeyJoinColumn 注解定义了一对一的关联关系。

     


    • 其中一个实体通过外键关联到另一个实体的主键。注:一对一,则外键必须为唯一约束。

     

    复制代码
     @Entity
    public class Customer implements Serializable {
    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name="passport_fk")
    public Passport getPassport() {
    ...
    }
    
    
    @Entity
    public class Passport implements Serializable {
    @OneToOne(mappedBy = "passport")
    public Customer getOwner() {
    ...
    }
    复制代码

     

    通过@JoinColumn注解定义一对一的关联关系。如果没有@JoinColumn注解,则系统自动处理,在主表中将创建连接列,列名为:主题的关联属性名 + 下划线 + 被关联端的主键列名。上例为 passport_id, 因为Customer 中关联属性为 passport, Passport 的主键为 id.

     


    • 通过关联表来保存两个实体之间的关联关系。注:一对一,则关联表每个外键都必须是唯一约束。

     

    复制代码
     @Entity
    public class Customer implements Serializable {
    @OneToOne(cascade = CascadeType.ALL)
    @JoinTable(name = "CustomerPassports",
    joinColumns = @JoinColumn(name="customer_fk"),
    inverseJoinColumns = @JoinColumn(name="passport_fk")
    )
    public Passport getPassport() {
    ...
    }
    
    
    @Entity public class Passport implements Serializable {
    @OneToOne(mappedBy = "passport")
    public Customer getOwner() {
    ...
    }
    复制代码

     

    Customer 通过 CustomerPassports 关联表和 Passport 关联。该关联表通过 passport_fk 外键指向 Passport 表,该信心定义为 inverseJoinColumns 的属性值。 通过 customer_fk 外键指向Customer 表,该信息定义为 joinColumns 属性值。

     

    • 多对一

     

    使用 @ManyToOne 注解定义多对一关系。

     

    复制代码
     @Entity()
    public class Flight implements Serializable {
    @ManyToOne( cascade = {CascadeType.PERSIST, CascadeType.MERGE} )
    @JoinColumn(name="COMP_ID")
    public Company getCompany() {
    return company;
    }
    ...
    }
    复制代码

     

    其中@JoinColumn 注解是可选的,关键字段默认值和一对一关联的情况相似。列名为:主题的关联属性名 + 下划线 + 被关联端的主键列名。本例中为company_id,因为关联的属性是company, Company的主键为 id.

     

    @ManyToOne 注解有个targetEntity属性,该参数定义了目标实体名。通常不需要定义,大部分情况为默认值。但下面这种情况则需要 targetEntity 定义(使用接口作为返回值,而不是常用的实体)。

     

    复制代码
     @Entity()
    public class Flight implements Serializable {
    @ManyToOne(cascade= {CascadeType.PERSIST,CascadeType.MERGE},targetEntity= CompanyImpl.class)
    @JoinColumn(name="COMP_ID")
    public Company getCompany() {
    return company;
    }
    ...
    }
    
    
    public interface Company {
    ...
    复制代码

     

    多对一也可以通过关联表的方式来映射,通过@JoinTable 注解可定义关联表。该关联表包含指回实体的外键(通过@JoinTable.joinColumns)以及指向目标实体表的外键(通过@JoinTable.inverseJoinColumns).

     

    复制代码
     @Entity()
    public class Flight implements Serializable {
    
    @ManyToOne( cascade = {CascadeType.PERSIST, CascadeType.MERGE} )
    @JoinTable(name="Flight_Company",
    joinColumns = @JoinColumn(name="FLIGHT_ID"),
    inverseJoinColumns = @JoinColumn(name="COMP_ID")
    )
    public Company getCompany() {
    return company;
    }
    ...
    }
    复制代码

    非主键多对一关联:

    A表:sn   B表:cp_sn

    A表配置:

    复制代码
     1 private List<B> sns;  
     2 
     3         @OneToMany(mappedBy = "a", fetch = FetchType.LAZY)  
     4         public List<B> getSns() {  
     5             return sns;  
     6         }  
     7       
     8         public void setSns(List<B> sns) {  
     9             this.sns = sns;  
    10         }  
    复制代码

    B表配置:

    复制代码
    1     private A a;  
    2       
    3         @ManyToOne(fetch = FetchType.LAZY)  
    4         @JoinColumn(name = "CP_SN", referencedColumnName="sn",  insertable = false, updatable = false)  
    5         public A getA() {  
    6             return a;  
    7         }  
    复制代码

     name = "CP_SN" -- 本表中的字段

     referencedColumnName="sn" -- 关联表的字段

     

    集合类型

    • 一对多

     

    @OneToMany 注解可定义一对多关联。一对多关联可以是双向的。

     

    双向

     

    规范中多对一端几乎总是双向关联中的主体(owner)端,而一对多的关联注解为@OneToMany(mappedBy=)

     

    复制代码
     @Entity
    public class Troop {
    @OneToMany(mappedBy="troop")
    public Set<Soldier> getSoldiers() {
    ...
    }
    
    
    @Entity
    public class Soldier {
    @ManyToOne
    @JoinColumn(name="troop_fk")
    public Troop getTroop() {
    ...
    }
    复制代码

     

    Troop 通过troop属性和Soldier建立了一对多的双向关联。在 mappedBy 端不必也不能定义任何物理映射。

     

    单向

     

    复制代码
     @Entity
    public class Customer implements Serializable {
    @OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
    @JoinColumn(name="CUST_ID")
    public Set<Ticket> getTickets() {
    ...
    }
    
    @Entity
    public class Ticket implements Serializable {
    ... //no bidir
    }
    复制代码

     

    一般通过连接表来实现这种关联,可以通过@JoinColumn注解来描述这种单向关联关系。上例Customer 通过 CUST_ID 列和 Ticket 建立了单向关联关系。

     

    通过关联表来处理单向关联

     

    复制代码
     @Entity
    public class Trainer {
    @OneToMany
    @JoinTable(
    name="TrainedMonkeys",
    joinColumns = @JoinColumn( name="trainer_id"),
    inverseJoinColumns = @JoinColumn( name="monkey_id")
    )
    public Set<Monkey> getTrainedMonkeys() {
    ...
    }
    
    
    @Entity
    public class Monkey {
    ... //no bidir
    }
    复制代码

     

    通过关联表来处理单向一对多关系是首选,这种关联通过 @JoinTable 注解来进行描述。上例子中 Trainer 通过TrainedMonkeys表和Monkey建立了单向关联关系。其中外键trainer_id关联到Trainer(joinColumns)而外键monkey_id关联到Monkey(inverseJoinColumns).

     

    默认处理机制

     

    通过连接表来建立单向一对多关联不需要描述任何物理映射,表名由一下3个部分组成,主表(owner table)表名 + 下划线 + 从表(the other side table)表名。指向主表的外键名:主表表名+下划线+主表主键列名 指向从表的外键定义为唯一约束,用来表示一对多的关联关系。

     

    复制代码
     @Entity
    public class Trainer {
    @OneToMany
    public Set<Tiger> getTrainedTigers() {
    ...
    }
    
    
    @Entity
    public class Tiger {
    ... //no bidir
    }
    复制代码

     

    上述例子中 Trainer 和 Tiger 通过 Trainer_Tiger 连接表建立单向关联关系。其中外键 trainer_id关联到 Trainer表,而外键 trainedTigers_id 关联到 Tiger 表。

     

    • 多对多

     

    通过@ManyToMany 注解定义多对多关系,同时通过 @JoinTable 注解描述关联表和关联条件。其中一端定义为 owner, 另一段定义为 inverse(对关联表进行更新操作,这段被忽略)。

     

    复制代码
    // 维护端注解
    @ManyToMany (cascade = CascadeType.REFRESH)
    @JoinTable (//关联表
               name =  "student_teacher" , //关联表名
               inverseJoinColumns =  @JoinColumn (name =  "teacher_id" ),//被维护端外键
               joinColumns =  @JoinColumn (name =  "student_id" ))//维护端外键被维护端注解
    
    @ManyToMany(cascade = CascadeType.REFRESH,
                mappedBy = "teachers",//通过维护端的属性关联
                fetch = FetchType.LAZY)
    // 关系维护端删除时,如果中间表存在些纪录的关联信息,则会删除该关联信息;
    // 关系被维护端删除时,如果中间表存在些纪录的关联信息,则会删除失败 .
    复制代码

     

    默认值:

     

    关联表名:主表表名 + 下划线 + 从表表名;关联表到主表的外键:主表表名 + 下划线 + 主表中主键列名;关联表到从表的外键名:主表中用于关联的属性名+ 下划线 + 从表的主键列名。

     

    用 cascading 实现传播持久化(Transitive persistence

     

    cascade 属性接受值为 CascadeType 数组,其类型如下:

     

    • CascadeType.PERSIST: cascades the persist (create) operation to associated entities persist() is called or if the entity is managed 如果一个实体是受管状态,或者当 persist() 函数被调用时,触发级联创建(create)操作。

     


    • CascadeType.MERGE: cascades the merge operation to associated entities if merge() is called or if the entity is managed 如果一个实体是受管状态,或者当 merge() 函数被调用时,触发级联合并(merge)操作。

     


    • CascadeType.REMOVE: cascades the remove operation to associated entities if delete() is called 当 delete() 函数被调用时,触发级联删除(remove)操作。

     


    • CascadeType.REFRESH: cascades the refresh operation to associated entities if refresh() is called 当 refresh() 函数被调用时,出发级联更新(refresh)操作。

     


    • CascadeType.ALL: all of the above 以上全部

     

     

    其他属性:

    @Enumerated
    @javax.persistence.Enumerated(EnumType.STRING)
    value:EnumType.STRING,EnumType.ORDINAL
    枚举类型成员属性映射,EnumType.STRING指定属性映射为字符串,EnumType.ORDINAL指定属性映射为数据序

    @Lob
    @javax.persistence.Lob
    用于标注字段类型为Clob和Blob类型
    Clob(Character Large Ojects)类型是长字符串类型,实体的类型可为char[]、Character[]、或者String类型
    Blob(Binary Large Objects)类型是字节类型,实体的类型可为byte[]、Byte[]、或者实现了Serializable接口的类。
    通常使用惰性加载的方式, @Basic(fetch=FetchType.LAZY)

    @SecondaryTable 
    @javax.persistence.SecondaryTable
    将一个实体映射到多个数据库表中
    如:

    复制代码
    @Entity
    @SecondaryTables({ 
    @SecondaryTable(name = "Address"), 
        @SecondaryTable(name = "Comments") 
    })
    public class Forum implements Serializable {
    @Column(table = "Address", length = 100) 
    private String street; 
    @Column(table = "Address", nullable = false) 
    private String city; 
    @Column(table = "Address") 
    private String conutry; 
    @Column(table = "Comments") 
    private String title; 
    @Column(table = "Comments") 
    private String Comments; 
    @Column(table = "Comments") 
    }
    复制代码

    table属性的值指定字段存储的表名称 没有用 @Column 注解改变属性默认的字段将会存在于 Forum 表

    @Index

    给某一字段加索引

    例:

    @Table(name = "tab_developer", indexes = {@Index(columnList = "username")})

    根据注解,将会给username字段加上索引

    每天不用多,进步一点点就够了
    
    
  • 相关阅读:
    (转)Java线程:线程的同步与锁
    (转)线程栈模型与线程的变量、线程状态转换
    (转)概念与原理
    Oracle 技术支持之现场优化的思维路径
    oracle复合索引的选择和使用
    oracle中sql执行性能关注点
    oracle中位图索引和B-tree索引的区别
    oracle锁表
    oracle索引的理解
    oracle海量数据中提升创建索引的速度
  • 原文地址:https://www.cnblogs.com/jianyi12/p/6003707.html
Copyright © 2011-2022 走看看