I am trying to adapt my data model to use a BaseEntity base-class. The following code represents the general idea:
@MappedSuperclass
public abstract class BaseEntity implements HasAuditInfo {
@Id
@GeneratedValue
private Long id;
@Column(unique = true, nullable = false)
private String uuid;
private Long createdById;
@Temporal(value = TemporalType.TIMESTAMP)
@Column(nullable = false)
private Date createdOn;
private Long changedById;
@Temporal(value = TemporalType.TIMESTAMP)
@Column(nullable = false)
private Date changedOn;
@Column(nullable = false)
private Long changedOnValue;
private Boolean active;
private Long deactivatedById;
@Temporal(value = TemporalType.TIMESTAMP)
private Date deactivatedOn;
@NotNull
@DecimalMin("0")
private Integer version = 0;
private Long domainId;
[... Getters/Setters etc ...]
}
The following is an example of a derived entity:
@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class Address extends BaseEntity implements Serializable, Comparable<Address> {
private static final long serialVersionUID = 6301090657382674578L;
// Address Fields
@NotBlank(message = "Address Line 1 is a mandatory field.")
private String addressLine1;
private String addressLine2;
private String country;
@NotBlank(message = "Region is a mandatory field.")
private String region;
@NotBlank(message = "City is a mandatory field.")
private String city;
@NotBlank(message = "Zipcode is a mandatory field.")
private String zipcode;
[... Getters/Setters etc ...]
}
If I'm understanding the JPA documentation correctly, this should be perfectly valid, yet I get the following error from EclipseLink when deploying my code:
Entity class [class com.x.y.z.Address] has no primary key specified. It should define either an @Id, @EmbeddedId or an @IdClass. If you have defined PK using any of these annotations then make sure that you do not have mixed access-type (both fields and properties annotated) in your entity class hierarchy.
I've tried a few things to work around this:
- Upgrading to EclipseLink 2.3 (I'm currently using 2.2)
- Making BaseEntity non-abstract
- Moving the @Id annotation and field directly into Address
- Annotating the getId() method instead of field both in BaseEntit开发者_JAVA技巧y and in Address.
None of these approaches have had any effect, short of migrating my code to Hibernate (or some other, better, JPA implementation), is there anything I can do?
The solution is to explicitly name each column in BaseEntity, as follows:
@MappedSuperclass
public abstract class BaseEntity {
@Id
@GeneratedValue
@Column(name = "id")
@SearchableId
protected Long id;
@Column(name = "uuid", unique = true, nullable = false)
protected String uuid;
@Column(name = "createdById")
protected Long createdById;
@Temporal(value = TemporalType.TIMESTAMP)
@Column(name = "createdOn", nullable = false)
protected Date createdOn;
@Column(name = "changedById")
protected Long changedById;
@Temporal(value = TemporalType.TIMESTAMP)
@Column(name = "changedOn", nullable = false)
protected Date changedOn;
@Column(name = "changedOnValue", nullable = false)
protected Long changedOnValue;
@Column(name = "active")
protected Boolean active;
@Column(name = "deactivatedById")
protected Long deactivatedById;
@Temporal(value = TemporalType.TIMESTAMP)
@Column(name = "deactivatedOn")
protected Date deactivatedOn;
@Version
@Column(name = "version")
protected Integer version = 0;
@Column(name = "domainId")
protected Long domainId;
You should not get this error. And definitely not if you move the @Id into the Address.
Are you sure you recompiled/deployed your code after making the changes?
If you remove the TABLE_PER_CLASS inheritance does it work? (does Address have subclasses?)
精彩评论