>, Serializable {
private static final long serialVersionUID = 1L;
@@ -119,7 +118,6 @@ protected BaseEntity() {
*
* @return The ID, or null if not set yet, e.g. when the entity has a generated ID and is not persisted yet.
*/
- @Override
@Nullable
public abstract I getId();
@@ -128,7 +126,6 @@ protected BaseEntity() {
*
* @param id The ID, may be null.
*/
- @Override
public abstract void setId(@Nullable I id);
/**
diff --git a/src/main/java/org/omnifaces/persistence/model/Identifiable.java b/src/main/java/org/omnifaces/persistence/model/Identifiable.java
deleted file mode 100644
index d2e0e1a..0000000
--- a/src/main/java/org/omnifaces/persistence/model/Identifiable.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright OmniFaces
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
- * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations under the License.
- */
-package org.omnifaces.persistence.model;
-
-import java.io.Serializable;
-
-import jakarta.annotation.Nullable;
-
-import org.omnifaces.persistence.model.dto.Page;
-import org.omnifaces.persistence.service.BaseEntityService;
-import org.omnifaces.persistence.service.EntityRepository;
-
-/**
- *
- * Base interface for something identifiable.
- *
- * Usage example:
- *
- *
- * @Entity
- * public class YourEntity extends BaseEntity<Long> {
- *
- * @Id
- * private Long id;
- *
- * @Override
- * public Long getId() {
- * return id;
- * }
- *
- * @Override
- * public void setId(Long id) {
- * this.id = id;
- * }
- *
- * }
- *
- *
- * @param The generic ID type, usually {@link Long}.
- * @author Bauke Scholtz
- * @since 1.0
- * @see BaseEntity
- * @see BaseEntityService
- * @deprecated Entities need not implement this. Extend {@link BaseEntity} for an entity whose identity is based on its ID, and use
- * {@link EntityRepository#getId(Object)} to get the ID of any entity.
- */
-@Deprecated(since = "1.3", forRemoval = true)
-public interface Identifiable & Serializable> {
-
- /**
- * The string representing the field name "id".
- *
- * @deprecated Use {@link Page#ID} instead.
- */
- @Deprecated(since = "1.3", forRemoval = true)
- String ID = Page.ID;
-
- /**
- * Returns the ID.
- *
- * @return The ID, or null if not set yet, e.g. when the entity has a generated ID and is not persisted yet.
- */
- @Nullable
- I getId();
-
- /**
- * Sets the ID.
- *
- * @param id The ID, may be null.
- */
- void setId(@Nullable I id);
-
-}
diff --git a/src/main/java/org/omnifaces/persistence/model/dto/Page.java b/src/main/java/org/omnifaces/persistence/model/dto/Page.java
index 2af3bae..a08ed39 100644
--- a/src/main/java/org/omnifaces/persistence/model/dto/Page.java
+++ b/src/main/java/org/omnifaces/persistence/model/dto/Page.java
@@ -123,7 +123,7 @@ public final class Page implements Serializable { // This class MAY NOT be mutab
* attribute is named code by its code. The actual name of the ID attribute works as well. A page without ordering is ordered by the ID
* descending.
*
- * @since 1.3
+ * @since 2.0
*/
public static final String ID = "id";
@@ -253,7 +253,7 @@ public Map getLastOrderingValues() {
* applicable.
*
* @return The amount of records to skip after the record represented by the last ordering values.
- * @since 1.3
+ * @since 2.0
*/
public int getResidualOffset() {
return residualOffset;
@@ -484,7 +484,7 @@ public Builder range(int offset, int limit, Map lastOrderingValu
* @return This builder.
* @see Page#getLastOrderingValues()
* @see Page#getResidualOffset()
- * @since 1.3
+ * @since 2.0
*/
public Builder range(int offset, int limit, Map lastOrderingValues, int residualOffset, boolean reversed) {
checkRangeNotSet();
diff --git a/src/main/java/org/omnifaces/persistence/service/BaseEntityService.java b/src/main/java/org/omnifaces/persistence/service/BaseEntityService.java
index dd53a09..ff427ec 100644
--- a/src/main/java/org/omnifaces/persistence/service/BaseEntityService.java
+++ b/src/main/java/org/omnifaces/persistence/service/BaseEntityService.java
@@ -426,7 +426,7 @@ protected EntityType getMetamodel() {
* Returns the entity name of current entity, to be used in JPQL. This is the name of {@link Entity}, or else the simple name of the entity class.
*
* @return The entity name of current entity.
- * @since 1.3
+ * @since 2.0
*/
protected String getEntityName() {
return getMetamodel().getName();
diff --git a/src/main/java/org/omnifaces/persistence/service/EntityMetadata.java b/src/main/java/org/omnifaces/persistence/service/EntityMetadata.java
index c847709..ace0dc7 100644
--- a/src/main/java/org/omnifaces/persistence/service/EntityMetadata.java
+++ b/src/main/java/org/omnifaces/persistence/service/EntityMetadata.java
@@ -31,6 +31,7 @@
import jakarta.persistence.EntityManagerFactory;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
+import jakarta.persistence.PersistenceUnitUtil;
import jakarta.persistence.metamodel.Attribute;
import jakarta.persistence.metamodel.EntityType;
import jakarta.persistence.metamodel.Metamodel;
@@ -115,7 +116,7 @@ Mappings getMappings(EntityManagerFactory entityManagerFactory, Provider provide
var metamodel = entityManagerFactory.getMetamodel();
return new Mappings(
mappingsPerFactory.computeIfAbsent(entityManagerFactory, k -> new FactoryMappings()),
- UNIT_MAPPINGS.computeIfAbsent(entityManagerFactory, k -> new UnitMappings(metamodel)), metamodel, provider
+ UNIT_MAPPINGS.computeIfAbsent(entityManagerFactory, k -> new UnitMappings(metamodel)), entityManagerFactory, metamodel, provider
);
}
@@ -127,12 +128,17 @@ final class Mappings {
private final FactoryMappings factoryMappings;
private final UnitMappings unitMappings;
+ private final EntityManagerFactory entityManagerFactory;
private final Metamodel metamodel;
private final Provider provider;
- private Mappings(FactoryMappings factoryMappings, UnitMappings unitMappings, Metamodel metamodel, Provider provider) {
+ private Mappings(
+ FactoryMappings factoryMappings, UnitMappings unitMappings, EntityManagerFactory entityManagerFactory, Metamodel metamodel, Provider provider
+ )
+ {
this.factoryMappings = factoryMappings;
this.unitMappings = unitMappings;
+ this.entityManagerFactory = entityManagerFactory;
this.metamodel = metamodel;
this.provider = provider;
}
@@ -159,8 +165,8 @@ IdAttribute getIdAttribute(Class> type) {
}
/**
- * Returns the ID of the given entity of this persistence unit: via the provider when it is a proxy, else via {@link BaseEntity#getId()} when it extends
- * it, else via its ID attribute.
+ * Returns the ID of the given entity of this persistence unit: via {@link PersistenceUnitUtil#getIdentifier(Object)} when it is a proxy, which does not
+ * initialize the proxy, else via {@link BaseEntity#getId()} when it extends it, else via its ID attribute.
*
* @param The generic ID type.
* @param entity The entity, may be a proxy.
@@ -170,7 +176,7 @@ IdAttribute getIdAttribute(Class> type) {
@SuppressWarnings("unchecked")
I getId(Object entity) {
if (provider.isProxy(entity)) {
- return provider.getIdentifier(entity);
+ return (I) entityManagerFactory.getPersistenceUnitUtil().getIdentifier(entity);
}
return entity instanceof BaseEntity> baseEntity ? (I) baseEntity.getId() : getIdAttribute(provider.getEntityType(entity)).get(entity);
diff --git a/src/main/java/org/omnifaces/persistence/service/EntityRepository.java b/src/main/java/org/omnifaces/persistence/service/EntityRepository.java
index 020b2a7..432f6a1 100644
--- a/src/main/java/org/omnifaces/persistence/service/EntityRepository.java
+++ b/src/main/java/org/omnifaces/persistence/service/EntityRepository.java
@@ -69,7 +69,7 @@
* @param The generic ID type.
* @param The generic entity type.
* @see BaseEntityService
- * @since 1.3
+ * @since 2.0
*/
public final class EntityRepository & Serializable, E> implements Serializable {
diff --git a/src/main/java/org/omnifaces/persistence/service/EntityRepositoryExtension.java b/src/main/java/org/omnifaces/persistence/service/EntityRepositoryExtension.java
index dff8051..dc7a82a 100644
--- a/src/main/java/org/omnifaces/persistence/service/EntityRepositoryExtension.java
+++ b/src/main/java/org/omnifaces/persistence/service/EntityRepositoryExtension.java
@@ -40,7 +40,7 @@
* does nothing.
*
* @author Bauke Scholtz
- * @since 1.3
+ * @since 2.0
*/
public final class EntityRepositoryExtension implements Extension {
diff --git a/src/main/java/org/omnifaces/persistence/service/SingularFetch.java b/src/main/java/org/omnifaces/persistence/service/SingularFetch.java
index fc42024..34d5f0a 100644
--- a/src/main/java/org/omnifaces/persistence/service/SingularFetch.java
+++ b/src/main/java/org/omnifaces/persistence/service/SingularFetch.java
@@ -28,7 +28,7 @@
* join.
*
* @author Bauke Scholtz
- * @since 1.3
+ * @since 2.0
* @see PostponedFetchRoot
*/
class SingularFetch extends FetchWrapper {
diff --git a/src/test/java/org/omnifaces/persistence/ProviderEntityTest.java b/src/test/java/org/omnifaces/persistence/ProviderEntityTest.java
index 92090d7..660ec72 100644
--- a/src/test/java/org/omnifaces/persistence/ProviderEntityTest.java
+++ b/src/test/java/org/omnifaces/persistence/ProviderEntityTest.java
@@ -13,37 +13,20 @@
package org.omnifaces.persistence;
import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertNull;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-import static org.omnifaces.persistence.Provider.ECLIPSELINK;
import static org.omnifaces.persistence.Provider.HIBERNATE;
-import static org.omnifaces.persistence.Provider.OPENJPA;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import org.junit.jupiter.api.Test;
-import org.omnifaces.persistence.model.Identifiable;
+import org.omnifaces.persistence.model.BaseEntity;
/**
- * Unit tests for the entity methods of {@link Provider} on entities which do not implement {@link Identifiable}. This class lives outside the integration test
+ * Unit tests for the entity methods of {@link Provider} on entities which do not extend {@link BaseEntity}. This class lives outside the integration test
* package so that its stub entity does not end up in the persistence unit of the integration tests.
*/
class ProviderEntityTest {
- @Test
- void identifierOfNullIsNull() {
- assertNull(HIBERNATE.getIdentifier(null));
- }
-
- @Test
- void identifierOfNonProxyEntityNotImplementingIdentifiableIsRejected() {
- var entity = new PlainEntity();
- assertThrows(IllegalArgumentException.class, () -> HIBERNATE.getIdentifier(entity));
- assertThrows(IllegalArgumentException.class, () -> ECLIPSELINK.getIdentifier(entity));
- assertThrows(IllegalArgumentException.class, () -> OPENJPA.getIdentifier(entity));
- }
-
@Test
void entityTypeOfSubclassIsEntityAnnotatedSuperclass() {
assertEquals(PlainEntity.class, HIBERNATE.getEntityType(new PlainEntitySubclass()));
diff --git a/src/test/java/org/omnifaces/persistence/service/EntityMetadataIdTest.java b/src/test/java/org/omnifaces/persistence/service/EntityMetadataIdTest.java
index 00c2898..93f3864 100644
--- a/src/test/java/org/omnifaces/persistence/service/EntityMetadataIdTest.java
+++ b/src/test/java/org/omnifaces/persistence/service/EntityMetadataIdTest.java
@@ -29,7 +29,6 @@
import org.junit.jupiter.api.Test;
import org.omnifaces.persistence.model.GeneratedIdEntity;
-import org.omnifaces.persistence.model.Identifiable;
import org.omnifaces.persistence.service.EntityMetadata.Mappings;
/**
@@ -54,21 +53,6 @@ void idOfBaseEntityIsReadViaGetId() throws ReflectiveOperationException {
assertEquals(ID, mappings(BaseEntitySubclass.class, BaseEntitySubclass.class.getDeclaredField("unrelated")).getId(entity));
}
- @Test
- void idOfIdentifiableEntityNotExtendingBaseEntityIsReadViaIdAttribute() throws ReflectiveOperationException {
- var entity = new IdentifiableEntity();
- entity.code = ID;
- assertEquals(ID, mappings(IdentifiableEntity.class, IdentifiableEntity.class.getDeclaredField("code")).getId(entity));
- }
-
- @Test
- void idOfIdentifiableEntityNotExtendingBaseEntityIsUnsetViaIdAttribute() throws ReflectiveOperationException {
- var entity = new IdentifiableEntity();
- entity.code = ID;
- mappings(IdentifiableEntity.class, IdentifiableEntity.class.getDeclaredField("code")).unsetId(entity);
- assertNull(entity.code);
- }
-
@Test
void idOfEntityWithPropertyAccessIsUnsetViaSetter() throws ReflectiveOperationException {
var entity = new PropertyAccessEntity();
@@ -101,23 +85,6 @@ static class PlainEntity {
}
- @SuppressWarnings({"deprecation", "removal"})
- static class IdentifiableEntity implements Identifiable {
-
- Long code;
-
- @Override
- public Long getId() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void setId(Long id) {
- throw new UnsupportedOperationException();
- }
-
- }
-
static class PropertyAccessEntity {
private Long value;
diff --git a/src/test/java/org/omnifaces/persistence/service/IdAttributeTest.java b/src/test/java/org/omnifaces/persistence/service/IdAttributeTest.java
index db30909..a1e7a87 100644
--- a/src/test/java/org/omnifaces/persistence/service/IdAttributeTest.java
+++ b/src/test/java/org/omnifaces/persistence/service/IdAttributeTest.java
@@ -32,7 +32,6 @@
import org.junit.jupiter.api.Test;
import org.omnifaces.persistence.model.GeneratedIdEntity;
-import org.omnifaces.persistence.model.Identifiable;
/**
* Unit tests for {@link IdAttribute}. The metamodel is stubbed, see {@link Stubs}.
@@ -72,14 +71,6 @@ void idIsSetViaBaseEntityMethodsWhenExtended() throws ReflectiveOperationExcepti
assertNull(entity.getId());
}
- @Test
- void idOfIdentifiableEntityNotExtendingBaseEntityIsSetViaIdAttribute() throws ReflectiveOperationException {
- var entity = new IdentifiableEntity();
- entity.code = 42L;
- idAttribute(IdentifiableEntity.class.getDeclaredField("code")).set(entity, null);
- assertNull(entity.code);
- }
-
@Test
void idClassIsRejected() {
var entityType = stub(EntityType.class, Map.of("hasSingleIdAttribute", false, "getJavaType", Object.class));
@@ -123,23 +114,6 @@ static class FieldAccessEntity {
}
- @SuppressWarnings({"deprecation", "removal"})
- static class IdentifiableEntity implements Identifiable {
-
- Long code;
-
- @Override
- public Long getId() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void setId(Long id) {
- throw new UnsupportedOperationException();
- }
-
- }
-
static class PrimitiveIdEntity {
long code;
diff --git a/src/test/java/org/omnifaces/persistence/test/BaseEntityTest.java b/src/test/java/org/omnifaces/persistence/test/BaseEntityTest.java
index 29aeca1..6fa9ecf 100644
--- a/src/test/java/org/omnifaces/persistence/test/BaseEntityTest.java
+++ b/src/test/java/org/omnifaces/persistence/test/BaseEntityTest.java
@@ -18,7 +18,9 @@
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.omnifaces.persistence.test.Serializations.serializeAndDeserialize;
+import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
@@ -670,6 +672,24 @@ void equalsWorksWithNonComparable() {
}
+ // ----------------------------------------------------------------------------------------------------------------
+ // Serialization
+ // ----------------------------------------------------------------------------------------------------------------
+
+ @Nested
+ class Serialization {
+
+ @Test
+ void baseEntityIsSerializable() throws Exception {
+ assertTrue(Serializable.class.isAssignableFrom(BaseEntity.class));
+
+ var person = new Person();
+ person.setId(42L);
+ assertEquals(person, serializeAndDeserialize(person));
+ }
+
+ }
+
// ----------------------------------------------------------------------------------------------------------------
// Helper methods
// ----------------------------------------------------------------------------------------------------------------
diff --git a/src/test/java/org/omnifaces/persistence/test/EntityRepositoryIT.java b/src/test/java/org/omnifaces/persistence/test/EntityRepositoryIT.java
index 0b08055..37fbd56 100644
--- a/src/test/java/org/omnifaces/persistence/test/EntityRepositoryIT.java
+++ b/src/test/java/org/omnifaces/persistence/test/EntityRepositoryIT.java
@@ -305,8 +305,16 @@ void testGetIdOfEntityWithoutBaseEntity() {
articleRepository.persist(article);
});
assertEquals(article.getCode(), articleRepository.getId(article), "Generated code after persist");
- var lazyCategorySlug = transactionServiceCDI.call(() -> categoryRepository.getId(articleRepository.getById(article.getCode()).getCategory()));
- assertEquals("getid", lazyCategorySlug, "Slug of lazy category");
+ var lazyCategory = transactionServiceCDI.call(() -> {
+ var reference = articleRepository.getById(article.getCode()).getCategory();
+ var provider = categoryRepository.getProvider();
+ return List.of(categoryRepository.getId(reference), provider.isProxy(reference), provider.isProxyUninitialized(reference));
+ });
+ assertEquals("getid", lazyCategory.get(0), "Slug of lazy category");
+
+ if (!OmniPersistenceIT.isEclipseLink() && !OmniPersistenceIT.isOpenJPA()) {
+ assertEquals(List.of(true, true), lazyCategory.subList(1, 3), "Lazy category is a proxy which stays uninitialized");
+ }
}
finally {
deleteArticles(List.of(article));
diff --git a/src/test/java/org/omnifaces/persistence/test/IdentifiableTest.java b/src/test/java/org/omnifaces/persistence/test/IdentifiableTest.java
deleted file mode 100644
index 2a8abaf..0000000
--- a/src/test/java/org/omnifaces/persistence/test/IdentifiableTest.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright OmniFaces
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
- * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations under the License.
- */
-package org.omnifaces.persistence.test;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.omnifaces.persistence.test.Serializations.serializeAndDeserialize;
-
-import java.io.Serializable;
-
-import org.junit.jupiter.api.Test;
-import org.omnifaces.persistence.model.BaseEntity;
-import org.omnifaces.persistence.model.Identifiable;
-import org.omnifaces.persistence.test.model.Person;
-
-/**
- * {@link Identifiable} does not require its implementations to be serializable, but {@link BaseEntity} and therefore all its subclasses are.
- */
-@SuppressWarnings("removal")
-class IdentifiableTest {
-
- @Test
- void identifiableIsNotSerializable() {
- assertFalse(Serializable.class.isAssignableFrom(Identifiable.class));
- }
-
- @Test
- void baseEntityIsSerializable() throws Exception {
- assertTrue(Serializable.class.isAssignableFrom(BaseEntity.class));
-
- var person = new Person();
- person.setId(42L);
- assertEquals(person, serializeAndDeserialize(person));
- }
-
-}