Performance enhancements on JPA history
This commit is contained in:
parent
54078be6e0
commit
ee4ca9c934
|
@ -35,7 +35,6 @@ import ca.uhn.fhir.context.RuntimeSearchParam;
|
|||
import ca.uhn.fhir.jpa.entity.BaseHasResource;
|
||||
import ca.uhn.fhir.jpa.entity.BaseTag;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceHistoryTable;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceHistoryTablePk;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceHistoryTag;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamDate;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamNumber;
|
||||
|
@ -127,9 +126,9 @@ public abstract class BaseFhirDao {
|
|||
q.setMaxResults(myConfig.getHardSearchLimit());
|
||||
}
|
||||
for (Tuple next : q.getResultList()) {
|
||||
long id = (Long) next.get(0);
|
||||
Date updated = (Date) next.get(1);
|
||||
tuples.add(new HistoryTuple(ResourceTable.class, updated, id));
|
||||
long id = next.get(0, Long.class);
|
||||
Date updated = next.get(1, Date.class);
|
||||
tuples.add(new HistoryTuple(false, updated, id));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -137,13 +136,13 @@ public abstract class BaseFhirDao {
|
|||
Collection<HistoryTuple> tuples = Collections2.filter(theTuples, new com.google.common.base.Predicate<HistoryTuple>() {
|
||||
@Override
|
||||
public boolean apply(HistoryTuple theInput) {
|
||||
return theInput.getTable().equals(ResourceTable.class);
|
||||
return theInput.isHistory() == false;
|
||||
}
|
||||
});
|
||||
Collection<Long> ids = Collections2.transform(tuples, new Function<HistoryTuple, Long>() {
|
||||
@Override
|
||||
public Long apply(HistoryTuple theInput) {
|
||||
return (Long) theInput.getId();
|
||||
return theInput.getId();
|
||||
}
|
||||
});
|
||||
if (ids.isEmpty()) {
|
||||
|
@ -162,11 +161,11 @@ public abstract class BaseFhirDao {
|
|||
}
|
||||
}
|
||||
|
||||
private void searchHistoryHistory(String theResourceName, Long theId, Date theSince, Integer theLimit, List<HistoryTuple> tuples) {
|
||||
private void searchHistoryHistory(String theResourceName, Long theResourceId, Date theSince, Integer theLimit, List<HistoryTuple> tuples) {
|
||||
CriteriaBuilder builder = myEntityManager.getCriteriaBuilder();
|
||||
CriteriaQuery<Tuple> cq = builder.createTupleQuery();
|
||||
Root<?> from = cq.from(ResourceHistoryTable.class);
|
||||
cq.multiselect(from.get("myPk").as(ResourceHistoryTablePk.class), from.get("myUpdated").as(Date.class));
|
||||
cq.multiselect(from.get("myId").as(Long.class), from.get("myUpdated").as(Date.class));
|
||||
|
||||
List<Predicate> predicates = new ArrayList<Predicate>();
|
||||
if (theSince != null) {
|
||||
|
@ -177,8 +176,8 @@ public abstract class BaseFhirDao {
|
|||
if (theResourceName != null) {
|
||||
predicates.add(builder.equal(from.get("myResourceType"), theResourceName));
|
||||
}
|
||||
if (theId != null) {
|
||||
predicates.add(builder.equal(from.get("myId"), theId));
|
||||
if (theResourceId != null) {
|
||||
predicates.add(builder.equal(from.get("myResourceId"), theResourceId));
|
||||
}
|
||||
|
||||
cq.where(builder.and(predicates.toArray(new Predicate[0])));
|
||||
|
@ -191,9 +190,9 @@ public abstract class BaseFhirDao {
|
|||
q.setMaxResults(myConfig.getHardSearchLimit());
|
||||
}
|
||||
for (Tuple next : q.getResultList()) {
|
||||
ResourceHistoryTablePk id = (ResourceHistoryTablePk) next.get(0);
|
||||
Long id = next.get(0, Long.class);
|
||||
Date updated = (Date) next.get(1);
|
||||
tuples.add(new HistoryTuple(ResourceHistoryTable.class, updated, id));
|
||||
tuples.add(new HistoryTuple(true, updated, id));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -203,13 +202,13 @@ public abstract class BaseFhirDao {
|
|||
Collection<HistoryTuple> tuples = Collections2.filter(theTuples, new com.google.common.base.Predicate<HistoryTuple>() {
|
||||
@Override
|
||||
public boolean apply(HistoryTuple theInput) {
|
||||
return theInput.getTable().equals(ResourceHistoryTable.class);
|
||||
return theInput.isHistory()==true;
|
||||
}
|
||||
});
|
||||
Collection<ResourceHistoryTablePk> ids = Collections2.transform(tuples, new Function<HistoryTuple, ResourceHistoryTablePk>() {
|
||||
Collection<Long> ids = Collections2.transform(tuples, new Function<HistoryTuple, Long>() {
|
||||
@Override
|
||||
public ResourceHistoryTablePk apply(HistoryTuple theInput) {
|
||||
return (ResourceHistoryTablePk) theInput.getId();
|
||||
public Long apply(HistoryTuple theInput) {
|
||||
return (Long) theInput.getId();
|
||||
}
|
||||
});
|
||||
if (ids.isEmpty()) {
|
||||
|
@ -221,7 +220,7 @@ public abstract class BaseFhirDao {
|
|||
CriteriaBuilder builder = myEntityManager.getCriteriaBuilder();
|
||||
CriteriaQuery<ResourceHistoryTable> cq = builder.createQuery(ResourceHistoryTable.class);
|
||||
Root<ResourceHistoryTable> from = cq.from(ResourceHistoryTable.class);
|
||||
cq.where(from.get("myPk").in(ids));
|
||||
cq.where(from.get("myId").in(ids));
|
||||
|
||||
cq.orderBy(builder.desc(from.get("myUpdated")));
|
||||
TypedQuery<ResourceHistoryTable> q = myEntityManager.createQuery(cq);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package ca.uhn.fhir.jpa.dao;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.*;
|
||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
|
@ -36,7 +36,6 @@ import ca.uhn.fhir.context.RuntimeSearchParam;
|
|||
import ca.uhn.fhir.jpa.entity.BaseHasResource;
|
||||
import ca.uhn.fhir.jpa.entity.BaseTag;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceHistoryTable;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceHistoryTablePk;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamDate;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamNumber;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamString;
|
||||
|
@ -493,7 +492,7 @@ public class FhirResourceDao<T extends IResource> extends BaseFhirDao implements
|
|||
ArrayList<T> retVal = new ArrayList<T>();
|
||||
|
||||
String resourceType = getContext().getResourceDefinition(myResourceType).getName();
|
||||
TypedQuery<ResourceHistoryTable> q = myEntityManager.createQuery(ResourceHistoryTable.Q_GETALL, ResourceHistoryTable.class);
|
||||
TypedQuery<ResourceHistoryTable> q = myEntityManager.createQuery("SELECT h FROM ResourceHistoryTable h WHERE h.myResourceId = :PID AND h.myResourceType = :RESTYPE ORDER BY h.myUpdated ASC", ResourceHistoryTable.class);
|
||||
q.setParameter("PID", theId.asLong());
|
||||
q.setParameter("RESTYPE", resourceType);
|
||||
|
||||
|
@ -558,7 +557,11 @@ public class FhirResourceDao<T extends IResource> extends BaseFhirDao implements
|
|||
|
||||
if (entity == null) {
|
||||
if (theId.hasUnqualifiedVersionId()) {
|
||||
entity = myEntityManager.find(ResourceHistoryTable.class, new ResourceHistoryTablePk(myResourceName, theId.asLong(), theId.getUnqualifiedVersionIdAsLong()));
|
||||
TypedQuery<ResourceHistoryTable> q = myEntityManager.createQuery("SELECT t from ResourceHistoryTable t WHERE t.myResourceId = :RID AND t.myResourceType = :RTYP AND t.myResourceVersion = :RVER", ResourceHistoryTable.class);
|
||||
q.setParameter("RID", theId.asLong());
|
||||
q.setParameter("RTYP", myResourceName);
|
||||
q.setParameter("RVER", theId.getUnqualifiedVersionIdAsLong());
|
||||
entity = q.getSingleResult();
|
||||
}
|
||||
if (entity == null) {
|
||||
throw new ResourceNotFoundException(theId);
|
||||
|
|
|
@ -4,13 +4,13 @@ import java.util.Date;
|
|||
|
||||
class HistoryTuple implements Comparable<HistoryTuple> {
|
||||
|
||||
private Object myId;
|
||||
private Class<?> myTable;
|
||||
private Long myId;
|
||||
private boolean myIsHistory;
|
||||
private Date myUpdated;
|
||||
|
||||
public HistoryTuple(Class<?> theTable, Date theUpdated, Object theId) {
|
||||
public HistoryTuple(boolean theIsHistory, Date theUpdated, Long theId) {
|
||||
super();
|
||||
myTable = theTable;
|
||||
myIsHistory = theIsHistory;
|
||||
myUpdated = theUpdated;
|
||||
myId = theId;
|
||||
}
|
||||
|
@ -20,24 +20,24 @@ class HistoryTuple implements Comparable<HistoryTuple> {
|
|||
return myUpdated.compareTo(theO.myUpdated);
|
||||
}
|
||||
|
||||
public Object getId() {
|
||||
public Long getId() {
|
||||
return myId;
|
||||
}
|
||||
|
||||
public Class<?> getTable() {
|
||||
return myTable;
|
||||
public boolean isHistory() {
|
||||
return myIsHistory;
|
||||
}
|
||||
|
||||
public Date getUpdated() {
|
||||
return myUpdated;
|
||||
}
|
||||
|
||||
public void setId(Object theId) {
|
||||
public void setId(Long theId) {
|
||||
myId = theId;
|
||||
}
|
||||
|
||||
public void setTable(Class<?> theTable) {
|
||||
myTable = theTable;
|
||||
public void setIsHistory(boolean theIsHistory) {
|
||||
myIsHistory = theIsHistory;
|
||||
}
|
||||
|
||||
public void setUpdated(Date theUpdated) {
|
||||
|
|
|
@ -6,11 +6,14 @@ import java.util.Collection;
|
|||
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.EmbeddedId;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.UniqueConstraint;
|
||||
|
||||
import org.hibernate.annotations.Index;
|
||||
|
||||
|
@ -18,61 +21,30 @@ import ca.uhn.fhir.model.primitive.IdDt;
|
|||
import ca.uhn.fhir.rest.server.Constants;
|
||||
|
||||
@Entity
|
||||
@Table(name = "HFJ_RES_VER", uniqueConstraints = {})
|
||||
@Table(name = "HFJ_RES_VER", uniqueConstraints = {@UniqueConstraint(name="IDX_RES_VER_ALL", columnNames = { "RES_ID", "RES_TYPE", "RES_VER" })})
|
||||
@org.hibernate.annotations.Table(appliesTo="HFJ_RES_VER", indexes= {@Index(name="IDX_RES_VER_DATE", columnNames= {"RES_UPDATED"})})
|
||||
public class ResourceHistoryTable extends BaseHasResource implements Serializable {
|
||||
|
||||
public static final String Q_GETALL = "SELECT h FROM ResourceHistoryTable h WHERE h.myPk.myId = :PID AND h.myPk.myResourceType = :RESTYPE ORDER BY h.myUpdated ASC";
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@EmbeddedId
|
||||
private ResourceHistoryTablePk myPk;
|
||||
|
||||
@Column(name="RES_TYPE",insertable=false, updatable=false)
|
||||
@Id
|
||||
@GeneratedValue(strategy=GenerationType.AUTO)
|
||||
@Column(name="PID")
|
||||
private Long myId;
|
||||
|
||||
@Column(name = "RES_ID")
|
||||
private Long myResourceId;
|
||||
|
||||
@Column(name = "RES_TYPE", length = 30, nullable = false)
|
||||
private String myResourceType;
|
||||
|
||||
@Column(name="PID", insertable=false, updatable=false)
|
||||
private Long myId;
|
||||
@Column(name = "RES_VER", nullable = false)
|
||||
private Long myResourceVersion;
|
||||
|
||||
@OneToMany(mappedBy = "myResourceHistory", cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true)
|
||||
private Collection<ResourceHistoryTag> myTags;
|
||||
|
||||
@Override
|
||||
public IdDt getIdDt() {
|
||||
return new IdDt(myPk.getResourceType() + '/' + myPk.getId() + '/' + Constants.PARAM_HISTORY + '/' + myPk.getVersion());
|
||||
}
|
||||
|
||||
public ResourceHistoryTablePk getPk() {
|
||||
return myPk;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public String getResourceType() {
|
||||
return myPk.getResourceType();
|
||||
// try {
|
||||
// return (Class<IResource>) Class.forName(Patient.class.getPackage().getName() + "." + myPk.getResourceType());
|
||||
// } catch (ClassNotFoundException e) {
|
||||
// throw new InternalErrorException(e);
|
||||
// }
|
||||
}
|
||||
|
||||
public Collection<ResourceHistoryTag> getTags() {
|
||||
if (myTags == null) {
|
||||
myTags = new ArrayList<ResourceHistoryTag>();
|
||||
}
|
||||
return myTags;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getVersion() {
|
||||
return myPk.getVersion();
|
||||
}
|
||||
|
||||
public void setPk(ResourceHistoryTablePk thePk) {
|
||||
myPk = thePk;
|
||||
}
|
||||
|
||||
public void addTag(ResourceHistoryTag theTag) {
|
||||
for (ResourceHistoryTag next : getTags()) {
|
||||
if (next.getTag().getTerm().equals(theTag)) {
|
||||
|
@ -82,15 +54,6 @@ public class ResourceHistoryTable extends BaseHasResource implements Serializabl
|
|||
getTags().add(theTag);
|
||||
}
|
||||
|
||||
public boolean hasTag(String theTerm, String theLabel, String theScheme) {
|
||||
for (ResourceHistoryTag next : getTags()) {
|
||||
if (next.getTag().getScheme().equals(theScheme) && next.getTag().getTerm().equals(theTerm)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void addTag(ResourceTag theTag) {
|
||||
ResourceHistoryTag tag = new ResourceHistoryTag(this, theTag.getTag());
|
||||
tag.setResourceType(theTag.getResourceType());
|
||||
|
@ -104,4 +67,51 @@ public class ResourceHistoryTable extends BaseHasResource implements Serializabl
|
|||
return historyTag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IdDt getIdDt() {
|
||||
return new IdDt(getResourceType() + '/' + getResourceId() + '/' + Constants.PARAM_HISTORY + '/' + getVersion());
|
||||
}
|
||||
|
||||
public Long getResourceId() {
|
||||
return myResourceId;
|
||||
}
|
||||
|
||||
public String getResourceType() {
|
||||
return myResourceType;
|
||||
}
|
||||
|
||||
|
||||
public Collection<ResourceHistoryTag> getTags() {
|
||||
if (myTags == null) {
|
||||
myTags = new ArrayList<ResourceHistoryTag>();
|
||||
}
|
||||
return myTags;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getVersion() {
|
||||
return myResourceVersion;
|
||||
}
|
||||
|
||||
public boolean hasTag(String theTerm, String theLabel, String theScheme) {
|
||||
for (ResourceHistoryTag next : getTags()) {
|
||||
if (next.getTag().getScheme().equals(theScheme) && next.getTag().getTerm().equals(theTerm)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setResourceId(Long theResourceId) {
|
||||
myResourceId = theResourceId;
|
||||
}
|
||||
|
||||
public void setResourceType(String theResourceType) {
|
||||
myResourceType=theResourceType;
|
||||
}
|
||||
|
||||
public void setVersion(long theVersion) {
|
||||
myResourceVersion=theVersion;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,94 +0,0 @@
|
|||
package ca.uhn.fhir.jpa.entity;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Embeddable;
|
||||
|
||||
@Embeddable
|
||||
public class ResourceHistoryTablePk implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Column(name = "PID")
|
||||
private Long myId;
|
||||
|
||||
@Column(name = "RES_TYPE", length = 30, nullable = false)
|
||||
private String myResourceType;
|
||||
|
||||
@Column(name = "VERSION", nullable = false)
|
||||
private Long myVersion;
|
||||
|
||||
public ResourceHistoryTablePk() {
|
||||
// nothing
|
||||
}
|
||||
|
||||
public ResourceHistoryTablePk(String theResourceType, Long theResourceId, Long theVersion) {
|
||||
super();
|
||||
myResourceType = theResourceType;
|
||||
myId = theResourceId;
|
||||
myVersion = theVersion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((myId == null) ? 0 : myId.hashCode());
|
||||
result = prime * result + ((myResourceType == null) ? 0 : myResourceType.hashCode());
|
||||
result = prime * result + ((myVersion == null) ? 0 : myVersion.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
ResourceHistoryTablePk other = (ResourceHistoryTablePk) obj;
|
||||
if (myId == null) {
|
||||
if (other.myId != null)
|
||||
return false;
|
||||
} else if (!myId.equals(other.myId))
|
||||
return false;
|
||||
if (myResourceType == null) {
|
||||
if (other.myResourceType != null)
|
||||
return false;
|
||||
} else if (!myResourceType.equals(other.myResourceType))
|
||||
return false;
|
||||
if (myVersion == null) {
|
||||
if (other.myVersion != null)
|
||||
return false;
|
||||
} else if (!myVersion.equals(other.myVersion))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return myId;
|
||||
}
|
||||
|
||||
public String getResourceType() {
|
||||
return myResourceType;
|
||||
}
|
||||
|
||||
public Long getVersion() {
|
||||
return myVersion;
|
||||
}
|
||||
|
||||
public void setId(Long theId) {
|
||||
myId = theId;
|
||||
}
|
||||
|
||||
public void setResourceType(String theResourceType) {
|
||||
myResourceType = theResourceType;
|
||||
}
|
||||
|
||||
public void setVersion(Long theVersion) {
|
||||
myVersion = theVersion;
|
||||
}
|
||||
|
||||
}
|
|
@ -8,7 +8,6 @@ import javax.persistence.GeneratedValue;
|
|||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.JoinColumns;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.Table;
|
||||
|
||||
|
@ -23,17 +22,13 @@ public class ResourceHistoryTag extends BaseTag implements Serializable {
|
|||
private Long myId;
|
||||
|
||||
@ManyToOne()
|
||||
@JoinColumns(value= {
|
||||
@JoinColumn(name="RES_TYPE", referencedColumnName="RES_TYPE"),
|
||||
@JoinColumn(name="PID", referencedColumnName="PID"),
|
||||
@JoinColumn(name="VERSION", referencedColumnName="VERSION")
|
||||
}/*, foreignKey=@ForeignKey(name="FK_HT_RT")*/)
|
||||
@JoinColumn(name="RES_VER_PID", referencedColumnName="PID", nullable=false)
|
||||
private ResourceHistoryTable myResourceHistory;
|
||||
|
||||
@Column(name = "RES_TYPE", length = ResourceTable.RESTYPE_LEN,nullable=false, insertable=false, updatable=false)
|
||||
@Column(name = "RES_TYPE", length = ResourceTable.RESTYPE_LEN, nullable=false)
|
||||
private String myResourceType;
|
||||
|
||||
@Column(name="PID", insertable=false,updatable=false)
|
||||
@Column(name="RES_ID", nullable=false)
|
||||
private Long myResourceId;
|
||||
|
||||
public String getResourceType() {
|
||||
|
@ -63,6 +58,7 @@ public class ResourceHistoryTag extends BaseTag implements Serializable {
|
|||
public ResourceHistoryTag(ResourceHistoryTable theResourceHistoryTable, TagDefinition theTag) {
|
||||
myResourceHistory=theResourceHistoryTable;
|
||||
setTag(theTag);
|
||||
setResourceId(theResourceHistoryTable.getResourceId());
|
||||
}
|
||||
|
||||
public ResourceHistoryTable getResourceHistory() {
|
||||
|
|
|
@ -250,11 +250,9 @@ public class ResourceTable extends BaseHasResource implements Serializable {
|
|||
public ResourceHistoryTable toHistory(FhirContext theCtx) {
|
||||
ResourceHistoryTable retVal = new ResourceHistoryTable();
|
||||
|
||||
ResourceHistoryTablePk pk = new ResourceHistoryTablePk();
|
||||
pk.setId(myId);
|
||||
pk.setResourceType(myResourceType);
|
||||
pk.setVersion(myVersion);
|
||||
retVal.setPk(pk);
|
||||
retVal.setResourceId(myId);
|
||||
retVal.setResourceType(myResourceType);
|
||||
retVal.setVersion(myVersion);
|
||||
|
||||
retVal.setPublished(getPublished());
|
||||
retVal.setUpdated(getUpdated());
|
||||
|
|
Loading…
Reference in New Issue