We have a pojo that needs to have a list of integers. As an example, I created pojo Messageand would like to link the list groupIds(these identifiers should be requested and displayed in the user interface). Therefore, ideally, we would like to do something like this:
Message msg = em.find(Message.class, 101);
List<Integer> groupIds = msg.getGroupIds();
I got the impression that this would only require one pojo with JPA, but according to the discussion here I need to create a second pojo because JPA works in terms of objects instead of primitive types.
From this discussion, I tried the following code example, but getting an error openjpa-1.2.3-SNAPSHOT-r422266:907835 fatal user error: org.apache.openjpa.util.MetaDataException: The type of field "pojo.Group.messageId" isn't supported by declared persistence strategy "ManyToOne". Please choose a different strategy.
DDL:
CREATE TABLE "APP". "MESSAGE" (
"MESSAGE_ID" INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 1, INCREMENT BY 1),
"AUTHOR" CHAR (20) NOT NULL
);
ALTER TABLE "APP". "MESSAGE" ADD CONSTRAINT "MESSAGE_PK" PRIMARY KEY ("MESSAGE_ID");
CREATE TABLE "APP". "GROUP_ASSOC" (
"GROUP_ID" INTEGER NOT NULL,
"MESSAGE_ID" INTEGER NOT NULL
);
ALTER TABLE "APP". "GROUP_ASSOC" ADD CONSTRAINT "GROUP_ASSOC_PK" PRIMARY KEY ("MESSAGE_ID", "GROUP_ID");
ALTER TABLE "APP". "GROUP_ASSOC" ADD CONSTRAINT "GROUP_ASSOC_FK" FOREIGN KEY ("MESSAGE_ID")
REFERENCES "APP". "MESSAGE" ("MESSAGE_ID");POJO,
@Entity
@Table(name = "MESSAGE")
public class Message {
@Id
@Column(name = "MESSAGE_ID")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long messageId;
@OneToMany
private List<Group> groups = new ArrayList<Group>();
@Column(name = "AUTHOR")
private String author;
}
@Entity
@IdClass(pojo.Group.GroupKey.class)
@Table(name = "GROUP_ASSOC")
public class Group {
@Id
@Column(name = "GROUP_ID")
private Long groupId;
@Id
@Column(name = "MESSAGE_ID")
@ManyToOne
private Long messageId;
public static class GroupKey {
public Long groupId;
public Long messageId;
public boolean equals(Object obj) {
if(obj == this) return true;
if(!(obj instanceof Group)) return false;
Group g = (Group) obj;
return g.getGroupId() == groupId && g.getMessageId() == messageId;
}
public int hashCode() {
return ((groupId == null) ? 0 : groupId.hashCode())
^ ((messageId == null) ? 0 : messageId.hashCode());
}
}
}
Test code:
EntityManager em = Persistence.createEntityManagerFactory("JPATest").createEntityManager();
em.getTransaction().begin();
Message msg = new Message();
msg.setAuthor("Paul");
em.persist(msg);
List<Group> groups = new ArrayList<Group>();
Group g1 = new Group();
g1.setMessageId(msg.getMessageId());
Group g2 = new Group();
g2.setMessageId(msg.getMessageId());
msg.setGroups(groups);
em.getTransaction().commit();
It all seems ridiculous - 3 classes (if you include a GroupKey compound identity class) to model a list of integers - isn't there a more elegant solution?