model相关
# 主键生成策略
JPA提供的四种标准用法为TABLE,SEQUENCE,IDENTITY,AUTO.
- TABLE:使用一个特定的数据库表格来保存主键。
- SEQUENCE:根据底层数据库的序列来生成主键,条件是数据库支持序列。
- IDENTITY:主键由数据库自动生成(主要是自动增长型),Oracle不支持这种方式。
- AUTO:主键由程序控制(也是默认的,在指定主键时,如果不指定主键生成策略,默认为AUTO)
# 1、同时支持自增和自定义设置主键值的策略
public class CustomIdGenerator extends IdentityGenerator {
public static final String STRATEGY = "com.zxp.model.support.CustomIdGenerator";
@Override
public Serializable generate(SharedSessionContractImplementor session, Object object) {
Object id = getFieldValue("id", object);
if (id != null) {
return (Serializable) id;
}
return super.generate(session, object);
}
private Object getFieldValue(@NonNull String fieldName, @NonNull Object object) {
Assert.notNull(fieldName, "FieldName must not be null");
Assert.notNull(object, "Object type must not be null");
Object value = null;
try {
String firstLetter = fieldName.substring(0, 1).toUpperCase();
String getter = "get" + firstLetter + fieldName.substring(1);
Method method = object.getClass().getMethod(getter);
value = method.invoke(object);
} catch (Exception e) {
e.printStackTrace();
}
return value;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# 2、雪花算法生成主键的策略
public class SnowflakeGenerator implements IdentifierGenerator {
public static final String STRATEGY = "com.zxp.model.support.SnowflakeGenerator";
@Override
public Serializable generate(SharedSessionContractImplementor session, Object object) throws HibernateException {
// 有自定义的id,就用自定义的
Object id = com.zxp.utils.ReflectionUtils.getFieldValue("id", object);
if (id != null) {
return (Serializable) id;
}
Snowflake snowflake = IdUtil.getSnowflake();
return snowflake.nextId();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
参考文章 :
JPA中使用 @GenericGenerator 自定义方式 生成 主键 ID_exception_index的博客-CSDN博客 (opens new window)
Long类型的主键,在序列化时,注意要用String方式序列化,以免丢失精度。
@JSONField(serializeUsing = ToStringSerializer.class) // 阿里fastjson
@JsonSerialize(using = com.fasterxml.jackson.databind.ser.std.ToStringSerializer.class) // objectMapper
1
2
2
# 枚举类型数据处理
# 常规方式
public class EnumConvert implements AttributeConverter<StatusEnum, Integer> {
@Override
public Integer convertToDatabaseColumn(StatusEnum attribute) {
return attribute.getValue();
}
@Override
public StatusEnum convertToEntityAttribute(Integer dbData) {
return StatusEnum.fromValue(dbData);
}
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
@Convert(converter = EnumConvert.class)
@Column(name = "STATUS")
private StatusEnum status;
1
2
3
2
3
参考文章 : 解决JPA的枚举局限性 - JPA映射枚举的最佳实现 - xiaoqhuang - 博客园 (cnblogs.com) (opens new window)
# 多类对应一张表
场景:博客系统里面,有文章Post、独立页面Sheet,这两个类,可以对应一个post表,通过类型来区分,在设置对象类属性的时候,可以设计文章Post、页面Sheet,以及公共的BasePost
@Data
@Entity(name = "BasePost")
@Table(name = "posts", indexes = {
@Index(name = "posts_type_status", columnList = "type, status"),
@Index(name = "posts_create_time", columnList = "create_time")})
@DiscriminatorColumn(name = "type", discriminatorType = DiscriminatorType.INTEGER,
columnDefinition = "int default 0")
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
public class BasePost extends BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY, generator = "custom-id")
@GenericGenerator(name = "custom-id", strategy = "run.halo.app.model.entity.support"
+ ".CustomIdGenerator")
private Integer id;
/**
* Post title.
*/
@Column(name = "title", nullable = false)
private String title;
/**
* Post status.
*/
@Column(name = "status")
@ColumnDefault("1")
private PostStatus status;
/**
* Post slug.
*/
@Column(name = "slug", unique = true)
private String slug;
/**
* Post editor type.
*/
@Column(name = "editor_type")
@ColumnDefault("0")
private PostEditorType editorType;
/**
* Original content,not format.
*/
@Column(name = "original_content", nullable = false)
@Lob
private String originalContent;
/**
* Cover thumbnail of the post.
*/
@Column(name = "thumbnail", length = 1023)
private String thumbnail;
/**
* Post visits.
*/
@Column(name = "visits")
@ColumnDefault("0")
private Long visits;
/**
* Whether to allow comments.
*/
@Column(name = "disallow_comment")
@ColumnDefault("0")
private Boolean disallowComment;
/**
* Likes
*/
@Column(name = "likes")
@ColumnDefault("0")
private Long likes;
/**
* Edit time.
*/
@Column(name = "edit_time")
@Temporal(TemporalType.TIMESTAMP)
private Date editTime;
/**
* Meta keywords.
*/
@Column(name = "meta_keywords", length = 511)
private String metaKeywords;
@Override
public void prePersist() {
super.prePersist();
if (editTime == null) {
editTime = getCreateTime();
}
if (status == null) {
status = PostStatus.DRAFT;
}
if (editorType == null) {
editorType = PostEditorType.MARKDOWN;
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108