如何正确地将 UUID 用作我的 @Entity 的 @Id?

huangapple go评论107阅读模式
英文:

How can I use an UUID as an @Id for my @Entity properly?

问题

我想将一个用户实体从Spring Boot存储到MySQL数据库中,并且我想将UUID作为Id使用。但是当我按照在线解决方案操作时,我只得到The userId doesn't have a default value错误。我就是找不出问题出在哪里。以下是代码部分:

用户实体:

@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "user")
@Data
public class User {

	@JsonProperty("userId")
	@Column(name = "userId", columnDefinition = "BINARY(16)")
	@GeneratedValue(generator = "uuid2")
	@GenericGenerator(name = "uuid2", strategy = "uuid2")
	@Id
	private UUID userId;
	
	@JsonProperty("email")
	@Column(name = "email", nullable = false)
	private String email;
	
	@JsonProperty("name")
	@Column(name = "name", nullable = false)
	String name;

	@JsonProperty("surname")
	@Column(name = "surname", nullable = false)
	String surname;

	@JsonProperty("password")
	@Column(name = "password", nullable = false)
	private String password;
}

MySQL表格:

create table if not exists user (
   userId binary(16) not null primary key,
   name varchar(80) not null,
   surname varchar(80) not null,
   email varchar(120) not null,
   password varchar(120) not null
);

错误信息:

SQL Error: 1364, SQLState: HY000

2020-07-23 15:31:29.234 ERROR 16336 --- [nio-8080-exec-1] o.h.engine.jdbc.spi.SqlExceptionHelper   : Field 'userId' doesn't have a default value
2020-07-23 15:31:29.251 ERROR 16336 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.orm.jpa.JpaSystemException: could not execute statement; nested exception is org.hibernate.exception.GenericJDBCException: could not execute statement] with root cause
英文:

I want to store a User entity from Spring Boot into a MySQL database and I want to use an UUID as an Id. But when I follow the online solutions I only get The userId doesn't have a default value. And I just can't figure out whats wrong. Here is the code:

User entity:

@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "user")
@Data
public class User {

	@JsonProperty("userId")
	@Column(name = "userId", columnDefinition = "BINARY(16)")
	@GeneratedValue(generator = "uuid2")
	@GenericGenerator(name = "uuid2", strategy = "uuid2")
	@Id
	private UUID userId;
	
	@JsonProperty("email")
	@Column(name = "email", nullable = false)
	private String email;
	
	@JsonProperty("name")
	@Column(name = "name", nullable = false)
	String name;

	@JsonProperty("surname")
	@Column(name = "surname", nullable = false)
	String surname;

	@JsonProperty("password")
	@Column(name = "password", nullable = false)
	private String password;
}

MySQL table:

create table if not exists user (
   userId binary(16) not null primary key,
   name varchar(80) not null,
   surname varchar(80) not null,
   email varchar(120) not null,
   password varchar(120) not null
);

The error message:

SQL Error: 1364, SQLState: HY000

2020-07-23 15:31:29.234 ERROR 16336 --- [nio-8080-exec-1] o.h.engine.jdbc.spi.SqlExceptionHelper   : Field 'userId' doesn't have a default value
2020-07-23 15:31:29.251 ERROR 16336 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.orm.jpa.JpaSystemException: could not execute statement; nested exception is org.hibernate.exception.GenericJDBCException: could not execute statement] with root cause

答案1

得分: 2

首先,我必须注意

> 根据JPA,只有以下类型可以用作标识属性类型:
> * 任何Java基本类型
> * 任何基本包装类型
> * java.lang.String
> * java.util.Date(TemporalType#DATE)
> * java.sql.Date
> * java.math.BigDecimal
> * java.math.BigInteger
>
> 在这个列表之外使用的任何类型作为标识属性将不具备可移植性

但是,Hibernate 支持 UUID 标识符值生成。这是通过其 org.hibernate.id.UUIDGenerator 标识符生成器来支持的。

您可以使用默认策略,即根据 IETF RFC 4122 的版本 4(随机)策略。

@Id
@Column(name = "userId", columnDefinition = "BINARY(16)")
@GeneratedValue
private UUID userId;

或者选择另一种策略,即基于 RFC 4122 版本 1(基于时间)策略(使用 IP 地址而不是 MAC 地址)。

@Id
@Column(name = "userId", columnDefinition = "BINARY(16)")
@GeneratedValue(generator = "custom-uuid")
@GenericGenerator(
	name = "custom-uuid",
	strategy = "org.hibernate.id.UUIDGenerator",
	parameters = {
		@Parameter(
			name = "uuid_gen_strategy_class",
			value = "org.hibernate.id.uuid.CustomVersionOneStrategy"
		)
	}
)
private UUID userId;
英文:

First of all I have to notice that:

> According to JPA only the following types should be used as identifier attribute types:
> * any Java primitive type
> * any primitive wrapper type
> * java.lang.String
> * java.util.Date (TemporalType#DATE)
> * java.sql.Date
> * java.math.BigDecimal
> * java.math.BigInteger
>
> Any types used for identifier attributes beyond this list will not be portable.

But, Hibernate supports UUID identifier value generation. This is supported through its org.hibernate.id.UUIDGenerator id generator.

You can use the default strategy, that is a version 4 (random) strategy according to IETF RFC 4122.

@Id
@Column(name = "userId", columnDefinition = "BINARY(16)")
@GeneratedValue
private UUID userId;

Or an alternative strategy which is a RFC 4122 version 1 (time-based) strategy (using IP address rather than mac address).

@Id
@Column(name = "userId", columnDefinition = "BINARY(16)")
@GeneratedValue(generator = "custom-uuid")
@GenericGenerator(
	name = "custom-uuid",
	strategy = "org.hibernate.id.UUIDGenerator",
	parameters = {
		@Parameter(
			name = "uuid_gen_strategy_class",
			value = "org.hibernate.id.uuid.CustomVersionOneStrategy"
		)
	}
)
private UUID userId;

huangapple
  • 本文由 发表于 2020年7月23日 22:01:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/63056093.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定