Skip to content

Commit

Permalink
HHH-3854 - Fix and test
Browse files Browse the repository at this point in the history
  • Loading branch information
lukasz-antoniak committed Nov 11, 2012
1 parent 0d2a967 commit 94e1307
Show file tree
Hide file tree
Showing 10 changed files with 703 additions and 13 deletions.
@@ -0,0 +1,53 @@
package org.hibernate.envers.entities.mapper.relation;

import java.io.Serializable;

import org.hibernate.envers.configuration.AuditConfiguration;
import org.hibernate.envers.entities.mapper.relation.lazy.ToOneDelegateSessionImplementor;
import org.hibernate.envers.reader.AuditReaderImplementor;
import org.hibernate.persister.entity.EntityPersister;

/**
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
*/
public class ToOneEntityLoader {
/**
* Immediately loads historical entity or its current state when excluded from audit process.
*/
public static Object loadImmediate(AuditReaderImplementor versionsReader, Class<?> entityClass, String entityName,
Object entityId, Number revision, AuditConfiguration verCfg) {
if ( verCfg.getEntCfg().getNotVersionEntityConfiguration( entityName ) == null ) {
// Audited relation, look up entity with Envers.
return versionsReader.find( entityClass, entityName, entityId, revision );
}
else {
// Not audited relation, look up entity with Hibernate.
return versionsReader.getSessionImplementor().immediateLoad( entityName, (Serializable) entityId );
}
}

/**
* Creates proxy of referenced *-to-one entity.
*/
public static Object createProxy(AuditReaderImplementor versionsReader, Class<?> entityClass, String entityName,
Object entityId, Number revision, AuditConfiguration verCfg) {
EntityPersister persister = versionsReader.getSessionImplementor().getFactory().getEntityPersister( entityName );
return persister.createProxy(
(Serializable) entityId,
new ToOneDelegateSessionImplementor( versionsReader, entityClass, entityId, revision, verCfg )
);
}

/**
* Creates Hibernate proxy or retrieves the complete object of an entity if proxy is not
* allowed (e.g. @Proxy(lazy=false), final class).
*/
public static Object createProxyOrLoadImmediate(AuditReaderImplementor versionsReader, Class<?> entityClass, String entityName,
Object entityId, Number revision, AuditConfiguration verCfg) {
EntityPersister persister = versionsReader.getSessionImplementor().getFactory().getEntityPersister( entityName );
if ( persister.hasProxy() ) {
return createProxy( versionsReader, entityClass, entityName, entityId, revision, verCfg );
}
return loadImmediate( versionsReader, entityClass, entityName, entityId, revision, verCfg );
}
}
Expand Up @@ -34,6 +34,7 @@
import org.hibernate.envers.entities.mapper.relation.lazy.ToOneDelegateSessionImplementor;
import org.hibernate.envers.reader.AuditReaderImplementor;
import org.hibernate.envers.tools.Tools;
import org.hibernate.persister.entity.EntityPersister;

/**
* @author Adam Warski (adam at warski dot org)
Expand Down Expand Up @@ -95,10 +96,10 @@ public void nullSafeMapToEntityFromMap(AuditConfiguration verCfg, Object obj, Ma
value = versionsReader.getFirstLevelCache().get(referencedEntityName, revision, entityId);
} else {
EntityInfo referencedEntity = getEntityInfo(verCfg, referencedEntityName);

value = versionsReader.getSessionImplementor().getFactory().getEntityPersister(referencedEntityName).
createProxy((Serializable)entityId, new ToOneDelegateSessionImplementor(versionsReader, referencedEntity.getEntityClass(),
entityId, revision, verCfg));
value = ToOneEntityLoader.createProxyOrLoadImmediate(
versionsReader, referencedEntity.getEntityClass(), referencedEntityName,
entityId, revision, verCfg
);
}
}

Expand Down
Expand Up @@ -27,6 +27,7 @@
import org.hibernate.HibernateException;
import org.hibernate.envers.configuration.AuditConfiguration;
import org.hibernate.envers.entities.EntitiesConfigurations;
import org.hibernate.envers.entities.mapper.relation.ToOneEntityLoader;
import org.hibernate.envers.reader.AuditReaderImplementor;

/**
Expand All @@ -41,7 +42,7 @@ public class ToOneDelegateSessionImplementor extends AbstractDelegateSessionImpl
private final Class<?> entityClass;
private final Object entityId;
private final Number revision;
private EntitiesConfigurations entCfg;
private final AuditConfiguration verCfg;

public ToOneDelegateSessionImplementor(AuditReaderImplementor versionsReader,
Class<?> entityClass, Object entityId, Number revision,
Expand All @@ -51,16 +52,10 @@ public ToOneDelegateSessionImplementor(AuditReaderImplementor versionsReader,
this.entityClass = entityClass;
this.entityId = entityId;
this.revision = revision;
this.entCfg = verCfg.getEntCfg();
this.verCfg = verCfg;
}

public Object doImmediateLoad(String entityName) throws HibernateException {
if(entCfg.getNotVersionEntityConfiguration(entityName) == null){
// audited relation, look up entity with envers
return versionsReader.find(entityClass, entityName, entityId, revision);
} else {
// notAudited relation, look up entity with hibernate
return delegate.immediateLoad(entityName, (Serializable) entityId);
}
return ToOneEntityLoader.loadImmediate( versionsReader, entityClass, entityName, entityId, revision, verCfg );
}
}
@@ -0,0 +1,121 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2011, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.envers.test.entities.onetoone;

import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToOne;

import org.hibernate.annotations.Proxy;
import org.hibernate.envers.Audited;
import org.hibernate.envers.NotAudited;

/**
* Test class for issue HHH-3854. Restricting creation of proxy objects is essential.
*/
@Entity
@Audited
@Proxy(lazy=false)
public final class BidirectionalEagerAnnotationRefEdOneToOne {
/**
* ID column.
*/
@Id
@GeneratedValue
private Integer id;

/**
* Field containing the referring entity.
*/
@OneToOne(mappedBy = "refedOne", fetch = FetchType.EAGER)
@NotAudited
private BidirectionalEagerAnnotationRefIngOneToOne refIng;

/**
* Field containing some data.
*/
private String data;

@Override
public boolean equals(Object o) {
if ( this == o ) return true;
if ( ! ( o instanceof BidirectionalEagerAnnotationRefEdOneToOne ) ) return false;

BidirectionalEagerAnnotationRefEdOneToOne that = (BidirectionalEagerAnnotationRefEdOneToOne) o;

if ( data != null ? !data.equals( that.data ) : that.data != null ) return false;
if ( id != null ? !id.equals( that.id ) : that.id != null ) return false;

return true;
}

@Override
public int hashCode() {
int result = id != null ? id.hashCode() : 0;
result = 31 * result + ( data != null ? data.hashCode() : 0 );
return result;
}

@Override
public String toString() {
return "BidirectionalEagerAnnotationRefEdOneToOne(id = " + id + ", data = " + data + ")";
}

/**
* @return the id
*/
public Integer getId() {
return id;
}

/**
* @return the refIng
*/
public BidirectionalEagerAnnotationRefIngOneToOne getRefIng() {
return refIng;
}

/**
* @param refIng the refIng to set
*/
public void setRefIng(BidirectionalEagerAnnotationRefIngOneToOne refIng) {
this.refIng = refIng;
}

/**
* @return the data
*/
public String getData() {
return data;
}

/**
* @param data the data to set
*/
public void setData(String data) {
this.data = data;
}
}
@@ -0,0 +1,143 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2011, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.envers.test.entities.onetoone;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;

import org.hibernate.annotations.Proxy;
import org.hibernate.envers.Audited;

/**
* Test class for issue HHH-3854. Restricting creation of proxy objects is essential.
*/
@Entity
@Audited
@Proxy(lazy=false)
public final class BidirectionalEagerAnnotationRefIngOneToOne {
/**
* ID column.
*/
@Id
@GeneratedValue
private Integer id;

/**
* Field with an optional first referred entity.
*/
@OneToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL, optional = true)
@JoinColumn(name = "REF_ID_ONE")
private BidirectionalEagerAnnotationRefEdOneToOne refedOne = null;

/**
* Field with an optional second referred entity.
*/
@OneToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL, optional = true)
@JoinColumn(name = "REF_ID_TWO")
private BidirectionalEagerAnnotationRefEdOneToOne refedTwo = null;

/**
* Field containing some data.
*/
private String data;

@Override
public boolean equals(Object o) {
if ( this == o ) return true;
if ( ! ( o instanceof BidirectionalEagerAnnotationRefIngOneToOne ) ) return false;

BidirectionalEagerAnnotationRefIngOneToOne that = (BidirectionalEagerAnnotationRefIngOneToOne) o;

if ( data != null ? !data.equals( that.data ) : that.data != null ) return false;
if ( id != null ? !id.equals( that.id ) : that.id != null ) return false;

return true;
}

@Override
public int hashCode() {
int result = id != null ? id.hashCode() : 0;
result = 31 * result + ( data != null ? data.hashCode() : 0 );
return result;
}

@Override
public String toString() {
return "BidirectionalEagerAnnotationRefIngOneToOne(id = " + id + ", data = " + data + ")";
}

/**
* @return the id
*/
public Integer getId() {
return id;
}

/**
* @return the refedOne
*/
public BidirectionalEagerAnnotationRefEdOneToOne getRefedOne() {
return refedOne;
}

/**
* @param refedOne the refedOne to set
*/
public void setRefedOne(BidirectionalEagerAnnotationRefEdOneToOne refedOne) {
this.refedOne = refedOne;
}

/**
* @return the refedTwo
*/
public BidirectionalEagerAnnotationRefEdOneToOne getRefedTwo() {
return refedTwo;
}

/**
* @param refedTwo the refedTwo to set
*/
public void setRefedTwo(BidirectionalEagerAnnotationRefEdOneToOne refedTwo) {
this.refedTwo = refedTwo;
}

/**
* @return the data
*/
public String getData() {
return data;
}

/**
* @param data the data to set
*/
public void setData(String data) {
this.data = data;
}
}

0 comments on commit 94e1307

Please sign in to comment.