数据库配置
# 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 注解。

1、建立实体类

使用 @Entity 注解(javax.persistence.Entity,后面如无 特别说明,注解都来自 javax.persistence包)。

@Entity
@Data
public class User {

默认建立表名为 user(全小写),可以使用 name属性指定表名。

@Entity(name="user2")
@Data
public class User {

上面两种情况下建立的 两张表 如下:

2、主键id

使用 @Id 注解 即可;

使用 @GeneratedValue 注解,是配置 主键的 自增策略;

@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

对于MySQL,不是每种都支持( TODO )。

3、复合主键

@PrimaryKeyJoinColumns、@PrimaryKeyJoinColumn 注解。

4、普通字段

4.1、使用 @Column注解

@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 和 其它属性的配置 冲突 时,如何建立字段?

4.2、不使用 @Column注解

// 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)。

4.3、枚举类型

// 枚举类 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)

4.4、创建时间、最后更新时间

// 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 |

4.5、@Transient

指明字段不存库,也就不会在数据表中建立字段。

// User.java
@Transient
private String abcNotInDb;

检查数据表,没有发现对应字段,符合预期。

4.6、对象类型属性

比如,存取用户地址,地址中包含 省市区等,怎么处理呢?

如下: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个字段:来自博客园

4.7、对象类型属性-JSON类型(MySQL)

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              |                             |

》》》全文完《《《来自博客园

1、JPA对象型属性操作

2、SpringBoot+MYSQL 配置支持json数据格式

发布本文时,还未细看,里面用了 mybatis。

3、MySQL 5.7 json jpa_spring data jpa + mysql使用json 类型