Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Override @ManyToOne targetEntity for @Embedded with interfaces

Tags:

hibernate

jpa

I am using hibernate and annotations for ORM. I have interfaces for all beans and I am using targetEntity for relationships: hibernate cannot derive the type because the getter returns an interface rather than a bean.

I get a MappingException (could not determine type) for embedded beans.

@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;
    }

}

I get the MappingException: Could not determine type for: Field, at table: chart, for columns: [org.hibernate.mapping.Column(field)]

Using beans instead of interfaces for property and getter/setter declarations solves the problem, but I would like to stick to using interfaces. Using beans for property declarations alone does not solve the problem.

Could anyone point me in the right direction ?

like image 222
user1966634 Avatar asked Jan 10 '13 12:01

user1966634


2 Answers

I have used a workable solution to this for a while now, but it includes a minor case of vendor lock-in. I have found no way of doing this with JPA annotations only, but there is a Hibernate-specific annotation @Target that does the trick. I have done something like you have, with the expected results. However, I didn't use your other annotations so I can't guarantee it will turn out to work as you expect.

Nothing strange going on in the Embeddable classes:

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; }

}

But in the consuming class, we use Hibernate's @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
}

Result:

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)
like image 175
blagae Avatar answered Oct 22 '22 10:10

blagae


My past using jpa told me not to use inheritance. No mapped superclasses, no interfaces, etc ... simply entities with members. i worked with hibernate as well as eclipselink and both have really, really problems with inheritance. It is relly difficulty to write a persistence layer with jpa that supports more than one provider, as there are so many bugs all these providers. keep it as simple as possible. don't use any "special" features. i assure you, when trying to change the provider or simply running a software on different applications servers like jboss (hibernate) or glassfish/weblogic (eclipse/top link), you can be glad when having a most simply persistence layer that uses as little features as possible. i don't know if this is a bug, but i'd assume it is.

like image 27
Robert Franz Avatar answered Oct 22 '22 12:10

Robert Franz