JPA 部分注解

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/xiaoleizhanghahaha/article/details/84676979

@MappedSuperclass

      标注的实体类不会映射到数据库 也无需实现序列化接口 属性都会映射到子类中

@Entity(name=“UserEntity”)

对实体注释。任何Hibernate映射对象都要有这个注释,只能标注在实体的class定义处,表示实体对应的数据库表的信息。
不用name和@Table结合的话  默认类名的 SnakeCaseStrategy(命名策略 )为表名 
使用name不用@Table 默认name的 SnakeCaseStrategy(命名策略 )为表名

@Table(name = “UserEntity”,catalog="",schema="")

name  可选,表示表的名称。默认,表名和实体名称一致,只有在不一致的情况下才需要指定表名。
catalog:可选,表示Catalogs名称,默认为Catalog(“”)。属性表示实体指定的目录名
schema:可选,表示Schema名称,默认为Schema(“”)。属性表示实体指定数据库名所用的数据库模式
uniqueConstraints 用来批量命名唯一键 “mobile”, “email” 列加上注解 @Column(unique=true)
@Table(name=”an_user_table”, uniqueConstraints = {@UniqueConstraint(columnNames={“mobile”, “email”})}) 

@Inheritance(strategy = InheritanceType.JOINED)

在JPA中,实体继承关系的映射策略共有三种:单表继承策略(table per class)、Joined策略(table per subclass)和Table_PER_Class策略。

1.单表继承策略
    单表继承策略,父类实体和子类实体共用一张数据库表,在表中通过一列辨别字段来区别不同类别的实体。具体做法如下:

a.在父类实体的@Entity注解下添加如下的注解:
	@Inheritance(Strategy=InheritanceType.SINGLE_TABLE)
	@DiscriminatorColumn(name=”辨别字段列名”)
	@DiscriminatorValue(父类实体辨别字段列值)
b.在子类实体的@Entity注解下添加如下的注解:
	@DiscriminatorValue(子类实体辨别字段列值) 

定义了一个父类
    @Entity  
    @Inheritance(strategy = InheritanceType.SINGLE_TABLE)  
    @Table(name = "WINDOW_FILE")  
    @DiscriminatorColumn(name = "DISCRIMINATOR", discriminatorType = DiscriminatorType.STRING, length = 30)  
    @DiscriminatorValue("WindowFile")  
    public class WindowFile {  
  
    @Id  
    @GeneratedValue(strategy = GenerationType.AUTO)  
    private Integer id;  
  
    @Basic  
    @Column(name = "NAME")  
    private String name;  
  
    @Basic  
    @Column(name = "TYPE")  
    private String type;  
  
    @Basic  
    @Column(name = "DATE")  
    private Date date;  
    //省略get set  
}  

后定义2个子类
@Entity
@DiscriminatorValue(“Folder”)
public class Folder extends WindowFile {
@Basic
@Column(name = “FILE_COUNT”)
private Integer fileCount;
//省略get set
}

@Entity  
@DiscriminatorValue("Document")  
public class Document extends WindowFile {  
    @Basic  
    @Column(name = "SIZE")  
    private String size;  
    //省略get set  
}  
 以上通过列DISCRIMINATOR的不同,区分具体父子实体。

实际表结构如下:
WINDOW_FILE DISCRIMINATOR,ID,NAME,DATE,TYPE,SIZE,FILE_COUNT
当你使用WindowFile实体时,实际表的字段为DISCRIMINATOR=‘WindowFile’,SIZE与FILE_COUNT永远是空
当使用Folder实体时,DISCRIMINATOR=‘Folder’,SIZE永远是空,FILE_COUNT为实际值。
Document同理,与Folder类似。

2.Joined策略
父类实体和子类实体分别对应数据库中不同的表,子类实体的表中只存在其扩展的特殊属性,父类的公共属性保存在父类实体映射表中。具体做法:
@Inheritance(Strategy=InheritanceType.JOINED)
子类实体不需要特殊说明

@Entity  
@Table(name = "T_ANIMAL")  
@Inheritance(strategy = InheritanceType.JOINED)  
public class Animal {  
  
    @Id  
    @Column(name = "ID")  
    @GeneratedValue(strategy = GenerationType.AUTO)  
    private Integer id;  
  
    @Column(name = "NAME")  
    private String name;  
  
    @Column(name = "COLOR")  
    private String color;  
    //省略get set  
}  

@Entity  
@Table(name = "T_BIRD")  
@PrimaryKeyJoinColumn(name = "BIRD_ID")  
public class Bird extends Animal {  
  
	@Column(name = "SPEED")  
	private String speed;  
	//省略get set  
} 

@Entity  
@Table(name = "T_DOG")  
@PrimaryKeyJoinColumn(name = "DOG_ID")  
public class Dog extends Animal {  
  
    @Column(name = "LEGS")  
    private Integer legs;  
    //省略get set  
}  

实际表结构如下:
T_ANIMAL  ID,COLOR,NAME
T_BIRD  SPEED,BIRD(既是外键,也是主键)
T_DOG  LEGS,DOG_ID(既是外键,也是主键)

3.Table_PER_Class策略:
Table_PER_Class策略,父类实体和子类实体每个类分别对应一张数据库中的表,子类表中保存所有属性,包括从父类实体中继承的属性。具体做法:
只需在父类实体的@Entity注解下添加如下注解:

@Inheritance(Strategy=InheritanceType.TABLE_PER_CLASS)
	    @Entity  
    @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)  
    @Table(name = "T_VEHICLE")  
    public class Vehicle { // 基类  
        @Id  
        // @GeneratedValue  
        @Column(name = "ID")  
        private Integer id;  
      
    @Column(name = "SPEED")  
    private Integer speed;// 速度  
    //省略get set  
}  

@Entity  
@Table(name = "T_CAR")  
public class Car extends Vehicle {  
  
	@Column(name = "ENGINE")  
	private String engine;// 发动机  
	//省略get set  
} 
一旦使用这种策略就意味着你不能使用AUTO generator 和IDENTITY generator,即主键值不能采用数据库自动生成。
实际表结构如下:
T_VEHICLE  ID,SPEED
T_CAR  ID,SPEED,ENGINE

@SequenceGenerator(name = “ID_SEQ”, sequenceName = “SEQ_BDF2_USER”,allocationSize=1,initialValue=1, )

SEQ_BDF2_USER 这个序列数据库中要存在
标注在类上,要和@GeneratedValue 一起使用,
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "ID_SEQ")
 
标注在属性  @SequenceGenerator(name = "ID_SEQ", sequenceName = "SEQ_BDF2_USER",allocationSize=1,initialValue=1)
注意事项
    类上面声明序列可以在各个字段使用
    字段上声明的序列只能在当前字段使用
    @SequenceGenerator中allocationSize属性用来定义递增值
    如果主键为随机生成的,请检查是否定义allocationSize属性
    如果是其它数据库请修改主键策略GenerationType
strategy:表示主键生成策略,有AUTO,INDENTITY,SEQUENCE 和 TABLE 4种,分别表示让ORM框架自动选择,根据数据库的 Identity 字段生成,根据数据库表的 Sequence 字段生成,以有根据一个额外的表生成主键,默认为 AUTO。
generator:表示主键生成器的名称,这个属性通常和ORM框架相关,例如,Hibernate可以指定uuid等主键生成方式.

@id

@id定义了映射到数据库表的主键的属性,一个实体只能有一个属性被映射为主键。

@Basic(fetch=FetchType,optional=true)

@Basic表示一个简单的属性到数据库表的字段的映射,对于没有任何标注的getXxxx()方法,默认即为@Basic
fetch:表示该属性的读取策略,有EAGER和LAZY两种,分别表示主支抓取和延迟加载,默认为EAGER。
optional:表示该属性是否允许为null,默认为true。

@Column

可选
@Column描述了数据库表中该字段的详细定义,这对于根据JPA注解生成数据库表结构的工具非常有作用。
name:表示数据库表中该字段的名称,默认情形属性名称一致。
nullable:表示该字段是否允许为null,默认为true。
unique:表示该字段是否是唯一标识,默认为false。
length:表示该字段的大小,仅对String类型的字段有效。
insertable:表示在ORM框架执行插入操作时,该字段是否应出现INSETRT语句中,默认为true。
updateable:表示在ORM框架执行更新操作时,该字段是否应该出现在UPDATE语句中,默认为true。对于一经创建就不可以更改的字段,该属性非常有用,如对于birthday字段。
columnDefinition:表示该字段在数据库中的实际类型。通常ORM框架可以根据属性类型自动判断数据库中字段的类型,但是对于Date类型仍无法确定数据库中字段类型究竟是DATE,TIME还是TIMESTAMP。此外,String的默认映射类型为VARCHAR,如果要将String类型映射到特定数据库的BLOB或TEXT字段类型,该属性非常有用。

@Transient

可选
@Transient表示该属性并非一个到数据库表的字段的映射,ORM框架将忽略该属性。
如果一个属性并非数据库表的字段映射。就务必将其标示为@Transient。否则。ORM框架默认其注解为@Basic

@OneToOne(fetch=FetchType,cascade=CascadeType)

可选
@OneToOne描述一个一对一的关联
fetch:表示抓取策略,默认为FetchType.LAZY
cascade:表示级联操作策略

@ManyToOne(fetch=FetchType,cascade=CascadeType)

可选
@ManyToOne表示一个多对一的映射,该注解标注的属性通常是数据库表的外键
optional:是否允许该字段为null,该属性应该根据数据库表的外键约束来确定,默认为true
fetch:表示抓取策略,默认为FetchType.EAGER
cascade:表示默认的级联操作策略,可以指定为ALL,PERSIST,MERGE,REFRESH和REMOVE中的若干组合,默认为无级联操作
targetEntity:表示该属性关联的实体类型。该属性通常不必指定,ORM框架根据属性类型自动判断targetEntity。

@OneToMany(fetch=FetchType,cascade=CascadeType)

可选
@OneToMany描述一个一对多的关联,该属性应该为集体类型,在数据库中并没有实际字段。
fetch:表示抓取策略,默认为FetchType.LAZY,因为关联的多个对象通常不必从数据库预先读取到内存
cascade:表示级联操作策略,对于OneToMany类型的关联非常重要,通常该实体更新或删除时,其关联的实体也应当被更新或删除
例如:实体User和Order是OneToMany的关系,则实体User被删除时,其关联的实体Order也应该被全部删除

@ManyToMany 描述一个多对多的关联.多对多关联上是两个一对多关联,但是在ManyToMany描述中,中间表是由ORM框架自动处理

targetEntity:表示多对多关联的另一个实体类的全名,例如:package.Book.class
mappedBy:表示多对多关联的另一个实体类的对应集合属性名称
两个实体间相互关联的属性必须标记为@ManyToMany,并相互指定targetEntity属性,
需要注意的是,有且只有一个实体的@ManyToMany注解需要指定mappedBy属性,指向targetEntity的集合属性名称
利用ORM工具自动生成的表除了User和Book表外,还自动生成了一个User_Book表,用于实现多对多关联

@JoinColumn

可选
@JoinColumn和@Column类似,介量描述的不是一个简单字段,而一一个关联字段,例如.描述一个@ManyToOne的字段.
name:该字段的名称.由于@JoinColumn描述的是一个关联字段,如ManyToOne,则默认的名称由其关联的实体决定.
例如,实体Order有一个user属性来关联实体User,则Order的user属性为一个外键,
其默认的名称为实体User的名称+下划线+实体User的主键名称
@JoinTable(name = “student_teacher”, inverseJoinColumns = @JoinColumn(name = “tid”), joinColumns = @JoinColumn(name = “sid”))
可选
由第三张表来维护两张表的关系
name:是关系表的名字
joinColumns:自己这一端的主键
inverseJoinColumns:对方的主键

@Embedded @Embededable

在使用实体类生成对应的数据库表时,很多的时候都会遇到这种情况:
在一个实体类中引用另外的实体类,一般遇上这种情况,我们使用@OneToOne、@OneToMany、@ManyToOne、@ManyToMany这4个注解比较多,但是好奇害死猫,
除了这四个有没有别的使用情况,尤其是一个实体类要在多个不同的实体类中进行使用,而本身又不需要独立生成一个数据库表,这就是需要@Embedded、@Embeddable的时候了,下面分成4类来说明在一个实体类中引用另外的实体类的情况,具体的数据库环境是MySQL 5.7。

@Embedded将几个字段组合成一个类,并作为整个Entity的一个属性.
例如User包括id,name,city,street,zip属性.
我们希望city,street,zip属性映射为Address对象.这样,User对象将具有id,name和address这三个属性.
Address对象必须定义为@Embededable
案例:
Address类
public class Address implements Serializable{
private static final long serialVersionUID = 8849870114128959929L;
private String country;
private String province;
private String city;
private String detail;
//setter、getter
}
Person类:
@Entity
public class Person implements Serializable{
private static final long serialVersionUID = 8849870114127659929L;
@Id
@GeneratedValue
private Long id;
@Column(nullable = false)
private String name;
@Column(nullable = false)
private Integer age;
private Address address;
//setter、getter
}
1、 两个注解全不使用 表中有id,age,name,address
Address属性字段会映射成tinyblob类型的字段,这是用来存储不超过255字符的二进制字符串的数据类型,显然我们通常不会这么使用
2、 只使用@Embeddable 和单独使用 @Embedded 效果是一样的。

覆盖@Embeddable类中字段的列属性
这里就要使用另外的两个注解@AttributeOverrides和@AttributeOverride,这两个注解是用来覆盖@Embeddable类中字段的属性的。

@AttributeOverrides:里面只包含了@AttributeOverride类型数组;
@AttributeOverride:包含要覆盖的@Embeddable类中字段名name和新增的@Column字段的属性;

@Entity 
public class Person implements Serializable{ 
private static final long serialVersionUID = 8849870114127659929L;
 @Id 
 @GeneratedValue 
 private Long id; 
 @Column(nullable = false)
 private String name; 
 @Column(nullable = false) 
 private Integer age; 
 @Embedded 
 @AttributeOverrides({@AttributeOverride(name="country", column=@Column(name = "person_country", length = 25, nullable = false)), @AttributeOverride(name="city", column = @Column(name = "person_city", length = 15))}) 
 private Address address; //setter、getter }

Address类如下:

@Embeddable 
public class Address implements Serializable{
private static final long serialVersionUID = 8849870114128959929L;
	 @Column(nullable = false) 
	 private String country; 
	 @Column(length = 30) 
	 private String province; 
	 @Column(unique = true)
	 private String city; 
	 @Column(length = 50) 
	 private String detail; 
	 //setter、getter 
 }

多层嵌入实体类属性

上面所有的例子都是使用两层实体类嵌入,其实这种实体类的嵌入映射是可以使用多层的,具体的例子如下。
我们新建立一个类Direction表示方位如下
@Embeddable public class Direction implements Serializable{ 
	@Column(nullable = false) 
	private Integer longitude;
	private Integer latitude;
 }
Address如下:
@Embeddable public class Address implements Serializable{ 
private static final long serialVersionUID = 8849870114128959929L;
 @Column(nullable = false) 
 private String country; 
 @Column(length = 30)
 private String province; 
 @Column(unique = true)
 private String city; 
 @Column(length = 50) 
 private String detail; 
 @Embedded 
 private Direction direction; 
 }
Person类如下:
@Entity public class Person implements Serializable{ 
private static final long serialVersionUID = 8849870114127659929L; 
@Id 
@GeneratedValue 
private Long id; 
@Column(nullable = false)
 private String name;
 @Column(nullable = false)
 private Integer age; 
 @Embedded 
 @AttributeOverrides({@AttributeOverride(name="direction.latitude", column=@Column(name = "person_latitude")), @AttributeOverride(name="direction.longitude", column = @Column(name = "person_longitude"))}) 
 private Address address; 
 }
 
 在上面需要注意如下几点:
    在Person中定义Direction中的属性时,需要用”.”将所有相关的属性连接起来;
    在Direction中longitude属性定义为not null,但是由于使用了@AttributeOverride注解,其中虽然没有定义null属性,但是这时使用的是默认的nullable属性,默认为true;

@Table(indexes = { 
        @Index(name="studentAnswerQueIdIndex", columnList="studentAnswerQueId DESC"),
        @Index(name="questionConIdIndex", columnList="questionConId") 
        })

@Index(name = "questionConIdIndex")
标注在属性上

@Enumerated:

EnumType.STRING  指定数据库中存储的值为枚举值(MAN,WOMEN)
EnumType.ORDINAL 指定数据库中存储的值为索引值(MAN的索引值0,WOMEN索引值1)
@Enumerated(EnumType.STRING) @Column(length = 5,nullable = false)
Gender枚举类
public  enum  Gender {
      MAN,WOMEN
}

/设置默认值
    private Gender gender = Gender.MAN;
    public User() {
    }

//枚举类型不能为空,所以非空约束一定要加上
    @Enumerated(EnumType.STRING) @Column(length = 5,nullable = false)
    public Gender getGender() {
        return gender;
    }
https://www.yiibai.com/jpa/jpa-object-relational-mapping.html
https://blog.csdn.net/qq_32827261/article/details/74690867

@Type(type = DbEnumType.CLAZE, parameters = { @Parameter(name = “enumClass”, value = oStatus.CLAZE) })

    @Column(name = "source")
    @Type(type = DbEnumType.CLAZE, parameters = { @Parameter(name = "enumClass", value = Source.CLAZE) })
    public Source getSource() {
        return source;
    }

@JSONField(serialize = false)
@JsonIgnore
@Transient
public String getMobile() {
    return Mobile;
}

@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "type", discriminatorType = DiscriminatorType.INTEGER)
@Table(name = "location")
@SequenceGenerator(name = "seq_location", sequenceName = "seq_location")

@Index(name = "c_nos_idx")
@Basic(fetch = FetchType.LAZY)   
@Type(type="text")
@Column(name = "pall_nos")


@Basic(fetch = FetchType.LAZY)
@Type(type="text")
@Column(name = "summary")
public String getSummary() {
    return summary;
}



@Entity
@DiscriminatorValue(house.LOCATION_TYPE)
//@NamedQueries({
//        @NamedQuery(name = house.QUERY_WAREHOUSE_DTO, query = "SELECT NEW houseDto(e.id, e.externalId, e.name) from ahouse e") })

猜你喜欢

转载自blog.csdn.net/xiaoleizhanghahaha/article/details/84676979