我的项目要求我的所有方法都应该是抽象的或最终的(请不要争论这个要求 - 我知道它是愚蠢的,只是假设它在那里)。
这是Hibernate映射实体的问题,因为Hibernate需要在运行时创建代理,以便能够在延迟加载时初始化关系。无法覆盖setter方法导致那些根本没有加载(查询确实已执行,但从不填充对象)。
如Hibernate's documentation中所述:
如果最终类确实实现了正确的接口,您可以在生成代理时告诉Hibernate使用该接口。请参见例4.4“在hbm.xml中代理接口”和例4.5“在注释中代理接口”。
示例:
@Entity @Proxy(proxyClass=ICat.class) public class Cat implements ICat { ... }
所以理论上可以告诉hibernate实现一个接口而不是扩展原始类。
我尝试过这个解决方案,但我的问题来自关系本身。这是一个过于简化的例子:
@Entity
@Proxy(proxyClass = ICat.class)
@Table(name = "cat")
public class Cat implements ICat {
@Id
private Long catId;
@OneToMany(mappedBy = "cat", fetch = FetchType.LAZY)
private List<Kitten> kittens;
...
}
@Entity
@Proxy(proxyClass = IKitten.class)
@Table(name="kitten")
public class Cat implements IKitten {
@Id
private Long kittenId;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name="catId")
private Cat cat;
...
}
现在,如果我尝试获取Cat
个对象,我会收到ClassCastException
因为它正在尝试将IKitten
集合转换为Kitten
集合。这让我认为我应该使用接口而不是实现声明关系 - 这也会产生编译时错误,因为我的接口永远不会被声明为实体,但是实现是(在文档的示例中明确说明)。
我该如何解决这个问题?
答案 0 :(得分:2)
您可以在one-to-many
和many-to-one
关联中使用该界面,但您需要在targetEntity
属性中提供实际的类。关系应该是这样的:
@Entity
@Proxy(proxyClass = ICat.class)
@Table(name = "cat")
public class Cat implements ICat {
@Id
private Long catId;
@OneToMany(mappedBy = "cat", fetch = FetchType.LAZY, targetEntity=Cat.class)
private List<IKitten> kittens;
...
}
@Entity
@Proxy(proxyClass = IKitten.class)
@Table(name="kitten")
public class Cat implements IKitten {
@Id
private Long kittenId;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name="catId", targetEntity=Cat.class)
private ICat cat;
...
}
答案 1 :(得分:0)
之前我有相同的要求,并通过宣布最后的所有课程来绕过它。我的hibernate结构没有代理,因此我不知道这是否能解决问题,而是需求。如果你使用mockito会有一个副作用。考虑到这一点。
顺便说一下,你的代码中显示的第二类中有一个拼写错误,它应该被命名为Kitten