Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import org.eclipse.persistence.exceptions.DescriptorException;
import org.eclipse.persistence.exceptions.ValidationException;
import org.eclipse.persistence.internal.descriptors.ObjectBuilder;
import org.eclipse.persistence.internal.descriptors.RecordInstantiationPolicy;
import org.eclipse.persistence.internal.helper.DatabaseField;
import org.eclipse.persistence.internal.identitymaps.CacheId;
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
Expand All @@ -38,6 +39,7 @@
import org.eclipse.persistence.queries.UpdateObjectQuery;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
Expand Down Expand Up @@ -462,7 +464,10 @@ public Object createPrimaryKeyInstance(Object object, AbstractSession session) {
return fieldValue;
}

Object keyInstance = getPKClassInstance();
Class<?> pkClass = getPKClass();
boolean isRecord = pkClass != null && pkClass.isRecord();
Object keyInstance = isRecord ? null : getPKClassInstance();
List<Object> recordValues = isRecord ? new ArrayList<>(pkElementArray.length) : null;
Set<ObjectReferenceMapping> usedObjectReferenceMappings = new HashSet<>();
for (int index = 0; index < pkElementArray.length; index++) {
Object keyObj = object;
Expand Down Expand Up @@ -492,11 +497,27 @@ public Object createPrimaryKeyInstance(Object object, AbstractSession session) {
fieldValue = mapping.getReferenceDescriptor().getCMPPolicy().createPrimaryKeyInstance(fieldValue, session);
usedObjectReferenceMappings.add((ObjectReferenceMapping)mapping);
}
accessor.setValue(nestedKeyInstance, fieldValue);
if (isRecord) {
recordValues.add(fieldValue);
} else {
accessor.setValue(nestedKeyInstance, fieldValue);
}
}
}

return keyInstance;
return isRecord ? createRecordInstance(pkClass, recordValues) : keyInstance;
}

/**
* Build a record primary key class instance from its component values using
* its canonical constructor. Records are immutable, so the default
* no-arg-constructor + field-reflection approach used for bean id classes
* cannot be applied.
*/
private Object createRecordInstance(Class<?> recordClass, List<?> values) {
RecordInstantiationPolicy policy = new RecordInstantiationPolicy(recordClass);
policy.setValues(values);
return policy.buildNewInstance();
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
* Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0,
* or the Eclipse Distribution License v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/

package org.eclipse.persistence.jpa.test.record;

import jakarta.persistence.EntityManager;
import jakarta.persistence.EntityManagerFactory;

import org.eclipse.persistence.jpa.test.framework.DDLGen;
import org.eclipse.persistence.jpa.test.framework.Emf;
import org.eclipse.persistence.jpa.test.framework.EmfRunner;
import org.eclipse.persistence.jpa.test.record.model.RecordIdClass;
import org.eclipse.persistence.jpa.test.record.model.RecordIdClassEntity;
import org.junit.Test;
import org.junit.runner.RunWith;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

/**
* Tests for a {@code java.lang.Record} used as a JPA {@code @IdClass}.
*/
@RunWith(EmfRunner.class)
public class TestRecordIdClass {

@Emf(createTables = DDLGen.DROP_CREATE, classes = { RecordIdClassEntity.class })
private EntityManagerFactory emf;

@Test
public void testPersistAndFind() {
EntityManager em = emf.createEntityManager();
try {
em.getTransaction().begin();
RecordIdClassEntity entity = new RecordIdClassEntity("code-1", "description-1");
em.persist(entity);
em.getTransaction().commit();
em.clear();

RecordIdClass idClass = new RecordIdClass(entity.getId(), entity.getCode());
RecordIdClassEntity found = em.find(RecordIdClassEntity.class, idClass);
assertNotNull("Entity should be found after persist", found);
assertEquals("description-1", found.getDescription());
} finally {
if (em.getTransaction().isActive()) {
em.getTransaction().rollback();
}
em.close();
}
}

@Test
public void testGetIdentifier() {
RecordIdClassEntity entity = new RecordIdClassEntity("code-1", "description-1");

Object identifier = emf.getPersistenceUnitUtil().getIdentifier(entity);

assertNotNull("Identifier should not be null", identifier);
assertTrue("Identifier should be a RecordIdClass", identifier instanceof RecordIdClass);
RecordIdClass idClass = (RecordIdClass) identifier;
assertEquals(entity.getId(), idClass.id());
assertEquals("code-1", idClass.code());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0,
* or the Eclipse Distribution License v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/

package org.eclipse.persistence.jpa.test.record.model;

import java.util.Objects;
import java.util.UUID;

/**
* A two-component record used as a JPA {@code @IdClass}.
*/
public record RecordIdClass(UUID id, String code) {

public RecordIdClass {
Objects.requireNonNull(id, "id must not be null");
Objects.requireNonNull(code, "code must not be null");
}

public RecordIdClass(String code) {
this(UUID.randomUUID(), code);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0,
* or the Eclipse Distribution License v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/

package org.eclipse.persistence.jpa.test.record.model;

import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.IdClass;

import java.util.UUID;

@Entity
@IdClass(RecordIdClass.class)
public class RecordIdClassEntity {

@Id
private UUID id;

@Id
private String code;

private String description;

protected RecordIdClassEntity() {
}

public RecordIdClassEntity(String code, String description) {
this.id = UUID.randomUUID();
this.code = code;
this.description = description;
}

public UUID getId() {
return id;
}

public String getCode() {
return code;
}

public String getDescription() {
return description;
}
}
Loading