7

We have a set of interfaces, used as an API, and referenced from other modules. A set of concrete implementations of those interfaces, private to the "main" app module. These classes carry a number of annotations (JPA as well as XStream for XML serialization).

I've run into a problem. We have a user class which had a number of fields within it related to location. We'd like to roll those up into an Address class. We want the data (for now) to remain in the same table. The approach is an embedded class.

The problem is that the type signatures must only refer to other interfaces to satisfy the interfaces they implement.

When I try to persist a UserImpl, I get the exception:

org.hibernate.MappingException: Could not determine type for: com.example.Address, at table: User, for columns: [org.hibernate.mapping.Column(address)]

Example code:

interface User {
    int getId();
    String getName();
    Address getAddress();
}

@Entity
class UserImpl implements User {
    int id;
    String name;
    Address address;

    int getId() {
        return id;
    }

    void setId(int id) {
        this.id = id;
    }

    String getName() {
        return name;
    }

    String setName(String name) {
        this.name = name;
    }

    @Embedded
    Address getAddress() {
        return address;
    }

    void setAddress(Address address) {
        this.address = address;
    }
}


interface Address {
    String getStreet();
    String getCity();
    String getState();
    String getZip();
    String getCountry();
}

@Embeddable
class AddressImpl implements Address {
    String street;
    String city;
    String state;
    String zip;
    String country;

    public String getStreet() {
        return street;
    }

    public String getCity() {
        return city;
    }

    public String getState() {
        return state;
    }

    //... etc
}
Mark Renouf
  • 30,697
  • 19
  • 94
  • 123
  • Entity interfaces are usually not a good idea and YAGNI (_almost_, but not completely the same thing). This case is a good example for that. – Kalle Richter Apr 25 '18 at 14:04

1 Answers1

13

You can use the @Target Hibernate Annotation (which is a Hibernate-specific extension to the JPA annotations)

@Embedded
@Target(AddressImpl.class)
Address getAddress() {
    return address;
}
mtpettyp
  • 5,533
  • 1
  • 33
  • 33
  • Thanks, that is indeed a solution though I was hoping this could be done by using only JPA. Might help to know if this is possible with other JPA implementations. – Mark Renouf Jul 02 '09 at 13:05
  • Based on the exception you mentioned I assumed you were using Hibernate. Chances are if it's part of Hibernate Annotations it hasn't been added to the JPA spec yet. – mtpettyp Jul 02 '09 at 13:36
  • 1
    We are, but it would be nice to be vendor neutral where possible. – Mark Renouf Jul 02 '09 at 16:52
  • What happens if interface is implemented by a enum class ? – Njax3SmmM2x2a0Zf7Hpd Jun 09 '14 at 15:06
  • There's a good reason why `@Target` is not a part of JPA: it just serves to cover up entity interface which are a bad idea and YAGNI. The only reason to have an entity class implement an interface is that it's doing more than setting and getting, then your entity design is bad. – Kalle Richter Apr 25 '18 at 14:05