Skip to content

Commit

Permalink
Merge pull request #28339 from njr-11/22762-jdql-update-and-delete-wi…
Browse files Browse the repository at this point in the history
…th-record-entity

JDQL update and delete with record entity, and omitted select clause returning different type
  • Loading branch information
njr-11 authored May 4, 2024
2 parents c810a5d + 15c8f48 commit 0c892b3
Show file tree
Hide file tree
Showing 10 changed files with 273 additions and 172 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import com.ibm.websphere.ras.annotation.Trivial;
import com.ibm.ws.ffdc.annotation.FFDCIgnore;

import io.openliberty.data.internal.persistence.cdi.DataExtensionProvider;
import jakarta.persistence.EntityManager;
import jakarta.persistence.metamodel.Attribute;
import jakarta.persistence.metamodel.Attribute.PersistentAttributeType;
Expand Down Expand Up @@ -65,13 +66,19 @@ public abstract class EntityManagerBuilder implements Runnable {
*/
final ConcurrentHashMap<Class<?>, CompletableFuture<EntityInfo>> entityInfoMap = new ConcurrentHashMap<>();

/**
* OSGi service component that provides the CDI extension for Data.
*/
final DataExtensionProvider provider;

/**
* The class loader for repository classes.
*/
private final ClassLoader repositoryClassLoader;

@Trivial
protected EntityManagerBuilder(ClassLoader repositoryClassLoader) {
protected EntityManagerBuilder(DataExtensionProvider provider, ClassLoader repositoryClassLoader) {
this.provider = provider;
this.repositoryClassLoader = repositoryClassLoader;
}

Expand Down

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ public void afterBeanDiscovery(@Observes AfterBeanDiscovery event, BeanManager b
EntityManagerFactory emf = instance.get();

if (emBuilder == null)
emBuilder = new PUnitEMBuilder(emf, loader);
emBuilder = new PUnitEMBuilder(emf, loader, provider);
else
throw new UnsupportedOperationException//
("The " + method.getName() + " resource accessor method of the " +
Expand All @@ -225,7 +225,7 @@ public void afterBeanDiscovery(@Observes AfterBeanDiscovery event, BeanManager b
try {
Object resource = InitialContext.doLookup(dataStore);
if (resource instanceof EntityManagerFactory)
emBuilder = new PUnitEMBuilder((EntityManagerFactory) resource, dataStore, loader);
emBuilder = new PUnitEMBuilder((EntityManagerFactory) resource, dataStore, loader, provider);

if (trace && tc.isDebugEnabled())
Tr.debug(this, tc, dataStore + " is the JNDI name for " + resource);
Expand All @@ -238,7 +238,7 @@ public void afterBeanDiscovery(@Observes AfterBeanDiscovery event, BeanManager b
Object resource = InitialContext.doLookup(javaCompName);

if (resource instanceof EntityManagerFactory)
emBuilder = new PUnitEMBuilder((EntityManagerFactory) resource, javaCompName, loader);
emBuilder = new PUnitEMBuilder((EntityManagerFactory) resource, javaCompName, loader, provider);

if (emBuilder != null || resource instanceof DataSource) {
isJNDIName = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import com.ibm.ws.threadContext.ComponentMetaDataAccessorImpl;

import io.openliberty.data.internal.persistence.EntityManagerBuilder;
import io.openliberty.data.internal.persistence.cdi.DataExtensionProvider;
import jakarta.persistence.EntityManager;
import jakarta.persistence.EntityManagerFactory;

Expand All @@ -37,8 +38,8 @@ public class PUnitEMBuilder extends EntityManagerBuilder {

private final String persistenceUnitRef;

public PUnitEMBuilder(EntityManagerFactory emf, ClassLoader repositoryClassLoader) {
super(repositoryClassLoader);
public PUnitEMBuilder(EntityManagerFactory emf, ClassLoader repositoryClassLoader, DataExtensionProvider provider) {
super(provider, repositoryClassLoader);
this.emf = emf;
this.persistenceUnitRef = emf.toString();

Expand All @@ -52,8 +53,9 @@ public PUnitEMBuilder(EntityManagerFactory emf, ClassLoader repositoryClassLoade
// DataStoreTestApp#DataStoreTestWeb.war, org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl@3708cabf]
}

public PUnitEMBuilder(EntityManagerFactory emf, String persistenceUnitRef, ClassLoader repositoryClassLoader) {
super(repositoryClassLoader);
public PUnitEMBuilder(EntityManagerFactory emf, String persistenceUnitRef,
ClassLoader repositoryClassLoader, DataExtensionProvider provider) {
super(provider, repositoryClassLoader);
this.emf = emf;
this.persistenceUnitRef = persistenceUnitRef;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ public class DBStoreEMBuilder extends EntityManagerBuilder {
public DBStoreEMBuilder(String dataStore, boolean isConfigDisplayId, boolean isJNDIName,
AnnotatedType<?> type, ClassLoader repositoryClassLoader,
DataExtensionProvider provider) {
super(repositoryClassLoader);
super(provider, repositoryClassLoader);
final boolean trace = TraceComponent.isAnyTracingEnabled();

ComponentMetaData cData = ComponentMetaDataAccessorImpl.getComponentMetaDataAccessor().getComponentMetaData();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3592,7 +3592,11 @@ public void testRecordInFromClause() {
assertEquals(20.98f, receipts.totalOf(2000L), 0.001f);
assertEquals(15.99f, receipts.totalOf(2001L), 0.001f);

receipts.deleteByTotalLessThan(2000.0f);
assertEquals(true, receipts.addTax(2001L, 0.0813f));

assertEquals(17.29f, receipts.totalOf(2001L), 0.001f);

assertEquals(2, receipts.removeIfTotalUnder(2000.0f));
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@
*/
@Repository
public interface Receipts extends CrudRepository<Receipt, Long> {
@Query("UPDATE Receipt SET total = total * (1.0 + :taxRate) WHERE purchaseId = :id")
boolean addTax(long id, float taxRate);

@Query("SELECT COUNT(this)")
long count();

Expand All @@ -42,6 +45,9 @@ public interface Receipts extends CrudRepository<Receipt, Long> {

Stream<Receipt> findByPurchaseIdIn(Iterable<Long> ids);

@Query("DELETE FROM Receipt WHERE total < :max")
int removeIfTotalUnder(float max);

@Query("SELECT total FROM Receipt WHERE purchaseId=:id")
float totalOf(long id);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2458,6 +2458,66 @@ public void testParenthesisInsertionForCursorPagination() {
assertEquals(false, page3.hasNext());
}

/**
* Use a repository method that runs a query without specifying an entity type
* and returns a record entity. The repository must be able to infer the record type
* to use from the return value and generate the proper select clause so that the
* generated entity type is converted to the record type.
*/
@Test
public void testRecordQueryInfersSelectClause() {

Rebate r1 = new Rebate(10, 10.00, "testRecordEntityInferredFromReturnType-CustomerA", //
LocalTime.of(15, 40, 0), //
LocalDate.of(2024, Month.MAY, 1), //
Rebate.Status.PAID, //
LocalDateTime.of(2024, Month.MAY, 1, 15, 40, 0), //
null);

Rebate r2 = new Rebate(12, 12.00, "testRecordEntityInferredFromReturnType-CustomerA", //
LocalTime.of(12, 46, 30), //
LocalDate.of(2024, Month.APRIL, 5), //
Rebate.Status.PAID, //
LocalDateTime.of(2024, Month.MAY, 2, 10, 18, 0), //
null);

Rebate r3 = new Rebate(13, 3.00, "testRecordEntityInferredFromReturnType-CustomerB", //
LocalTime.of(9, 15, 0), //
LocalDate.of(2024, Month.MAY, 2), //
Rebate.Status.PAID, //
LocalDateTime.of(2024, Month.MAY, 2, 9, 15, 0), //
null);

Rebate r4 = new Rebate(14, 4.00, "testRecordEntityInferredFromReturnType-CustomerA", //
LocalTime.of(10, 55, 0), //
LocalDate.of(2024, Month.MAY, 1), //
Rebate.Status.VERIFIED, //
LocalDateTime.of(2024, Month.MAY, 2, 14, 27, 45), //
null);

Rebate r5 = new Rebate(15, 5.00, "testRecordEntityInferredFromReturnType-CustomerA", //
LocalTime.of(17, 50, 0), //
LocalDate.of(2024, Month.MAY, 1), //
Rebate.Status.PAID, //
LocalDateTime.of(2024, Month.MAY, 5, 15, 5, 0), //
null);

Rebate[] all = rebates.addAll(r1, r2, r3, r4, r5);

List<Rebate> paid = rebates.paidTo("testRecordEntityInferredFromReturnType-CustomerA");

assertEquals(paid.toString(), 3, paid.size());
Rebate r;
r = paid.get(0);
assertEquals(12.0f, r.amount(), 0.001);
r = paid.get(1);
assertEquals(10.0f, r.amount(), 0.001);
r = paid.get(2);
assertEquals(5.0f, r.amount(), 0.001);

rebates.removeAll(all);
}

/**
* Tests lifecycle methods returning a single record.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import jakarta.data.repository.Delete;
import jakarta.data.repository.Insert;
import jakarta.data.repository.Query;
import jakarta.data.repository.Repository;
import jakarta.data.repository.Save;
import jakarta.data.repository.Update;
Expand Down Expand Up @@ -45,6 +46,9 @@ public interface Rebates { // Do not allow this interface to inherit from other
@Update
List<Rebate> modifyMultiple(List<Rebate> r);

@Query("WHERE customerId=?1 AND status=test.jakarta.data.jpa.web.Rebate.Status.PAID ORDER BY amount DESC, id ASC")
List<Rebate> paidTo(String customerId);

@Save
Rebate process(Rebate r);

Expand Down

0 comments on commit 0c892b3

Please sign in to comment.