我遇到了一个问题,如何创建扩展多个基本抽象类的 JPA 实体(无需创建额外的表(。我知道有一个注释@MappedSuperclass
,但它提供了一旦我们使用extends
就只创建一个基类的能力,并且多重继承不是 Java 功能。
例如,我有两个基础:
@MappedSuperclass
public abstract class Authored {
@ManyToOne
private User user;
}
和
@MappedSuperclass
public abstract class Dated {
private String creationDate;
}
我希望我的一些模型只能扩展Authored
,有些 - 只有Dated
,有些 - 两者兼而有之。虽然只能写
@Entity
public class MyEntity extends Authored {
...
}
或
@Entity
public class MyEntity extends Dated {
...
}
一些讨论建议继承类(例如 Authored
和AuthoredAndDated
(但这似乎太脏了,从逻辑上讲,这些基础都不能扩展另一个。
加法
我必须指出,这种风格在 Django 等其他框架中受支持(由于 python 中的多重继承(,所以 JPA 不支持它很奇怪。
抱歉让您失望,但是除了按照您的建议创建AuthoredAndDated
之外,没有其他解决方案。
我们的实体也面临同样的问题,并采取了同样的程序。
我们有一个
@MappedSuperclass
public class TimestampedObject {
@CreationTimestamp
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "created_at")
private Date createdAt;
@UpdateTimestamp
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "updated_at")
private Date updatedAt;
}
和
@MappedSuperclass
public class IdObject {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
@Column(name = "id", updatable = false, columnDefinition = "serial")
private Long id;
}
因此,我们为此创建了一个TimestampedIdObject
。
编辑:
如果您找到另一个合适的解决方案,如果您可以在此处发布它,那就太好了,因为我们有同样的问题......
您应该使用 @Embeddable
/@Embedded
作为目标,将继承替换为组合。
首先,不要使用 @MappedSuperClass
,而是对要与之共享属性的类使用 @Embeddable
:
@Embeddable
public class Authored {...}
@Embeddable
public class Dated {...}
在下一步中,您的实体不应从Authored
或Dated
继承,而应获取引用它们的属性:
@Entity
public class MyEntity {
@Embedded
private Authored authored;
@Embedded
private Dated dated;
}
如果你想从中获取行为,你可以在没有这些新属性的情况下进行一般访问,你需要引入一个公开必要方法的接口。
如果MyEntity
应该能够提供有关上次更新和创建的详细信息,您将引入一个接口Authorable
,该接口定义了访问相关数据的方法。
public interface Authorable { /* necessary methods */ }
然后MyEntity
将实现此接口:
@Entity
public class MyEntity implements Authorable {
/* previous content plus implemented mehtods from interface */
}