I have three tables; Account
, Event
and AccountEventRelation
.
The last one acts as a normal Many-to-Many relation between user and events, with the small but important exception that it allows one to have properties on the relation.
(Imagine an event with many users, but some users can also be an moderator of an event. The boolean property on account-event relation indicates that.)
I can make this work perfectly if I write my own DAO or use plain JDBC and SQL, but with Spring Data it fails terribly. Adding to that, the error message is confusing;
Caused by: java.lang.IllegalArgumentException: Expected id attribute type [class lan.localhost.entity.EventAccountRelationPk] on the existing id attribute [SingularAttributeImpl[EntityTypeImpl@1443927423:Account [ javaType: class lan.localhost.entity.Account descriptor: RelationalDescriptor(lan.localhost.entity.Account --> [DatabaseTable(user_account)]), mappings: 4],org.eclipse.persistence.mappings.ManyToOneMapping[account]]] on the identifiable type [EntityTypeImpl@1204999057:EventAccountRelation [ javaType: class lan.localhost.entity.EventAccountRelation descriptor: RelationalDescriptor(lan.localhost.entity.EventAccountRelation --> [DatabaseTable(event_account_rel)]), mappings: 4]] but found attribute type [class lan.localhost.entity.Account].
at org.eclipse.persistence.internal.jpa.metamodel.IdentifiableTypeImpl.getId(IdentifiableTypeImpl.java:200)
at org.springframework.data.jpa.repository.support.JpaMetamodelEntityInformation$IdMetadata.<init>(JpaMetamodelEntityInformation.java:212)
...
And the error message only appears when I have an interface extending JpaRepository
which is autowired.
What do I do wrong?
Have I misunderstood the JPA technology or am I just using Spring Data incorrectly?
Note: I have a repository on GitHub with the a test case as a Maven project, but here are snippets from my classes;
@Entity
@Table(name = "user_account")
public class Account {
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
...
@OneToMany(mappedBy = "account")
private List<EventAccountRelation> events;
...
}
The Event class;
@Entity
@Table(name = "meeting")
public class Event {
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
...
@OneToMany(mappedBy = "event")
private List<EventAccountRelation> accounts;
...
}
The join table;
@Entity
@Table(name = "event_account_rel")
public class EventAccountRelation {
@EmbeddedId
private EventAccountRelationPk primaryKey;
@MapsId("eventId")
@ManyToOne(optional = false)
@JoinColumn(name = "event_id", nullable = false, updatable = false)
private Event event;
@MapsId("accountId")
@ManyToOne(optional = false)
@JoinColumn(name = "account_id", nullable = false, updatable = false)
private Account account;
@Column(name = "moderator", nullable = false)
private Boolean moderator = Boolean.FALSE;
...
}
And finally the composite key;
@Embeddable
public class EventAccountRelationPk {
private Long eventId;
private Long accountId;
...
}
I use Spring 3.1.4, Spring Data 1.4.5 and EclipseLink 2.5.1 on a Java 1.6.
Of course I could try a later version, but unfortunately I am restricted to this environment. :/