Spring DATA JPA:建立實體類
JAVA 8
Spring Boot 2.5.3
MySQL 5.7.21
---
注,本文程式碼使用了 org.projectlombok:lombok (版本 由 Spring Boot 指定)。
目錄
Spring Boot專案資料庫配置:
資料庫配置
# MySQL on Ubuntu spring.datasource.url=jdbc:mysql://mylinux:3306/jpa?serverTimezone=Asia/Shanghai spring.datasource.username=springuser spring.datasource.password=ThePassword #spring.datasource.driver-class-name =com.mysql.jdbc.Driver # This is deprecated spring.datasource.driver-class-name =com.mysql.cj.jdbc.Driver spring.jpa.hibernate.ddl-auto=update spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect # 開啟使用過程中執行的SQL語句 spring.jpa.show-sql: true
實體類都是 POJO 物件,因此使用了 lombok 的 @Data 註解。
使用 @Entity 註解(javax.persistence.Entity,後面如無 特別說明,註解都來自 javax.persistence包)。
@Entity
@Data
public class User {
預設建立表名為 user(全小寫),可以使用 name屬性指定表名。
@Entity(name="user2")
@Data
public class User {
上面兩種情況下建立的 兩張表 如下:
使用 @Id 註解 即可;
使用 @GeneratedValue 註解,是配置 主鍵的 自增策略;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
資料表中效果:
mysql> desc user; +------------------+--------------+------+-----+-------------------+-----------------------------+ | Field | Type | Null | Key | Default | Extra | +------------------+--------------+------+-----+-------------------+-----------------------------+ | id | bigint(20) | NO | PRI | NULL | auto_increment |
自增策略 可見 GenerationType 列舉類:
TABLE
SEQUENCE
IDENTITY
AUTO
對於MySQL,不是每種都支援(TODO)。
@PrimaryKeyJoinColumns、@PrimaryKeyJoinColumn 註解。
@Column(columnDefinition = "VARCHAR(100) NOT NULL")
private String firstName;
@Column(columnDefinition = "VARCHAR(100) NOT NULL")
private String lastName;
@Column(columnDefinition = "INT DEFAULT 0")
private Integer age;
資料表中效果:
mysql> desc user;
+------------------+--------------+------+-----+-------------------+-----------------------------+
| Field | Type | Null | Key | Default | Extra |
+------------------+--------------+------+-----+-------------------+-----------------------------+
| age | int(11) | YES | | 0 | |
| first_name | varchar(100) | NO | | NULL | |
| last_name | varchar(100) | NO | | NULL | |
除了上面使用的 columnDefinition屬性 外, @Column 還有其它屬性 來做配置。
@Column的name屬性用來自定義 資料表中欄位名稱。
問題:
1)columnDefinition 和 其它屬性的配置 一致 時,如何建立欄位?
2)columnDefinition 和 其它屬性的配置 衝突 時,如何建立欄位?
// User.java
private Integer property;
private Float height;
private Float weight;
private String slogan;
資料表中效果:
mysql> desc user;
+------------------+--------------+------+-----+-------------------+-----------------------------+
| Field | Type | Null | Key | Default | Extra |
+------------------+--------------+------+-----+-------------------+-----------------------------+
| height | float | NO | | NULL | |
| weight | float | NO | | NULL | |
| slogan | varchar(255) | YES | | NULL | |
| property | int(11) | YES | | NULL | |
預設值Default 都是 NULL,String型別 預設為 varchar(255)。
// 列舉類 UserSex.java
@Getter
public enum UserSex {
MALE(0, "MALE"),
FEMALE(1, "FEMALE");
private int code;
private String info;
private UserSex(int code, String info) {
this.code = code;
this.info = info;
}
}
// User.java
// 不使用 @Column 註解
private UserSex sex;
資料表中效果:
mysql> desc user;
+------------------+--------------+------+-----+-------------------+-----------------------------+
| Field | Type | Null | Key | Default | Extra |
+------------------+--------------+------+-----+-------------------+-----------------------------+
| sex | int(11) | YES | | NULL | |
資料表中型別為 int(11)。
實際儲存的資料為:0、1
mysql> select distinct sex from user;
+------+
| sex |
+------+
| 0 |
| 1 |
+------+
2 rows in set (0.00 sec)
// User.java
@Column(insertable = false, columnDefinition = "DATETIME DEFAULT NOW()")
private Date createTime;
@Column(insertable = false, updatable = false, columnDefinition = "DATETIME DEFAULT NOW() ON UPDATE NOW()")
private Date updateTime;
像上面一樣配置以後,就無需再 新增、更新 記錄時設定 這兩個欄位的值了。
資料表中效果:
mysql> desc user;
+------------------+--------------+------+-----+-------------------+-----------------------------+
| Field | Type | Null | Key | Default | Extra |
+------------------+--------------+------+-----+-------------------+-----------------------------+
| create_time | datetime | YES | | CURRENT_TIMESTAMP | |
| update_time | datetime | YES | | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
指明欄位不存庫,也就不會在資料表中建立欄位。
// User.java
@Transient
private String abcNotInDb;
檢查資料表,沒有發現對應欄位,符合預期。
比如,存取使用者地址,地址中包含 省市區等,怎麼處理呢?
如下:POJO物件中使用 @Embeddable,實體類中使用 @Embedded + @AttributeOverrides + @AttributeOverride。
// Address.java 4個屬性
@Data
@Embeddable
public class Address {
/**
* 郵政編碼
*/
@Column(updatable = false)
private String zipCode;
// 省市區3級
// 省
private String province;
// 市
private String city;
// 區
private String district;
}
// User.java
@Embedded
@AttributeOverrides({
@AttributeOverride(name="zipCode", column = @Column(name = "address_zip_code")),
@AttributeOverride(name="province", column = @Column(name = "address_province")),
@AttributeOverride(name="city", column = @Column(name = "address_city")),
@AttributeOverride(name="district", column = @Column(name = "address_district"))
})
private Address address;
資料表中效果:
mysql> desc user;
+------------------+--------------+------+-----+-------------------+-----------------------------+
| Field | Type | Null | Key | Default | Extra |
+------------------+--------------+------+-----+-------------------+-----------------------------+
| address_zip_code | varchar(255) | YES | | NULL | |
| address_city | varchar(255) | YES | | NULL | |
| address_district | varchar(255) | YES | | NULL | |
| address_province | varchar(255) | YES | | NULL | |
試錯:實體類中 不使用各個註解,只 使用Address物件時,也會生成資料表字段,但沒有address字首了。
增加一個 address2 屬性:
// User.java
private Address address2;
資料表中新增了4個欄位:來自部落格園
MySQL 5.7.8 開始提供 JSON型別。
注意,試驗前需要刪除 4.6節 生成的 city、district、province、zip_code 四個欄位。
// User.java
@Column(columnDefinition = "JSON")
private Address jsonAddress;
啟動專案:沒有發現建立 json_address 欄位。但是,生成了 city、district、province、zip_code 等4個欄位。
未成功!
自測給user表新增 JSON 型別欄位:成功。來自部落格園
mysql> alter table user add json1 JSON;
Query OK, 0 rows affected (0.04 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> desc user;
...
| json1 | json | YES | | NULL | |
+------------------+--------------+------+-----+-------------------+-----------------------------+
22 rows in set (0.00 sec)
這樣看來,是JPA不支援MySQL的JSON型別了。
和 下面的配置有關係嗎?TODO
// application.properties
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
試驗了參考文件3中的方法,實現了新增 JSON型別物件。
pom.xml中新增依賴包:
<dependency>
<groupId>com.vladmihalcea</groupId>
<artifactId>hibernate-types-52</artifactId>
<version>2.4.3</version>
</dependency>
最新版本依賴包:
複製 上面的 Address 建立 Address2類,但是,去掉其 @Embeddable 註解。
@Data
//@Embeddable // JSON型別時,需要刪除
//public class Address2 implements Serializable { // 不需要實現 Serializable介面
public class Address2 {
/**
*
*/
// private static final long serialVersionUID = 211030L;
/**
* 郵政編碼
*/
@Column(updatable = false)
private String zipCode2;
...
}
實體類新增:來自部落格園
// User.java
// Address屬性,無效,,會建立 Address下的 4個欄位
@Type(type = "json")
@Column(columnDefinition = "json")
private Address jsonAddress;
// Address2 屬性,有效,,會建立JSON型別欄位 json_address2
@Type(type = "json")
@Column(columnDefinition = "json")
private Address2 jsonAddress2;
上面的部分註解不是來自javax.persistence包:
import org.hibernate.annotations.Type;
import org.hibernate.annotations.TypeDef;
import com.vladmihalcea.hibernate.type.json.JsonStringType;
啟動專案,修改表的SQL日誌語句:來自部落格園
2021-10-30 10:58:15.409 INFO 19068 --- [ main] org.hibernate.dialect.Dialect :
HHH000400: Using dialect: org.hibernate.dialect.MySQL5InnoDBDialect
Hibernate: alter table user add column city varchar(255)
Hibernate: alter table user add column district varchar(255)
Hibernate: alter table user add column province varchar(255)
Hibernate: alter table user add column zip_code varchar(255)
Hibernate: alter table user add column json_address2 json
資料表中效果:來自部落格園
mysql> desc user;
+------------------+--------------+------+-----+-------------------+-----------------------------+
| Field | Type | Null | Key | Default | Extra |
+------------------+--------------+------+-----+-------------------+-----------------------------+
| city | varchar(255) | YES | | NULL | |
| district | varchar(255) | YES | | NULL | |
| province | varchar(255) | YES | | NULL | |
| zip_code | varchar(255) | YES | | NULL | |
| json_address2 | json | YES | | NULL | |
》》》全文完《《《來自部落格園
參考文件
好文。
2、SpringBoot+MYSQL 配置支援json資料格式
釋出本文時,還未細看,裡面用了 mybatis。
3、MySQL 5.7 json jpa_spring data jpa + mysql使用json 型別
好文
4、