使用接口覆盖@Embedded的@ManyToOne targetEntity

时间:2013-01-10 12:34:38

标签: hibernate jpa

我正在使用ORM的hibernate和注释。 我有所有bean的接口,我使用targetEntity来建立关系: hibernate无法派生类型,因为getter返回的是接口而不是bean。

我为嵌入式bean得到了MappingException(无法确定类型)。

@Entity(name="FieldBean")
public class FieldBean implements Field {
    ...
}

@Embeddable
public class FacetBean implements Facet {
    ...    

    @ManyToOne(targetEntity = FieldBean.class)
    @JoinColumn(name = "field_id")
    public Field getField() {
        return field;
    }

}

@Entity(name = "Chart")
public class ChartBean implements Chart {

    @Embedded
    @AssociationOverride(
        name = "field",
        joinColumns = @JoinColumn(name = "category_facet_field_id")
    )
    public Facet getCategoryFacet() {
        return categoryFacet;
    }

}

我得到MappingException:无法确定类型:Field,at table:chart,for columns:[org.hibernate.mapping.Column(field)]

使用bean而不是接口来获取属性和getter / setter声明解决了这个问题,但我想坚持使用接口。单独使用bean进行属性声明并不能解决问题。

有人能指出我正确的方向吗?

3 个答案:

答案 0 :(得分:2)

我现在已经使用了一个可行的解决方案,但它包含一个供应商锁定的小案例。我发现只有JPA注释才能做到这一点,但是有一个特定于Hibernate的注释@Target可以解决这个问题。我已经做了类似于你的事情,并取得了预期的成果。但是,我没有使用你的其他注释,所以我不能保证它会像你期望的那样工作。

Embeddable类没有什么奇怪的事情发生了:

public interface PointsInt extends Serializable {
    int offensivePoints();

    int defensivePoints();

}

@Embeddable
public class Points implements PointsInt {
    private int def;
    private int off;
    public int offensivePoints() { return off; }

    public int defensivePoints() { return def; }

}

但是在消费类中,我们使用Hibernate的@Target

import javax.persistence.*;
import org.hibernate.annotations.Target;

@Entity
public class Series extends LongIdEntity implements Serializable {

    @Embedded
    @Target(Points.class)
    private PointsInt points;
    // I prefer to declare my annotations on fields rather than methods
}

结果:

mysql> describe series;
+-----------------+-------------+------+-----+---------+----------------+
| Field           | Type        | Null | Key | Default | Extra          |
+-----------------+-------------+------+-----+---------+----------------+
| id              | bigint(20)  | NO   | PRI | NULL    | auto_increment |
| def             | int(11)     | YES  |     | NULL    |                |
| off             | int(11)     | YES  |     | NULL    |                |
+-----------------+-------------+------+-----+---------+----------------+
3 rows in set (0.12 sec)

答案 1 :(得分:0)

我过去使用jpa告诉我不要使用继承。没有映射的超类,没有接口等......只是具有成员的实体。我使用hibernate和eclipselink,两者都有真正的继承问题。使用支持多个提供程序的jpa编写持久层非常困难,因为所有这些提供程序都存在很多错误。保持尽可能简单。不要使用任何“特殊”功能。我保证,在尝试更改提供程序或只是在jboss(hibernate)或glassfish / weblogic(eclipse / top link)等不同的应用程序服务器上运行软件时,你可以很高兴拥有一个使用尽可能少的最简单的持久层功能尽可能。我不知道这是不是一个错误,但我认为它是。

答案 2 :(得分:0)

除了讨论是否过度使用接口之外,问题的根源是您使用的接口应该是类。具体来说,您将在返回非JPA对象的方法上放置JPA批注。

解决方案非常简单:将注释放在字段上,而不是方法上。

puls <- read.table ("https://edbook.hi.is/gogn/pulsAll.csv", header=TRUE, sep=";")
ggplot(puls, aes(x = "", y = reykir, fill = reykir)) +
  geom_bar(stat = "identity") +
  coord_polar(theta = "y", start = 0, direction = 1)

唯一的缺点是,如果您坚持使用带有@Embeddable public class FacetBean implements Facet { @ManyToOne(targetEntity = FieldBean.class) @JoinColumn(name = "field_id") private FieldBean field; public Field getField() { return field; } } 参数的设置方法,那么任何设置方法都会出现问题。但是,如果您希望能够分配任何Field实例,即使它不是JPA托管的bean,也仍然会遇到此类问题。