常用注解有下面这些:
①:@Entity、@Table、@Id、@GeneratedValue、@Column、@Basic
②:@Transient 用于忽略某个属性,而不对该属性进行持久化操作
③:@Temporal
一、第①组注解
- @Entity 标注用于实体类声明语句之前,指出该Java 类为实体类,将映射到指定的数据库表。如声明一个实体类 Customer,它将映射到数据库中的 customer 表上。
-
@Table,当实体类与其映射的数据库表名不同名时需要使用 @Table 标注说明,该标注与 @Entity 标注并列使用,置于实体类声明语句之前,可写于单独语句行,也可与声明语句同行。 @Table 标注的常用选项是 name,用于指明数据库的表名。
-
@Id 标注用于声明一个实体类的属性映射为数据库的主键列。该属性通常置于属性声明语句之前,可与声明语句同行,也可写在单独行上。 @Id标注也可置于属性的getter方法之前。
- @GeneratedValue 用于标注主键的生成策略,通过 strategy 属性指定。默认情况下,JPA 自动选择一个最适合底层数据库的主键生成策略:SqlServer 对应 identity,MySQL 对应 auto increment。
在 javax.persistence.GenerationType 中定义了以下几种可供选择的策略:
—— IDENTITY:采用数据库 ID自增长的方式来自增主键字段,Oracle 不支持这种方式;
—— AUTO: JPA自动选择合适的策略,是默认选项;
—— SEQUENCE:通过序列产生主键,通过 @SequenceGenerator 注解指定序列名,MySql 不支持这种方式
—— TABLE:通过表产生主键,框架借由表模拟序列产生主键,使用该策略可以使应用更易于数据库移植(TABLE生成主键将会在后面详细讲解)。
- @Basic 表示一个简单的属性到数据库表的字段的映射,对于没有任何标注的 getXxxx() 方法,默认即为@Basic
—— fetch: 表示该属性的读取策略,有 EAGER 和 LAZY 两种,分别表示主支抓取和延迟加载,默认为 EAGER.
—— optional: 表示该属性是否允许为null, 默认为true
-
@Column,当实体的属性与其映射的数据库表的列不同名时需要使用此注解说明,该属性通常置于实体的属性声明语句之前,还可与 @Id 标注一起使用。
—— name 属性,用于设置映射数据库表的列名。此外,该标注还包含其它多个属性,如:unique 、nullable、length 等。
—— columnDefinition 属性: 表示该字段在数据库中的实际类型。
a、通常 ORM 框架可以根据属性类型自动判断数据库中字段的类型,但是对于Date类型仍无法确定数据库中字段类型究竟是DATE,TIME还是TIMESTAMP。
b、此外,String的默认映射类型为VARCHAR, 如果要将 String 类型映射到特定数据库的 BLOB 或TEXT 字段类型。
—— @Column 标注也可置于属性的getter方法之前
二、第②组注解
- 表示该属性并非一个到数据库表的字段的映射,ORM框架将忽略该属性。其作用类似于序列化中的@Transient注解。
- 如果一个属性并非数据库表的字段映射,就务必将其标示为@Transient;否则,ORM框架默认其注解为@Basic
三、第③组注解
-
在核心的 Java API 中并没有定义 Date 类型的精度(temporal precision)。而在数据库中,表示 Date 类型的数据有 DATE, TIME, 和 TIMESTAMP 三种精度(即单纯的日期,时间,或者两者 兼备). 在进行属性映射时可使用@Temporal注解来调整精度。
四、接下来就是修改 2、JPA的HelloWorld 中的实体类Customer.java,将上面的注解都使用一遍,看看实际的效果:
1 package com.magicode.jpa.helloworld; 2 3 import java.util.Date; 4 5 import javax.persistence.Column; 6 import javax.persistence.Entity; 7 import javax.persistence.GeneratedValue; 8 import javax.persistence.GenerationType; 9 import javax.persistence.Id; 10 import javax.persistence.Table; 11 import javax.persistence.Temporal; 12 import javax.persistence.TemporalType; 13 import javax.persistence.Transient; 14 15 /** 16 * @Entity 用于注明该类是一个实体类 17 * @Table(name="t_customer") 表明该实体类映射到数据库的 t_customer 表 18 */ 19 @Table(name="t_customer") 20 @Entity 21 public class Customer { 22 23 private Integer id; 24 private String lastName; 25 26 private String email; 27 private int age; 28 29 private Date birthday; 30 31 private Date createdTime; 32 33 /** 34 * @GeneratedValue(strategy=GenerationType.AUTO) 指明主键生成策略为AUTO 35 * @Id 表明实体类的主键 36 */ 37 @GeneratedValue(strategy=GenerationType.AUTO) 38 @Id 39 public Integer getId() { 40 return id; 41 } 42 43 /** 44 * @Column 指明lastName属性映射到表的 LAST_NAME 列中 45 * 同时还可以指定其长度、能否为null等数据限定条件 46 */ 47 @Column(name="LAST_NAME", length=50, nullable=false) 48 public String getLastName() { 49 return lastName; 50 } 51 52 /** 53 * 利用 @Temporal 来限定birthday为DATE型 54 */ 55 @Column(name="birthday") 56 @Temporal(TemporalType.DATE) 57 public Date getBirthday() { 58 return birthday; 59 } 60 61 /* 62 * 通过 @Column 的 columnDefinition 属性将CREATED_TIME列 63 * 映射为“DATE”类型 64 */ 65 @Column(name="CREATED_TIME", columnDefinition="DATE") 66 public Date getCreatedTime() { 67 return createdTime; 68 } 69 70 /* 71 * 通过 @Column 的 columnDefinition 属性将email列 72 * 映射为“TEXT”类型 73 */ 74 @Column(columnDefinition="TEXT") 75 public String getEmail() { 76 return email; 77 } 78 79 /* 80 * 工具方法,不需要映射为数据表的一列 81 */ 82 @Transient 83 public String getInfo(){ 84 return "lastName: " + lastName + " email: " + email; 85 } 86 87 public int getAge() { 88 return age; 89 } 90 91 public void setId(Integer id) { 92 this.id = id; 93 } 94 95 public void setLastName(String lastName) { 96 this.lastName = lastName; 97 } 98 99 public void setEmail(String email) { 100 this.email = email; 101 } 102 103 public void setAge(int age) { 104 this.age = age; 105 } 106 107 public void setBirthday(Date birthday) { 108 this.birthday = birthday; 109 } 110 111 public void setCreatedTime(Date createdTime) { 112 this.createdTime = createdTime; 113 } 114 115 }
在main方法中的测试不变,只是在持久化customer的时候添加两行代码:
// 4、调用EntityManager的persist方法完成持久化过程 Customer customer = new Customer(); customer.setAge(9); customer.setEmail("Tom@163.com"); customer.setLastName("Tom"); //添加1 customer.setBirthday(new Date()); //添加2 customer.setCreatedTime(new Date()); em.persist(customer);
对Customer.java做如下几点说明总结:
①、对getInfo()方法作为一个工具方法,不需要映射到数据库中。所以,使用了@Transient,表示在持久化的时候忽略它。否则,JPA会默认getInfo方法使用了默认的@Basic注解,而将其持久化到数据库的info列中。
②、getBirthday()方法上使用了@Temporal(TemporalType.DATE)注解,表明在持久化过程中将birthday对应的数据存为DATE(即只有“年月日”)。
同样的效果体现在getCreatedTime方法上。虽然该方法没有使用@Temporal注解,但是@Column(name="CREATED_TIME", columnDefinition="DATE")
指明了“映射数据库列名为CREATED_TIME”、“对应列的数据类型为DATE型”
③、在getEmail()方法上使用了@Column(columnDefinition="TEXT"),指明email这一列的数据类型为“TEXT”(在存放大文本的时候使用)
④、从②和③可以看出,columnDefinition的取值就可以直接使用数据库原生的类型名字即可
⑤、如果没有使用@Column的name属性指定映射的列名,那么默认的命名方法为getter规则:getXxx对应的名字为xxx(也就是第一个字母变小写得到)
运行main方法以后建立的数据库如下:
再看看表的结构: