与休眠Envers组合表 [英] Composite table with Hibernate Envers
问题描述
我有一个包含一个额外列的复合表的应用程序。它一切正常,直到我们添加Hibernate Envers(@Audited)。
org.hibernate.MappingException:无法读取映射的属性for responseDomainCodes in no.pack.response.ResponseDomainCode
如果需要,我很乐意提供更详细的信息,但是,此时我我不确定什么是相关的。
这些表看起来像这样,是一个非常标准的组合键表,只有一个额外的列。
数据库模式
+ -------- --- + --------- +
| CODE | TYPE |
+ ----------- + --------- +
|类别| VARCHAR |
|代码| VARCHAR |
+ ----------- + --------- +
|
|
+ ---------------------- + --------- +
| RESPONSE_DOMAIN_CODE | TYPE |
+ ---------------------- + --------- +
| response_domain_id | KEY |
| code_id | KEY |
|等级| VARCHAR |
+ ---------------------- + --------- +
|
|
+ -------------------- + ------ +
| RESPONSE_DOMAIN | TYPE |
+ -------------------- + ------ +
| response_domain_id | PK |
| response_kind_id | FK |
+ -------------------- + ------ +
ResponseDomain.java
@Entity
@Table(name =responseDomain)
public class ResponseDomain implements Serializable {
@Id
@Column(name =responseDomain_id)
@GeneratedValue (strategy = GenerationType.AUTO)
private长ID;
@ManyToOne
@JoinColumn(name =respons_kind_id)
私人ResponseKind responseKind;
@OneToMany(fetch = FetchType.EAGER,mappedBy =pk.responseDomain,cascade = CascadeType.ALL)
private Set< ResponseDomainCode> responseDomainCodes = new HashSet<>();
//省略休息。
}
Code.java
@Entity
@Table(name =code)
public class Code implements Serializable {
@Id
@Column(name =code_id)
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
私人字符串类别;
私人字符串代码;
@OneToMany(fetch = FetchType.EAGER,mappedBy =pk.code,cascade = CascadeType.ALL)
private Set< ResponseDomainCode> responseDomainCodes = new HashSet<>();
//省略休息
}
ResponseDomainCode .java
@Entity
@Table(name =responseDomain_code)
@ AssociationOverrides(value = {
@AssociationOverride(name =pk.responseDomain,
joinColumns = @JoinColumn(name =responseDomain_id)),
@AssociationOverride(name =pk.code ,
joinColumns = @JoinColumn(name =code_id))
})
public class ResponseDomainCode implements Serializable {
$ b $ @EmbeddedId
private ResponseDomainCodeId pk = new ResponseDomainCodeId();
@Column(name =rank)
private String rank;
public ResponseDomainCodeId getPk(){
return pk;
}
public void setPk(ResponseDomainCodeId pk){
this.pk = pk;
}
public String getRank(){
return rank;
}
public void setRank(String rank){
this.rank = rank;
}
@Transient
public ResponseDomain getResponseDomain(){
return getPk()。getResponseDomain();
}
public void setResponseDomain(ResponseDomain responseDomain){
this.getPk()。setResponseDomain(responseDomain); (
)
@Transient
public Code getCode(){
return getPk()。getCode();
}
public void setCode(Code code){
this.getPk()。setCode(code);
}
//省略休息
}
ResponseDomainCodeId.java
@Embeddable
public class ResponseDomainCodeId implements Serializable {
@ManyToOne
私人ResponseDomain responseDomain;
@ManyToOne
私人代码;
public ResponseDomainCodeId(){
}
public ResponseDomain getResponseDomain(){
return responseDomain;
}
public void setResponseDomain(ResponseDomain responseDomain){
this.responseDomain = responseDomain;
}
public Code getCode(){
return code;
}
public void setCode(Code code){
this.code = code;
}
//省略休息
}
在@adamw的帮助下,我设法解决了这个问题,通过改变我的映射。
不用复合键,生成具有自己唯一ID的表。
+ --------------- ------- + ------------ +
| RESPONSE_DOMAIN_CODE | TYPE |
+ ---------------------- + ------------ +
| id | PK(BIGINT)|
| response_domain_id | BIGINT |
| code_id | BIGINT |
|等级| VARCHAR |
+ ---------------------- + ------------ +
$ c $现在不是使用@Embeddable和@EmbeddedId,而是在任何一方都有@ManyToOne和@OneToMany注解,并且基于ResponseDomain进行查询。
p>
这样可以使用Hibernate Envers在这样的关系中实现完整版审计控制。
我希望这会对有人在某个时候。
I have an application with a composite table holding one extra column. It all works fine, until we add Hibernate Envers (@Audited).
org.hibernate.MappingException: Unable to read the mapped by attribute for responseDomainCodes in no.pack.response.ResponseDomainCode
I am happy to provide more detailed information if necessary, however, at this time I am not sure what would be relevant.
The tables look like this, and is a pretty standard composite key table, with one extra column.
Database schema
+-----------+---------+
| CODE | TYPE |
+-----------+---------+
| category | VARCHAR |
| code | VARCHAR |
+-----------+---------+
|
|
+----------------------+---------+
| RESPONSE_DOMAIN_CODE | TYPE |
+----------------------+---------+
| response_domain_id | KEY |
| code_id | KEY |
| rank | VARCHAR |
+----------------------+---------+
|
|
+--------------------+------+
| RESPONSE_DOMAIN | TYPE |
+--------------------+------+
| response_domain_id | PK |
| response_kind_id | FK |
+--------------------+------+
ResponseDomain.java
@Entity
@Table(name = "responseDomain")
public class ResponseDomain implements Serializable {
@Id
@Column(name = "responseDomain_id")
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@ManyToOne
@JoinColumn(name = "respons_kind_id")
private ResponseKind responseKind;
@OneToMany(fetch = FetchType.EAGER, mappedBy = "pk.responseDomain", cascade = CascadeType.ALL)
private Set<ResponseDomainCode> responseDomainCodes = new HashSet<>();
//Omitted rest.
}
Code.java
@Entity
@Table(name = "code")
public class Code implements Serializable {
@Id
@Column(name = "code_id")
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String category;
private String code;
@OneToMany(fetch = FetchType.EAGER, mappedBy = "pk.code", cascade = CascadeType.ALL)
private Set<ResponseDomainCode> responseDomainCodes = new HashSet<>();
//Omitted rest
}
ResponseDomainCode.java
@Entity
@Table(name = "responseDomain_code")
@AssociationOverrides(value = {
@AssociationOverride(name = "pk.responseDomain",
joinColumns = @JoinColumn(name = "responseDomain_id")),
@AssociationOverride(name = "pk.code",
joinColumns = @JoinColumn(name = "code_id"))
})
public class ResponseDomainCode implements Serializable {
@EmbeddedId
private ResponseDomainCodeId pk = new ResponseDomainCodeId();
@Column(name = "rank")
private String rank;
public ResponseDomainCodeId getPk() {
return pk;
}
public void setPk(ResponseDomainCodeId pk) {
this.pk = pk;
}
public String getRank() {
return rank;
}
public void setRank(String rank) {
this.rank = rank;
}
@Transient
public ResponseDomain getResponseDomain() {
return getPk().getResponseDomain();
}
public void setResponseDomain(ResponseDomain responseDomain) {
this.getPk().setResponseDomain(responseDomain);
}
@Transient
public Code getCode() {
return getPk().getCode();
}
public void setCode(Code code) {
this.getPk().setCode(code);
}
//Omitted rest
}
ResponseDomainCodeId.java
@Embeddable
public class ResponseDomainCodeId implements Serializable {
@ManyToOne
private ResponseDomain responseDomain;
@ManyToOne
private Code code;
public ResponseDomainCodeId() {
}
public ResponseDomain getResponseDomain() {
return responseDomain;
}
public void setResponseDomain(ResponseDomain responseDomain) {
this.responseDomain = responseDomain;
}
public Code getCode() {
return code;
}
public void setCode(Code code) {
this.code = code;
}
//Omitted rest
}
解决方案 With the help of @adamw I managed to solve this, by changing my mapping.
Instead of using a composite key, a table with its own unique ID was generated.
+----------------------+------------+
| RESPONSE_DOMAIN_CODE | TYPE |
+----------------------+------------+
| id | PK(BIGINT) |
| response_domain_id | BIGINT |
| code_id | BIGINT |
| rank | VARCHAR |
+----------------------+------------+
Now instead of using @Embeddable and @EmbeddedId I have a @ManyToOne and @OneToMany annotation on either side, and query based on ResponseDomain.
This enable full version audit control using Hibernate Envers also in relations like this.
I hope this will be helpful for someone at some point.
这篇关于与休眠Envers组合表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!