Add update path

This commit is contained in:
Michael Buckley 2024-08-29 11:23:45 -04:00
parent d4090ae604
commit a60294cc19
9 changed files with 162 additions and 24 deletions

View File

@ -102,6 +102,32 @@ abstract public class BasicEntityTestTemplate<R extends IRootEntity<J>,J extends
}
@ParameterizedTest
@MethodSource("getPartitions")
void updateResourceTable(Integer thePartitionId) {
doInTx(em->{
R root = myFixture.buildRootEntity();
root.setPartitionId(thePartitionId);
root.setString("hello!");
em.persist(root);
em.flush();
em.clear();
Object id = myEntityManagerFactory.getPersistenceUnitUtil().getIdentifier(root);
ourLog.info("flushed root entity. Id is {}", id);
R readback = em.find(myFixture.myRootType, id);
readback.setString("goodbye!");
em.flush();
em.clear();
readback = em.find(myFixture.myRootType, id);
assertNotNull(readback);
assertEquals("goodbye!", readback.getString());
});
}
@ParameterizedTest
@MethodSource("getPartitions")
void roundTripJoin(Integer thePartitionId) {
@ -167,15 +193,23 @@ abstract public class BasicEntityTestTemplate<R extends IRootEntity<J>,J extends
em.flush();
em.clear();
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<R> cr = cb.createQuery(myFixture.myRootType);
Root<R> from = cr.from(myFixture.myRootType);
from.fetch("myJoinEntities");
cr.select(from);
em.createQuery(cr).getResultStream()
.forEach(e-> ourLog.info("e: {}", e));
List<R> resultList = em.createQuery(cr).getResultList();
assertEquals(1,resultList.size());
resultList.forEach(e-> {
ourLog.info("root: {}", e);
assertNotNull(e);
assertNotNull(e.getJoins());
assertEquals(2, e.getJoins().size());
assertNotNull(e.getJoins().iterator().next());
e.getJoins().forEach(j-> ourLog.info("join: {}", j));
});
});
}

View File

@ -35,10 +35,9 @@ public class IdClassPkCustomXmlJpaBindingTest {
Consumer<HapiFhirLocalContainerEntityManagerFactoryBean> entityManagerFactoryCustomizer() {
return em->{
ourLog.info("Injecting custom persistence.xml");
em.setMappingResources("/ca/uhn/fhir/jpa/model/pkspike/idclass/orm.xml");
em.setMappingResources("/ca/uhn/fhir/jpa/model/pkspike/idclass/ormComposite.xml");
};
}
}
static final BasicEntityTestFixture<ResRootIdClassEntity, ResJoinIdClassEntity> ourFixture = BasicEntityTestFixture.buildNoNullPartition(ResRootIdClassEntity.class, ResJoinIdClassEntity.class);

View File

@ -1,5 +1,6 @@
package ca.uhn.fhir.jpa.model.pkspike.idclass;
import ca.uhn.fhir.jpa.config.HapiFhirLocalContainerEntityManagerFactoryBean;
import ca.uhn.fhir.jpa.config.r4.FhirContextR4Config;
import ca.uhn.fhir.jpa.model.pkspike.BasicEntityTestTemplate;
import ca.uhn.fhir.jpa.model.pkspike.BasicEntityTestFixture;
@ -9,18 +10,36 @@ import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.api.extension.ParameterResolver;
import org.junit.jupiter.api.extension.RegisterExtension;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import java.util.function.Consumer;
/**
* Use an IdClass even though the PK is only a single column.
* This allows us to extend the PK next door in the {@link IdClassPkCustomXmlJpaBindingTest}.
*/
@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = {
IdClassKeyTypesConfig.class, PKSpikeDefaultJPAConfig.class, FhirContextR4Config.class
IdClassPkJpaBindingTest.Config.class, IdClassKeyTypesConfig.class, PKSpikeDefaultJPAConfig.class, FhirContextR4Config.class
})
public class IdClassPkJpaBindingTest {
private static final Logger ourLog = LoggerFactory.getLogger(IdClassPkJpaBindingTest.class);
@Configuration
static class Config {
@Bean
Consumer<HapiFhirLocalContainerEntityManagerFactoryBean> entityManagerFactoryCustomizer() {
return em->{
ourLog.info("Injecting custom persistence.xml");
em.setMappingResources("/ca/uhn/fhir/jpa/model/pkspike/idclass/ormLong.xml");
};
}
}
public static final BasicEntityTestFixture<ResRootIdClassEntity, ResJoinIdClassEntity> ourFixture = BasicEntityTestFixture.build(ResRootIdClassEntity.class, ResJoinIdClassEntity.class);
@RegisterExtension

View File

@ -6,23 +6,31 @@ import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.IdClass;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.JoinColumns;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import jakarta.persistence.Transient;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.hibernate.annotations.PartitionKey;
@SuppressWarnings("JpaDataSourceORMInspection")
@Entity
@Table(
name = "RES_JOIN"
)
@IdClass(ResJoinIdClassEntity.ResJoinPK.class)
public class ResJoinIdClassEntity implements IJoinEntity<ResRootIdClassEntity> {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
@Column(name = "PID")
Long myId;
@PartitionKey
@Column(name = "PARTITION_ID", nullable = true, insertable = true, updatable = false)
Integer myPartitionId;
@ -78,4 +86,52 @@ public class ResJoinIdClassEntity implements IJoinEntity<ResRootIdClassEntity> {
// fixme keep copy
return myResource == null? null: myResource.myId;
}
static class ResJoinPK {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
@Column(name = "PID")
Long myId;
/** for Hibernate */
public ResJoinPK() {}
public ResJoinPK(Long theId) {
myId = theId;
}
@Override
public boolean equals(Object theO) {
return EqualsBuilder.reflectionEquals(this,theO);
}
@Override
public int hashCode() {
return HashCodeBuilder.reflectionHashCode(this);
}
@Override
public String toString() {
return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
}
}
static class ResJoinCompositePK extends ResJoinPK {
@Id
@Column(name = "PARTITION_ID", nullable = false, insertable = false, updatable = false)
Integer myPartitionId;
/** for Hibernate */
public ResJoinCompositePK() {}
public ResJoinCompositePK(Long theId, Integer thePartitionId) {
super(theId);
myPartitionId = thePartitionId;
}
}
}

View File

@ -13,6 +13,7 @@ import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.hibernate.annotations.PartitionKey;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

View File

@ -22,7 +22,7 @@ import org.springframework.test.context.junit.jupiter.SpringExtension;
})
class PartitionJpaBindingTest {
static final BasicEntityTestFixture<ResRootPartitionEntity, ResJoinPartitionEntity> ourConfig = BasicEntityTestFixture.build(ResRootPartitionEntity.class, ResJoinPartitionEntity.class);
static final BasicEntityTestFixture<ResRootPartitionEntity, ResJoinPartitionEntity> ourConfig = BasicEntityTestFixture.buildNoNullPartition(ResRootPartitionEntity.class, ResJoinPartitionEntity.class);
@RegisterExtension
static final ParameterResolver ourResolver = ValueTypeBasedParameterResolver.build(ourConfig);

View File

@ -25,8 +25,9 @@ public class ResJoinPartitionEntity implements IJoinEntity<ResRootPartitionEntit
@GeneratedValue(strategy = GenerationType.SEQUENCE)
@Column(name = "PID")
Long myId;
@PartitionKey
@Column(name = "PARTITION_ID", nullable = true, insertable = true, updatable = false)
@Column(name = "PARTITION_ID", nullable = true, insertable = false, updatable = false)
Integer myPartitionId;
@Column(name = "STRING_COL")
@ -38,7 +39,8 @@ public class ResJoinPartitionEntity implements IJoinEntity<ResRootPartitionEntit
@ManyToOne(
optional = false)
@JoinColumns({
@JoinColumn(name = "RES_ID", referencedColumnName = "RES_ID", nullable = false, insertable = true, updatable = false)
@JoinColumn(name = "RES_ID", referencedColumnName = "RES_ID", nullable = false, insertable = true, updatable = false),
@JoinColumn(name = "PARTITION_ID", referencedColumnName = "PARTITION_ID", nullable = false, insertable = true, updatable = false)
})
ResRootPartitionEntity myResource;

View File

@ -6,32 +6,34 @@
http://java.sun.com/xml/ns/persistence/orm_2_2.xsd"
>
<entity class="ca.uhn.fhir.jpa.model.pkspike.idclass.ResRootIdClassEntity" name="ResRootIdClassEntity">
<id-class class="ca.uhn.fhir.jpa.model.pkspike.idclass.ResRootIdClassEntity$ResRootCompositePK"/>
<!-- <id-class class="ca.uhn.fhir.jpa.model.pkspike.idclass.ResRootIdClassEntity$ResRootCompositePK"/>-->
<attributes>
<id name="myPartitionId" access="FIELD">
<column name="PARTITION_ID" insertable="true" updatable="false"/>
</id>
<one-to-many name="myJoinEntities" access="FIELD">
<join-column name="RES_ID"/>
<join-column name="PARTITION_ID"/>
</one-to-many>
<!-- <id name="myId" access="FIELD">-->
<!-- <column name="RES_ID"/>-->
<!-- <generated-value strategy="SEQUENCE"/>-->
<!-- </id>-->
<!-- <id name="myPartitionId" access="FIELD">-->
<!-- <column name="PARTITION_ID" insertable="true" updatable="false"/>-->
<!-- </id>-->
</attributes>
</entity>
<entity class="ca.uhn.fhir.jpa.model.pkspike.idclass.ResJoinIdClassEntity">
<!-- <id-class class="ca.uhn.fhir.jpa.model.pkspike.idclass.ResJoinIdClassEntity$ResJoinCompositePK"/>-->
<attributes>
<id name="myId" access="FIELD">
<column name="PID"/>
<generated-value strategy="SEQUENCE"/>
</id>
<!-- <id name="myPartitionId" access="FIELD">-->
<!-- <column name="PARTITION_ID" insertable="false"/>-->
<!-- <id name="myId" access="FIELD">-->
<!-- <column name="PID"/>-->
<!-- <generated-value strategy="SEQUENCE"/>-->
<!-- </id>-->
<basic name="myPartitionId" access="FIELD">
<column name="PARTITION_ID" insertable="false" updatable="false"/>
</basic>
<!-- <basic name="myPartitionId" access="FIELD">-->
<!-- <column name="PARTITION_ID" insertable="false" updatable="false"/>-->
<!-- </basic>-->
<many-to-one name="myResource" access="FIELD">
<join-column name="RES_ID" referenced-column-name="RES_ID"/>
<join-column name="PARTITION_ID" referenced-column-name="PARTITION_ID" />
<join-column name="PARTITION_ID" referenced-column-name="PARTITION_ID"/>
</many-to-one>
</attributes>
</entity>

View File

@ -0,0 +1,25 @@
<entity-mappings
xmlns="http://java.sun.com/xml/ns/persistence/orm"
version="2.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm
http://java.sun.com/xml/ns/persistence/orm_2_2.xsd"
>
<entity class="ca.uhn.fhir.jpa.model.pkspike.idclass.ResRootIdClassEntity" name="ResRootIdClassEntity">
<attributes>
<basic name="myPartitionId" access="FIELD">
<column name="PARTITION_ID" insertable="true" updatable="false"/>
</basic>
</attributes>
</entity>
<entity class="ca.uhn.fhir.jpa.model.pkspike.idclass.ResJoinIdClassEntity">
<attributes>
<basic name="myPartitionId" access="FIELD">
<column name="PARTITION_ID" insertable="true" updatable="false"/>
</basic>
<!-- <many-to-one name="myResource" access="FIELD">-->
<!-- <join-column name="RES_ID" referenced-column-name="RES_ID"/>-->
<!-- </many-to-one>-->
</attributes>
</entity>
</entity-mappings>