通过接口的懒惰代理(具有最终方法的实体)

时间:2015-02-13 08:47:14

标签: java hibernate jpa proxy hibernate-mapping

我的项目要求我的所有方法都应该是抽象的或最终的(请不要争论这个要求 - 我知道它是愚蠢的,只是假设它在那里)。

这是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集合。这让我认为我应该使用接口而不是实现声明关系 - 这也会产生编译时错误,因为我的接口永远不会被声明为实体,但是实现是(在文档的示例中明确说明)。

我该如何解决这个问题?

2 个答案:

答案 0 :(得分:2)

您可以在one-to-manymany-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