mysql - 如何使用一个自动生成的值创建复合主键?
问题描述
I am trying to map entity with my existing database table which is having two primary keys.
Out of two keys, one primary key is auto generated.
I am using `Spring Boot`, `JPA`, `Hibernate` and `MySQL`. I have used `@IdClass` to map with the composite primary class (with public constructor, setter/getters, same property names, equals and hash code methods).
`org.springframework.data.repository.CrudRepository` save method to save the entity.
下面的代码片段。
@Entity
@Table(name = "data")
@IdClass(DataKey.class)
public class DeviceData {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="id")
private BigInteger id;
@Column(name="name")
private String name;
@Id
@Column(name="device_id")
private int deviceId;
getters/setters
}
public class DataKey implements Serializable {
private static final long serialVersionUID = 1L;
private BigInteger id;
private int deviceId;
//setter/getters
public DataKey() {
}
public DataKey(BigInteger id, int deviceId) {
this.id = id;
this.deviceId = deviceId;
}
public int hashCode() {
return Objects.hash(id, deviceId);
}
public boolean equals(Object obj) {
if (obj == this)
return true;
if (!(obj instanceof DataKey))
return false;
DataKey dk = (DataKey) obj;
return dk.id.equals(this.id) && dk.deviceId == (this.deviceId);}
}
I am using org.springframework.data.repository.CrudRepository save method for persisting the entity.
设备数据数据=新设备数据();
data.setName("device1"); data.setDeviceId("1123");
dao.save(数据);//dao 扩展 crudrepository 接口。
但我遇到以下错误:
org.springframework.orm.jpa.JpaSystemException: Could not set field
value [POST_INSERT_INDICATOR] value by reflection.[class DataKey.id]
setter of DataKey.id; nested exception is
org.hibernate.PropertyAccessException: Could not set field value
[POST_INSERT_INDICATOR] value by reflection : [class class DataKey.id]
setter of class DataKey.id.
原因:java.lang.IllegalArgumentException:无法将 java.math.BigInteger 字段 DataKey.id 设置为 org.hibernate.id.IdentifierGeneratorHelper$2
解决方案
我能够使用序列生成器解决它。
@Id
@SequenceGenerator(name="my_seq", sequenceName="my_db_table_seq", allocationSize=1)
@GeneratedValue(generator = "my_seq")
@Column(name = "id", updatable = false, nullable = false)
private BigInteger id
在我的情况下,我使用的是 Postgres,并且我的表SERIAL
作为列数据类型在表中也有相应的条目pg_catalog.pg_sequences
(例如my_db_table_seq
在我上面的示例中)。
如果你没有指定一个特定的命名序列生成器(并且只@GeneratedValue(strategy = GenerationType.SEQUENCE)
在你的@Id
列上使用),它看起来像 Hibernate 默认为一个被调用hibernate_sequence
的,我已经看到了一些建议运行 db 命令CREATE SEQUENCE hibernate_sequence START 1
以在数据库中创建它。但这将对通过 Hibernate 插入行的每个表使用相同的序列,因此可能不是一个好主意。最好使用在数据库中为该表创建的序列,然后使用@SequenceGenerator
注释明确。
@GeneratedValue(strategy = GenerationType.IDENTITY)
在具有 的实体上使用复合键似乎确实存在问题@IdClass
,所以如果 Hibernate 可以支持这一点会很好。
但看起来序列生成器是一种有效的解决方法,所以这就是我要使用的。
推荐阅读
- python - How to fix error running local Otsu threshold example?
- javascript - VS Code - 如何在搜索面板中隐藏文件路径
- ios - 每 n 天安排一次本地通知(时区安全)
- firebase - 颤振项目构建错误 - firebase_messaging-9.1.4 import com.google.firebase.iid.FirebaseInstanceId;
- python - Python 请求在换行符的标题中给出无效的返回字符或前导空格
- java - Spring Boot 应用程序无法在 Docker 中运行
- database - 在 Power Bi 中用一列制作两列
- html - Div 高度:100% 不适用于身体最小高度:100vh
- sql - 我正在尝试此查询来更改属性名称
- c# - 如何为与数据集关联的仪表板无缝更新 datagris