HHH-8070 - Added IN criteria support to AuditRelatedId.
This commit is contained in:
parent
6871824f4d
commit
383972d6c2
|
@ -6,15 +6,16 @@
|
|||
*/
|
||||
package org.hibernate.envers.query.criteria;
|
||||
|
||||
import org.hibernate.envers.query.criteria.internal.RelatedAuditExpression;
|
||||
import org.hibernate.envers.query.criteria.internal.RelatedAuditEqualityExpression;
|
||||
import org.hibernate.envers.query.criteria.internal.RelatedAuditInExpression;
|
||||
import org.hibernate.envers.query.internal.property.PropertyNameGetter;
|
||||
|
||||
/**
|
||||
* Create restrictions on an id of an entity related to an audited entity.
|
||||
*
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
* @author Chris Cranford
|
||||
*/
|
||||
@SuppressWarnings({"JavaDoc"})
|
||||
public class AuditRelatedId {
|
||||
private final PropertyNameGetter propertyNameGetter;
|
||||
|
||||
|
@ -23,16 +24,32 @@ public class AuditRelatedId {
|
|||
}
|
||||
|
||||
/**
|
||||
* Apply an "equal" constraint
|
||||
* Applies an "equals" criteria predicate.
|
||||
*
|
||||
* @param id the value to test equality with
|
||||
* @return the criterion.
|
||||
*/
|
||||
public AuditCriterion eq(Object id) {
|
||||
return new RelatedAuditExpression( propertyNameGetter, id, true );
|
||||
return new RelatedAuditEqualityExpression( propertyNameGetter, id, true );
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply a "not equal" constraint
|
||||
* Applies a "not equals" criteria predicate.
|
||||
*
|
||||
* @param id the value to test inequality with
|
||||
* @return the criterion
|
||||
*/
|
||||
public AuditCriterion ne(Object id) {
|
||||
return new RelatedAuditExpression( propertyNameGetter, id, false );
|
||||
return new RelatedAuditEqualityExpression( propertyNameGetter, id, false );
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies an "in" criteria predicate.
|
||||
*
|
||||
* @param values the values to test with
|
||||
* @return the criterion
|
||||
*/
|
||||
public AuditCriterion in(Object[] values) {
|
||||
return new RelatedAuditInExpression( propertyNameGetter, values );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,14 +16,15 @@ import org.hibernate.envers.query.criteria.AuditCriterion;
|
|||
import org.hibernate.envers.query.internal.property.PropertyNameGetter;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
* @author Chris Cranford
|
||||
* @since 5.2
|
||||
*/
|
||||
public class RelatedAuditExpression implements AuditCriterion {
|
||||
public class RelatedAuditEqualityExpression implements AuditCriterion {
|
||||
private final PropertyNameGetter propertyNameGetter;
|
||||
private final Object id;
|
||||
private final boolean equals;
|
||||
|
||||
public RelatedAuditExpression(PropertyNameGetter propertyNameGetter, Object id, boolean equals) {
|
||||
public RelatedAuditEqualityExpression(PropertyNameGetter propertyNameGetter, Object id, boolean equals) {
|
||||
this.propertyNameGetter = propertyNameGetter;
|
||||
this.id = id;
|
||||
this.equals = equals;
|
||||
|
@ -45,15 +46,11 @@ public class RelatedAuditExpression implements AuditCriterion {
|
|||
);
|
||||
|
||||
RelationDescription relatedEntity = CriteriaTools.getRelatedEntity( enversService, entityName, propertyName );
|
||||
|
||||
if ( relatedEntity == null ) {
|
||||
throw new AuditException(
|
||||
"This criterion can only be used on a property that is " +
|
||||
"a relation to another property."
|
||||
"This criterion can only be used on a property that is a relation to another property."
|
||||
);
|
||||
}
|
||||
else {
|
||||
relatedEntity.getIdMapper().addIdEqualsToQuery( parameters, id, null, equals );
|
||||
}
|
||||
relatedEntity.getIdMapper().addIdEqualsToQuery( parameters, id, null, equals );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.envers.query.criteria.internal;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.envers.boot.internal.EnversService;
|
||||
import org.hibernate.envers.exception.AuditException;
|
||||
import org.hibernate.envers.internal.entities.RelationDescription;
|
||||
import org.hibernate.envers.internal.entities.mapper.id.QueryParameterData;
|
||||
import org.hibernate.envers.internal.reader.AuditReaderImplementor;
|
||||
import org.hibernate.envers.internal.tools.query.Parameters;
|
||||
import org.hibernate.envers.internal.tools.query.QueryBuilder;
|
||||
import org.hibernate.envers.query.criteria.AuditCriterion;
|
||||
import org.hibernate.envers.query.internal.property.PropertyNameGetter;
|
||||
|
||||
/**
|
||||
* @author Chris Cranford
|
||||
* @since 5.2
|
||||
*/
|
||||
public class RelatedAuditInExpression implements AuditCriterion {
|
||||
|
||||
private final PropertyNameGetter propertyNameGetter;
|
||||
private final Object[] ids;
|
||||
|
||||
public RelatedAuditInExpression(PropertyNameGetter propertyNameGetter, Object[] ids) {
|
||||
this.propertyNameGetter = propertyNameGetter;
|
||||
this.ids = ids;
|
||||
}
|
||||
|
||||
public void addToQuery(EnversService enversService,
|
||||
AuditReaderImplementor versionsReader,
|
||||
String entityName,
|
||||
String alias,
|
||||
QueryBuilder qb,
|
||||
Parameters parameters) {
|
||||
String propertyName = CriteriaTools.determinePropertyName(
|
||||
enversService,
|
||||
versionsReader,
|
||||
entityName,
|
||||
propertyNameGetter
|
||||
);
|
||||
|
||||
RelationDescription relatedEntity = CriteriaTools.getRelatedEntity( enversService, entityName, propertyName );
|
||||
if ( relatedEntity == null ) {
|
||||
throw new AuditException(
|
||||
"The criterion can only be used on a property that is a relation to another property."
|
||||
);
|
||||
}
|
||||
|
||||
// todo: should this throw an error if qpdList is null? is it possible?
|
||||
List<QueryParameterData> qpdList = relatedEntity.getIdMapper().mapToQueryParametersFromId( propertyName );
|
||||
if ( qpdList != null ) {
|
||||
QueryParameterData qpd = qpdList.iterator().next();
|
||||
parameters.addWhereWithParams( qpd.getQueryParameterName(), "in (", ids, ")" );
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,145 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.envers.test.integration.onetomany.relatedid;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
|
||||
import org.hibernate.envers.query.AuditEntity;
|
||||
import org.hibernate.envers.query.AuditQuery;
|
||||
import org.hibernate.envers.test.BaseEnversJPAFunctionalTestCase;
|
||||
import org.hibernate.envers.test.Priority;
|
||||
import org.hibernate.envers.test.tools.TestTools;
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* @author Chris Cranford
|
||||
*/
|
||||
@TestForIssue(jiraKey = "HHH-8070")
|
||||
public class AuditRelatedIdInTest extends BaseEnversJPAFunctionalTestCase {
|
||||
private Integer company1Id;
|
||||
private Integer company2Id;
|
||||
private Integer company3Id;
|
||||
private Integer employee1Id;
|
||||
private Integer employee2Id;
|
||||
private Integer employee3Id;
|
||||
private Integer employee4Id;
|
||||
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class<?>[]{
|
||||
Company.class,
|
||||
Employee.class
|
||||
};
|
||||
}
|
||||
|
||||
@Test
|
||||
@Priority(10)
|
||||
public void initData() {
|
||||
EntityManager em = getOrCreateEntityManager();
|
||||
try {
|
||||
// Revision 1
|
||||
Company company1 = new Company( "COMPANY1" );
|
||||
Company company2 = new Company( "COMPANY2" );
|
||||
Employee employee1 = new Employee( "Employee1", company1 );
|
||||
Employee employee2 = new Employee( "Employee2", company2 );
|
||||
Employee employee3 = new Employee( "Employee3", company2 );
|
||||
em.getTransaction().begin();
|
||||
em.persist( company1 );
|
||||
em.persist( company2 );
|
||||
em.persist( employee1 );
|
||||
em.persist( employee2 );
|
||||
em.persist( employee3 );
|
||||
em.getTransaction().commit();
|
||||
|
||||
// cache ids
|
||||
company1Id = company1.getId();
|
||||
company2Id = company2.getId();
|
||||
employee1Id = employee1.getId();
|
||||
employee2Id = employee2.getId();
|
||||
employee3Id = employee3.getId();
|
||||
|
||||
// Revision 2
|
||||
em.getTransaction().begin();
|
||||
employee2 = em.find( Employee.class, employee2.getId() );
|
||||
employee2.setCompany( company1 );
|
||||
company2 = em.find( Company.class, company2.getId() );
|
||||
company2.setName( "COMPANY2-CHANGED" );
|
||||
em.merge( employee2 );
|
||||
em.merge( company2 );
|
||||
em.getTransaction().commit();
|
||||
|
||||
// Revision 3
|
||||
Company company3 = new Company( "COMPANY3" );
|
||||
Employee employee4 = new Employee( "Employee4", company3 );
|
||||
em.getTransaction().begin();
|
||||
em.persist( company3 );
|
||||
em.persist( employee4 );
|
||||
em.getTransaction().commit();
|
||||
|
||||
// cache ids
|
||||
employee4Id = employee4.getId();
|
||||
company3Id = company3.getId();
|
||||
}
|
||||
finally {
|
||||
em.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRevisionCounts() {
|
||||
// companies
|
||||
assertEquals( 1, getAuditReader().getRevisions( Company.class, company1Id ).size() );
|
||||
assertEquals( 2, getAuditReader().getRevisions( Company.class, company2Id ).size() );
|
||||
assertEquals( 1, getAuditReader().getRevisions( Company.class, company3Id ).size() );
|
||||
// employees
|
||||
assertEquals( 1, getAuditReader().getRevisions( Employee.class, employee1Id ).size() );
|
||||
assertEquals( 2, getAuditReader().getRevisions( Employee.class, employee2Id ).size() );
|
||||
assertEquals( 1, getAuditReader().getRevisions( Employee.class, employee3Id ).size() );
|
||||
assertEquals( 1, getAuditReader().getRevisions( Employee.class, employee4Id ).size() );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCompany1EmployeeIn() {
|
||||
AuditQuery auditQuery = getAuditReader().createQuery().forRevisionsOfEntity( Employee.class, true, true );
|
||||
auditQuery.add( AuditEntity.relatedId( "company" ).in( new Integer[]{ company1Id } ) );
|
||||
final List<Employee> results = auditQuery.getResultList();
|
||||
assertEquals( 2, results.size() );
|
||||
final Employee employee1 = makeEmployee( employee1Id, "Employee1", company1Id, "COMPANY1" );
|
||||
final Employee employee2 = makeEmployee( employee2Id, "Employee2", company1Id, "COMPANY1" );
|
||||
assertEquals( results, TestTools.makeList( employee1, employee2 ) );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCompany2EmployeeIn() {
|
||||
AuditQuery auditQuery = getAuditReader().createQuery().forRevisionsOfEntity( Employee.class, true, true );
|
||||
auditQuery.add( AuditEntity.relatedId( "company" ).in( new Integer[]{ company2Id } ) );
|
||||
final List<Employee> results = auditQuery.getResultList();
|
||||
assertEquals( 2, results.size() );
|
||||
final Employee employee1 = makeEmployee( employee2Id, "Employee2", company2Id, "COMPANY2" );
|
||||
final Employee employee2 = makeEmployee( employee3Id, "Employee3", company2Id, "COMPANY2" );
|
||||
assertEquals( results, TestTools.makeList( employee1, employee2 ) );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCompany3EmployeeIn() {
|
||||
AuditQuery auditQuery = getAuditReader().createQuery().forRevisionsOfEntity( Employee.class, true, true );
|
||||
auditQuery.add( AuditEntity.relatedId( "company" ).in( new Integer[]{ company3Id } ) );
|
||||
final List<Employee> results = auditQuery.getResultList();
|
||||
assertEquals( 1, results.size() );
|
||||
final Employee employee = makeEmployee( employee4Id, "Employee4", company3Id, "COMPANY3" );
|
||||
assertEquals( results, TestTools.makeList( employee ) );
|
||||
}
|
||||
|
||||
private Employee makeEmployee(Integer employeeId, String employeeName, Integer companyId, String companyName) {
|
||||
return new Employee( employeeId, employeeName, new Company( companyId, companyName ) );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.envers.test.integration.onetomany.relatedid;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.OneToMany;
|
||||
|
||||
import org.hibernate.envers.Audited;
|
||||
|
||||
/**
|
||||
* @author Chris Cranford
|
||||
*/
|
||||
@Entity
|
||||
@Audited
|
||||
public class Company {
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private Integer id;
|
||||
private String name;
|
||||
@OneToMany
|
||||
private List<Employee> employees = new ArrayList<Employee>();
|
||||
|
||||
Company() {
|
||||
|
||||
}
|
||||
|
||||
public Company(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Company(Integer id, String name) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public List<Employee> getEmployees() {
|
||||
return employees;
|
||||
}
|
||||
|
||||
public void setEmployees(List<Employee> employees) {
|
||||
this.employees = employees;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result;
|
||||
result = ( id != null ? id.hashCode() : 0 );
|
||||
result = 31 * result + ( name != null ? name.hashCode() : 0 );
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object object) {
|
||||
if ( object == this ) {
|
||||
return true;
|
||||
}
|
||||
if ( !( object instanceof Company) ) {
|
||||
return false;
|
||||
}
|
||||
Company that = (Company) object;
|
||||
if ( getId() != null ? !getId().equals( that.getId() ) : that.getId() != null ) {
|
||||
return false;
|
||||
}
|
||||
if ( getName() != null ? !getName().equals( that.getName() ) : that.getName() != null ) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Company{" +
|
||||
"id=" + id +
|
||||
", name='" + name + '\'' + '}';
|
||||
}
|
||||
}
|
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.envers.test.integration.onetomany.relatedid;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.ManyToOne;
|
||||
|
||||
import org.hibernate.envers.Audited;
|
||||
|
||||
/**
|
||||
* @author Chris Cranford
|
||||
*/
|
||||
@Entity
|
||||
@Audited
|
||||
public class Employee {
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private Integer id;
|
||||
private String name;
|
||||
@ManyToOne
|
||||
private Company company;
|
||||
|
||||
Employee() {
|
||||
|
||||
}
|
||||
|
||||
public Employee(String name, Company company) {
|
||||
this( null, name, company );
|
||||
}
|
||||
|
||||
public Employee(Integer id, String name, Company company) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.company = company;
|
||||
}
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Company getCompany() {
|
||||
return company;
|
||||
}
|
||||
|
||||
public void setCompany(Company company) {
|
||||
this.company = company;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result;
|
||||
result = ( id != null ? id.hashCode() : 0 );
|
||||
result = 31 * result + ( name != null ? name.hashCode() : 0 );
|
||||
result = 31 * result + ( company != null ? company.hashCode() : 0 );
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object object) {
|
||||
if ( object == this ) {
|
||||
return true;
|
||||
}
|
||||
if ( !( object instanceof Employee) ) {
|
||||
return false;
|
||||
}
|
||||
Employee that = (Employee) object;
|
||||
if ( getId() != null ? !getId().equals( that.getId() ) : that.getId() != null ) {
|
||||
return false;
|
||||
}
|
||||
if ( getName() != null ? !getName().equals( that.getName() ) : that.getName() != null ) {
|
||||
return false;
|
||||
}
|
||||
if ( getCompany() != null ? !getCompany().equals( that.getCompany() ) : that.getCompany() != null ) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Employee{" +
|
||||
"id=" + id +
|
||||
", name='" + name + '\'' +
|
||||
", company=" + company +
|
||||
'}';
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue