我正在研究一个我无法改变的遗留数据库。此数据库定期与辅助实例同步,辅助实例创建新条目。要使实体的主键对所有实例都是唯一的,所有实体都有复合主键,包括由其原始数据库生成的代理键和标识原始实例的服务器ID。
复合主键对于Hibernate / JPA来说不是问题,它看起来像这样:
@Embeddable
public class ID implements Serializable {
private Long autoin; // Surrogate key
private Integer serverId; // instance identifier
@Column(name = "autoin_fix")
public Long getAutoin() {
return this.autoin;
}
@Column(name = "servdat_fk")
public Integer getServerId() {
return this.serverId;
}
// ... setter, equals, hashCode ...
}
现在考虑以下实体:
@Entity
@Table(name = "LEADS")
public class Request {
private Long id;
private Article article;
private Location location;
@Id
@Column(name = "autoin_fix")
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "auto-increment")
@GenericGenerator(name = "auto-increment", strategy = "sequence",
parameters = @org.hibernate.annotations.Parameter(name = "sequence", value = "AUTOINCREMENT"))
public Long getId() {
return this.id;
}
@ManyToOne
@JoinColumns({
@JoinColumn(name = "artikel_fk", referencedColumnName = "autoin_fix",
insertable = false, updatable = false), // Here is the problem!
@JoinColumn(name = "servdat_fk", referencedColumnName = "servdat_fk",
insertable = false, updatable = false)
})
public Article getArticle() {
return this.article;
}
@ManyToOne
@JoinColumns({
@JoinColumn(name = "standort_fk", referencedColumnName = "autoin_fix"),
@JoinColumn(name = "servdat_fk", referencedColumnName = "servdat_fk")
})
public Location getLocation() {
return this.location;
}
// Setters omitted
}
Request实体引用了两个其他实体,它们都使用复合主键来标识自己。但是从业务逻辑的角度来看,这两个实体(文章和位置)的serverId必须始终相同,数据库中只有一列serverId:
TABLE leads
-------------
autoin_fix
artikel_fk
standort_fk
servdat_fk // This only exists once, but is part of the association to both Article and Location!
要使应用程序启动,我必须向Article关联添加insertable = false,updatable = false,这是不我想要的。如果我尝试持久化一个Request对象,则不会写入“artikel_fk”字段,在数据库中留下null,因为我告诉hibernate它是只读的。并且不允许在其中一个连接列上使用insertable = false,updatable = false。
// This is illegal and the application won't start
@JoinColumns({
@JoinColumn(name = "artikel_fk", referencedColumnName = "autoin_fix"),
@JoinColumn(name = "servdat_fk", referencedColumnName = "servdat_fk", insertable = false, updatable = false)
})
有谁知道这个问题的解决方案?或者使用Hibernate / JPA无法映射?
编辑:文章和位置的(简化)定义(真的不那么有趣,重要的是它们使用复合主键):
@Entity
@Table(name = "ARTIKEL")
public class Article {
private ID id;
private String headline;
private String description;
@EmbeddedId
public ID getId() {
return this.id;
}
@Column(name = "artbesch")
public String getDescription() {
return this.description;
}
@Column(name = "artueschr")
public String getHeadline() {
return this.headline;
}
// Setters omitted
}
@Entity
@Table(name = "STANDORT")
public class Location {
private ID id;
private GeoCoordinates geoCoordinates;
private Name name;
@EmbeddedId
public ID getId() {
return this.id;
}
@Embedded
public GeoCoordinates getGeoCoordinates() {
return this.geoCoordinates;
}
@Embedded
public Name getName() {
return this.name;
}
// Setters omitted
}
答案 0 :(得分:0)
我认为如果从属实体的派生标识符是嵌入式id类的形式,那么表示关系的该id类的每个属性应该由对应关系属性上的@MapsId注释引用。
例如:
@Entity
public class Request {
// ...
@Id
int id;
@MapsId
@ManyToOne
private Article article;
// ...
}
我希望这样有效,因为我现在无法尝试。