9

我正在为 ORM 使用休眠和注释。我有所有 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:无法确定类型:字段,表:图表,列:[org.hibernate.mapping.Column(field)]

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

谁能指出我正确的方向?

4

3 回答 3

5

我已经使用了一段时间的可行解决方案,但它包括供应商锁定的小案例。我发现仅使用 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)
于 2015-01-03T10:36:24.207 回答
1

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

于 2013-01-11T17:39:36.727 回答
0

除了讨论接口是否被过度使用之外,问题的根源在于您正在使用接口,而这些接口是需要类的。具体来说,您将 JPA 注释放在返回非 JPA 对象的方法上。

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

@Embeddable
public class FacetBean implements Facet {

    @ManyToOne(targetEntity = FieldBean.class)
    @JoinColumn(name = "field_id")
    private FieldBean field;

    public Field getField() {
        return field;
    }
}

唯一的缺点是,如果您坚持使用带有Field参数的方法,那么您将遇到任何 setter 方法的问题。但是无论如何,如果您希望能够分配任何Field实例,即使它不是 JPA 管理的 bean,您也会遇到这样的问题。

于 2019-11-27T11:54:27.980 回答