JPA
Java Persistence API----java持久化接口
Hibernate注解分类
-
类级别注解
-
@Entity
映射实体类
@Entity(name = "tableName")
name可选,对应数据库中的一个表,若表名与实体类名相同,则可以省略
注意:使用@Entity时必须指定实体类的主键属性
-
@Table
与@Entity配合使用,只能标注在实体class定义处,表示实体对应的数据库表的信息
@Table(name = "", schema = "",catalog = "")
name可选,映射表的名称,默认表名与实体名称一致,只有在不一致的情况下才需要指定表名
catelog(目录)可选,表示Catalog名称,默认为Catalog("")
sahema(模式)可选,表示Schema名称,默认为Schema("")
![](C:\Users\lirui\Desktop\java web\schema与catalog.png)
![](C:\Users\lirui\Desktop\java web\2.schema与catalog.png)
-
@Embeddable 嵌入类
表示一个非Entity类,可以嵌入到另一个Entity类中作为属性而存在
-
-
属性级别注解
-
添加方式
- 写在属性上面
- 写在属性的get访问器上面
-
@Id
必须,定义了映射到数据库表的主键属性,一个实体类可以有一个或多个属性被映射成主键
注意:
1.如果有多个属性定义为主键属性,该实体类必须实现Serializable接口
2.字符串作为主键,长度不能过长,需要指定长度 @Column(length=8)
@SequenceGenerator
-
@GeneratedValue
参考:http://blog.csdn.net/fancylovejava/article/details/7438660@GeneratedValue(strategy=GenerationType,generator = "")
可选,用于定义主键生成策略
strategy
表示主键生成策略,取值有:
1.GenerationType.AUTO:根据底层数据库自动选择(默认,mysql默认为自动增长型)
2.GenerationType.INDENTITY:根据数据库Identity字段生成
3.GenerationType.SEQUENCE:使用Sequence来决定主键的取值
4.GenerationType.TABLE:使用指定表来决定主键取值,结合@TableGenerator使用
@Id @TableGenerator(name="tab_cat_gen",allocationSize=1) @GeneratedValue(strategy=GenerationType.TABLE)
generator
表示主键的生成器名称,这个属性通常和ORM框架相关,例如Hibernate可以指定uuid等主键的生成方式
主键为String,使用手工设置主键的方式,定义如下:
@Id @GeneratedValue(generator = "生成器名称") @GenericGenerator(name = "生成器名称",strategy = "assigned") @Column(length = 8)
-
@Column
可将属性映射到列,使用该注解来覆盖默认值,描述了数据库表中该字段的详细定义,这对于根据JPA注解生成的数据库表结构的工具非常有作用
name:可选,表示数据库表中该字段的名称,默认情形下属性名称一致
nullable:可选,表示该字段是否允许为null,默认为true
unique:可选,表示该字段是否为唯一标识,默认为false
length:可选,表示该字段大小,仅对String类型的字段有效,默认为255(若为主键不能使用默认值)
insertable:可选,表示在ORM框架执行插入操作时,该字段是否应出现在Insetrt语句中,默认为true
updateable:可选,表示在ORM框架执行更新操作时,该字段是否应出现在UPDATE语句中,默认为true。对于一经创建就不可以更改的字段,该属性非常有用
-
@Embedded
用于注解属性,表示该属性的类是嵌入类,注意同时嵌入类也必须标注@Embeddable注解
-
@EmbeddedId
使用嵌入式主键类实现复合主键
注意:嵌入式主键类必须实现Serializable接口,必须有默认的public 无参构造方法,必须覆盖equals和hashCode方法,使用@Embeddable注解嵌入式主键类
@Lob
@Version
@Basic
-
@Transient
可选,表示该属性并非一个到数据库表的字段的映射,ORM将忽略该属性,如果一个属性并非数据库表的字段映射,就务必标示为@Transient,否则ORM框架默认其注解为@Basic
-
-
映射关系注解
备注:cascade定义级联
mappedBy定义外键关系维护,使用该注解的一方不进行外键维护,所以,所以推荐级联方定义在另一方,使另一方维护外键,进行级联
-
一对一单向外键
主表类A与从表类B的主键值相对应
主表A: @OneToOne(cascade = CascadeType.ALL) @PrimaryKeyJoinColumn public B getB(){...} 从表B: 无
主表A中有一个从表属性是B类型的b
主表A: @OneToOne(cascade=CascadeType.All) @JoinColumn(name="pid",unique=true) public B getB(){...} 从表B: 无
注意:保存时应先保存外键对象,再保存主表对象
未测试
-
一对一双向外键关联
双向关联必须设置mappedBy属性,因为双向关联只能交一方控制,不可能双方都设置外间保存关联关系,否则双方都无法保存
主表A中有一个从表属性是B类型的b,同时,从表B中有一个主表属性是A类型的a
主表A: @OneToOne(cascade = CascadeType.ALL) @JoinColumn(name="主表外键")//这里指定的是数据库中的外键字段。 public B getB(){...} 从表B: @OneToOne(mappedBy = "b") public A getA(){...}
注意:@JoinColumn是可选的。默认值是从表变量名+"_"+从表的主键(注意,这里加的是主键。而不是主键对应的变量)。
未测试
-
一对一单向外键联合主键
- 创建主键类,主键类必须实现Serializable接口,重写hashCode()和equals()方法,并添加注解@Embeddable注解
- 实体类中主键添加@EmbeddedId注解
未测试
-
多对一单向外键关联
多方有一方的引用
多方 @ManyToOne(cascade = {CascadeType.ALL},fetch = FetchType.EAGER) @JoinColumn(name = "外键名",referencedColumnName = "关联表的列名") private One one; 一方: 无
测试通过,cascade定义级联,可在多方添加cascade,添加后可以省略一方的保存,直接保存多方数据即可级联,也可不添加cascade
-
一对多单向外键关联
一方持有多方集合Set
一方 @OneToMany(cascade = {CascadeType.ALL},fetch = FetchType.LAZY) @JoinColumn(name = "外键名") private Set many=new HashSet<Many>(); 多方: 无
测试通过,cascade定义级联,可在一方添加cascade,添加后可以省略多方的保存,直接保存单方数据即可级联,也可不添加cascade
-
一对多双向外键关联
多方持有一方引用,一方持有多方集合Set
一方 @OneToMany(cascade = {CascadeType.ALL},fetch = FetchType.LAZY) @JoinColumn(name = "外键名") private Set many=new HashSet<Many>(); 多方 @ManyToOne(cascade = {CascadeType.ALL},fetch = FetchType.EAGER) @JoinColumn(name = "外键名",referencedColumnName = "关联表的列名") private One one; //备注:不推荐此种写法,推荐下方写法,因为下方方法采用了关系维护,使用多方维护关系,会省略update语句,提高执行效率
或
一方 @OneToMany(mappedBy = "one") private Set many=new HashSet<Many>(); 多方 @ManyToOne(cascade = CascadeType.ALL) @JoinColumn(name = "lkm_cust_id", referencedColumnName = "cust_id", nullable = false) private One one;
测试通过,cascade定义级联,cascade可以添加在维护外键的一方(多方),或均不添加,根据添加情况可简化保存代码
-
多对多单向外键关联
其中有一个多方持有另一个多方的集合对象
//关系属性
//EAGER: 查询时关联的数据也同时取出放入内存中,因为在内存里,所以在session外也可以取@ManyToMany @JoinTable(name="中间表名" ,joinColumns={@JoinColumn(name="自己的外键")} ,inverseJoinColumns={@JoinColumn(name="对方的外键")}) private Set many1=new HashSet<Many1>();
备注:JoinTable用于维护中间表,name中间表表名,两个外键: joinColumns=指向自己的外键 inverseJoinColumns=指向对方的外键
测试通过
-
多对多双向外键关联
双方持有对方集合
一方: @ManyToMany(mappedBy="") private Set many1=new HashSet<Many1>(); 另一方: @ManyToMany(cascade = CascadeType.ALL) @JoinTable(name="中间表名" ,joinColumns={@JoinColumn(name="自己的外键")} ,inverseJoinColumns={@JoinColumn(name="对方的外键")}) private Set many2=new HashSet<Many2>();
测试通过,cascade定义级联,cascade可以添加在维护外键的一方
-
中间表持有双方引用
-
新建复合主键(参考建立联合主键的第三种方式)
包含两个外键的普通javaBean对象(必须实现Serializable接口,必须有默认的public 无参构造方法,必须覆盖equals和hashCode方法)
引用复合对象类@IdClass(复合对象.class)
声明两个外键@Id注解
-
中间表持有双方引用并注解
@Entity @IdClass(SysUserRolePK.class) public class SysUserRole { private long roleId; private long userId; @Id @Column(name = "role_id") public long getRoleId() {...} public void setRoleId(long roleId) {...} @Id @Column(name = "user_id") public long getUserId() {...} public void setUserId(long userId) {...} @ManyToOne @JoinColumn(name = "role_id", referencedColumnName = "role_id", nullable = false) public SysRole getSysRoleByRoleId() { return sysRoleByRoleId; } @ManyToOne @JoinColumn(name = "user_id", referencedColumnName = "user_id", nullable = false) public SysUser getSysUserByUserId() { return sysUserByUserId; } }
-
-
联合主键
必须实现Serializable接口,必须有默认的public 无参构造方法,必须覆盖equals和hashCode方法
-
存在的意义(以下仅为猜测):
数据库通过主键来确定是不是同一条数据,在内存中则需要将主键映射成实现equals和hashCode方法的类,通过hashcode来确定是不是同一条数据
-
实现联合主键的三种方式
将联合主键的字段单独放在一个类中,该类需要实现java.io.Serializable接口并重写equals和hascode,再将该类注解为@Embeddable,最后在主类中(该类不包含联合主键类中的字段)保存该联合主键类的一个引用,并生成set和get方法,并将该引用注解为@Id
将联合主键的字段单独放在一个类中,该类需要实现java.io.Serializable接口并重写equals和hascode,最后在主类中(该类不包含联合主键类中的字段)保存该联合主键类的一个引用,并生成set和get方法,并将该引用注解为@EmbeddedId
-
将联合主键的字段单独放在一个类中,该类需要实现java.io.Serializable接口并要重写equals和hashcode.最后在主类中(该类包含联合主键类中的字段)将联合主键字段都注解为@Id,并在该类上方将上这样的注解:@IdClass(联合主键类.class)
@Entity @IdClass(SysUserRolePK.class) public class SysUserRole { private long roleId; private long userId; @Id @Column(name = "role_id") public long getRoleId() {...} public void setRoleId(long roleId) {...} @Id @Column(name = "user_id") public long getUserId() {...} public void setUserId(long userId) {...} }
public class SysUserRolePK implements Serializable { private long roleId; private long userId; @Column(name = "role_id") @Id //以上两行存在不存在均可 public long getRoleId() {...} public void setRoleId(long roleId) {...} @Column(name = "user_id") @Id //以上两行存在不存在均可 public long getUserId() {...} public void setUserId(long userId) {...} @Override public boolean equals(Object o) {...} @Override public int hashCode() {...} }