Community
Participate
Working Groups
Build Identifier: 2.0.0 In an entity called Entity1, I have following mapping : @ManyToMany @MapKeyJoinColumn(name="entity2_id") @JoinTable(joinColumns=@JoinColumn(name="entity1_id"), inverseJoinColumns=@JoinColumn(name="entity3_id")) private Map<Entity2, Entity3> entities; In database, a table entity1_entity_3 is generated with entity1_id integer NOT NULL, entity3_id integer NOT NULL, entity2_id integer, CONSTRAINT entity1_entity3_pkey PRIMARY KEY (entity1_id, entity3_id), ... I was expecting : entity1_id integer NOT NULL, entity3_id integer NOT NULL, entity2_id integer NOT NULL, CONSTRAINT entity1_entity2_entity3_pkey PRIMARY KEY (entity1_id, entity2_id, entity3_id) or eventually, CONSTRAINT entity1_entity2_pkey PRIMARY KEY (entity1_id, entity2_id) Because of the generated schema, we can't do this : Map<Entity2, Entity3> map = new HashMap<Entity2, Entity3>(); map.put(entity2A, entity3); map.put(entity2B, entity3); entity1.setEntities(map); entityManager.persist(entity1); It causes following error : ERROR: duplicate key value violates unique constraint "entity1_entity3_pkey" The current generated schema is not coherent with standard use of a java.util.Map Reproducible: Always
same generated schema with eclipse link 2.2.0.v20110202-r8913
The best workaround is to generate the schema using our sql-script type generation and change the generated schema manually and apply it to the database.
Setting target and priority. See the following page for the meanings of these fields: http://wiki.eclipse.org/EclipseLink/Development/Bugs/Guidelines Community: Please vote for this bug if it is important to you. Votes are one of the main criteria we use to determine which bugs to fix next.
Getting this same bug as of Eclipse 2.6.2, in both @OneToMany and @ManyToMany mapping. Further you can't fix it by messing around with the @JoinTable and @MapKeyClass annotations. I know a workaround is to use a manually generated schema, but that's pretty ugly.
I have this very same problem although changing the schemas won't fix the issue. This is what I implemented as a test case EntityManager em = EMF.get().createEntityManager(); // update schema first em.getTransaction().begin(); em.createNativeQuery("ALTER TABLE license_euladocument DROP CONSTRAINT license_euladocument_pkey;" + "ALTER TABLE license_euladocument ADD CONSTRAINT license_euladocument_pkey PRIMARY KEY (license_id, values_key);").executeUpdate(); em.getTransaction().commit(); { em.getTransaction().begin(); License license = new License(); license.setName("Test license"); HashMap<CaseValue, EULADocument> caseValues = new HashMap<CaseValue, EULADocument>(); CaseValue firstCaseValue = new CaseValue(); firstCaseValue.setValue("Case 1"); em.persist(firstCaseValue); CaseValue secondCaseValue = new CaseValue(); secondCaseValue.setValue("Case 2"); em.persist(secondCaseValue); CaseValue thirdCaseValue = new CaseValue(); thirdCaseValue.setValue("Case 3"); em.persist(thirdCaseValue); EULADocument firstEULADocument = new EULADocument(); firstEULADocument.setName("EULA document 1"); em.persist(firstEULADocument); EULADocument secondEULADocument = new EULADocument(); secondEULADocument.setName("EULA document 2"); em.persist(secondEULADocument); caseValues.put(firstCaseValue, firstEULADocument); caseValues.put(secondCaseValue, firstEULADocument); caseValues.put(thirdCaseValue, secondEULADocument); license.setValues(caseValues); em.persist(license); em.getTransaction().commit(); } em.getEntityManagerFactory().getCache().evictAll(); em.clear(); { TypedQuery<License> licenseTypedQuery = em.createQuery("select l from License l", License.class); List<License> licenses = licenseTypedQuery.getResultList(); assert licenses.size() == 1 && licenses.get(0).getValues().size() == 3; em.getTransaction().begin(); License license = licenses.get(0); Map<CaseValue, EULADocument> values = license.getValues(); // change map values set them all to the same document List<EULADocument> documents = new ArrayList<EULADocument>(values.values()); for (CaseValue caseValue : values.keySet()) { values.put(caseValue, documents.get(0)); } em.getTransaction().commit(); } I haven't added the code for the entities because they are very trivial. I can add them if required. This code FAILS. I don't have the primary key constraint error anymore but this is the new error [EL Fine]: sql: 2018-12-28 12:21:06.615--ClientSession(260580453)--Connection(1375503918)--DELETE FROM LICENSE_EULADOCUMENT WHERE ((values_ID = ?) AND (License_ID = ?)) bind => [5, 6] [EL Fine]: sql: 2018-12-28 12:21:06.615--ClientSession(260580453)--Connection(1375503918)--INSERT INTO LICENSE_EULADOCUMENT (values_ID, License_ID, values_KEY) VALUES (?, ?, ?) bind => [4, 6, 1] [EL Fine]: sql: 2018-12-28 12:21:06.63--ClientSession(260580453)--SELECT 1 [EL Warning]: 2018-12-28 12:21:06.63--ClientSession(260580453)--Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.7.3.v20180807-4be1041): org.eclipse.persistence.exceptions.DatabaseException Internal Exception: org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "license_euladocument_pkey" Detail: Key (license_id, values_key)=(6, 1) already exists. As you can see the issue is that the DELETE is made using the ((values_ID = ?) AND (License_ID = ?)) combination instead of the primary key I defined. Is there a way to fix this? I am really stuck looking for alternatives. Thanks!
The Eclipselink project has moved to Github: https://github.com/eclipse-ee4j/eclipselink