HHH-17189 Respect Audited annotations in component mapped super types
This commit is contained in:
parent
1cc7def6f9
commit
586cafa4a1
|
@ -114,6 +114,11 @@ public class ComponentAuditedPropertiesReader extends AuditedPropertiesReader {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// make sure that if a component is annotated with audited, it is honored.
|
||||||
|
if ( allClassAudited != null ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// assumption here is if a component reader is looking at a @MappedSuperclass, it should be treated
|
// assumption here is if a component reader is looking at a @MappedSuperclass, it should be treated
|
||||||
// as not being audited if we have reached htis point; allowing components and any @Embeddable
|
// as not being audited if we have reached htis point; allowing components and any @Embeddable
|
||||||
// class being audited by default.
|
// class being audited by default.
|
||||||
|
|
|
@ -0,0 +1,71 @@
|
||||||
|
/*
|
||||||
|
* 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.orm.test.envers.integration.components.mappedsuperclass;
|
||||||
|
|
||||||
|
import jakarta.persistence.Access;
|
||||||
|
import jakarta.persistence.AccessType;
|
||||||
|
import jakarta.persistence.MappedSuperclass;
|
||||||
|
|
||||||
|
import org.hibernate.envers.Audited;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Chris Cranford
|
||||||
|
*/
|
||||||
|
@MappedSuperclass
|
||||||
|
@Access(AccessType.FIELD)
|
||||||
|
@Audited
|
||||||
|
public abstract class AbstractAuditedEmbeddable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initial Value
|
||||||
|
*/
|
||||||
|
protected static final int UNDEFINED = -1;
|
||||||
|
|
||||||
|
private int code = UNDEFINED;
|
||||||
|
|
||||||
|
|
||||||
|
protected AbstractAuditedEmbeddable() {
|
||||||
|
this( UNDEFINED );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor with code
|
||||||
|
*/
|
||||||
|
public AbstractAuditedEmbeddable(int code) {
|
||||||
|
this.code = code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getCode() {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result = 1;
|
||||||
|
result = prime * result + code;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if ( this == obj ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if ( obj == null ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( getClass() != obj.getClass() ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
AbstractAuditedEmbeddable other = (AbstractAuditedEmbeddable) obj;
|
||||||
|
if ( code != other.code ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
/*
|
||||||
|
* 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.orm.test.envers.integration.components.mappedsuperclass;
|
||||||
|
|
||||||
|
import jakarta.persistence.Embeddable;
|
||||||
|
|
||||||
|
import org.hibernate.envers.Audited;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Chris Cranford
|
||||||
|
*/
|
||||||
|
@Embeddable
|
||||||
|
@Audited
|
||||||
|
public class AuditedEmbeddableWithDeclaredData extends AbstractAuditedEmbeddable {
|
||||||
|
|
||||||
|
private String codeArt;
|
||||||
|
|
||||||
|
public AuditedEmbeddableWithDeclaredData(int code, String codeArt) {
|
||||||
|
super( code );
|
||||||
|
this.codeArt = codeArt;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Needed for @Embeddable
|
||||||
|
protected AuditedEmbeddableWithDeclaredData() {
|
||||||
|
this( UNDEFINED, null );
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCodeart() {
|
||||||
|
return codeArt;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result = super.hashCode();
|
||||||
|
result = prime * result + ( ( codeArt == null ) ? 0 : codeArt.hashCode() );
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if ( this == obj ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if ( !super.equals( obj ) ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( getClass() != obj.getClass() ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
AuditedEmbeddableWithDeclaredData other = (AuditedEmbeddableWithDeclaredData) obj;
|
||||||
|
if ( codeArt == null ) {
|
||||||
|
if ( other.codeArt != null ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ( !codeArt.equals( other.codeArt ) ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,77 @@
|
||||||
|
/*
|
||||||
|
* 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.orm.test.envers.integration.components.mappedsuperclass;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.hibernate.envers.AuditReader;
|
||||||
|
import org.hibernate.envers.AuditReaderFactory;
|
||||||
|
import org.hibernate.orm.test.envers.BaseEnversJPAFunctionalTestCase;
|
||||||
|
import org.hibernate.orm.test.envers.Priority;
|
||||||
|
|
||||||
|
import org.hibernate.testing.orm.junit.JiraKey;
|
||||||
|
import org.hibernate.testing.transaction.TransactionUtil;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Chris Cranford
|
||||||
|
*/
|
||||||
|
@JiraKey("HHH-17189")
|
||||||
|
public class AuditedEmbeddableWithDeclaredDataTest extends BaseEnversJPAFunctionalTestCase {
|
||||||
|
|
||||||
|
private long id;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<?>[] getAnnotatedClasses() {
|
||||||
|
return new Class[] {
|
||||||
|
EntityWithAuditedEmbeddableWithDeclaredData.class,
|
||||||
|
AbstractAuditedEmbeddable.class,
|
||||||
|
AuditedEmbeddableWithDeclaredData.class
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Priority(10)
|
||||||
|
public void initData() {
|
||||||
|
this.id = TransactionUtil.doInJPA( this::entityManagerFactory, entityManager -> {
|
||||||
|
final EntityWithAuditedEmbeddableWithDeclaredData entity = new EntityWithAuditedEmbeddableWithDeclaredData();
|
||||||
|
entity.setName( "Entity 1" );
|
||||||
|
entity.setValue( new AuditedEmbeddableWithDeclaredData( 42, "Data" ) );
|
||||||
|
|
||||||
|
entityManager.persist(entity);
|
||||||
|
return entity.getId();
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEmbeddableThatExtendsAuditedMappedSuperclass() {
|
||||||
|
TransactionUtil.doInJPA( this::entityManagerFactory, entityManager -> {
|
||||||
|
final EntityWithAuditedEmbeddableWithDeclaredData entity = entityManager.find(
|
||||||
|
EntityWithAuditedEmbeddableWithDeclaredData.class,
|
||||||
|
id
|
||||||
|
);
|
||||||
|
|
||||||
|
final AuditReader auditReader = AuditReaderFactory.get( entityManager );
|
||||||
|
|
||||||
|
final List<Number> revisions = auditReader.getRevisions( EntityWithAuditedEmbeddableWithDeclaredData.class, id );
|
||||||
|
assertThat( revisions ).hasSize( 1 );
|
||||||
|
|
||||||
|
final EntityWithAuditedEmbeddableWithDeclaredData entityRevision1 = auditReader.find(
|
||||||
|
EntityWithAuditedEmbeddableWithDeclaredData.class,
|
||||||
|
id,
|
||||||
|
revisions.get( 0 )
|
||||||
|
);
|
||||||
|
assertThat( entityRevision1.getName() ).isEqualTo( entity.getName() );
|
||||||
|
|
||||||
|
// All fields should be audited because the mapped superclass is annotated
|
||||||
|
assertThat( entity.getValue().getCodeart() ).isEqualTo( entityRevision1.getValue().getCodeart() );
|
||||||
|
assertThat( entityRevision1.getValue().getCode() ).isEqualTo( 42 );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
/*
|
||||||
|
* 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.orm.test.envers.integration.components.mappedsuperclass;
|
||||||
|
|
||||||
|
import jakarta.persistence.Embeddable;
|
||||||
|
|
||||||
|
import org.hibernate.envers.Audited;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Chris Cranford
|
||||||
|
*/
|
||||||
|
@Embeddable
|
||||||
|
@Audited
|
||||||
|
public class AuditedEmbeddableWithNoDeclaredData extends AbstractAuditedEmbeddable {
|
||||||
|
|
||||||
|
public AuditedEmbeddableWithNoDeclaredData(int code) {
|
||||||
|
super( code );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Needed for @Embeddable
|
||||||
|
protected AuditedEmbeddableWithNoDeclaredData() {
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,76 @@
|
||||||
|
/*
|
||||||
|
* 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.orm.test.envers.integration.components.mappedsuperclass;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.hibernate.envers.AuditReader;
|
||||||
|
import org.hibernate.envers.AuditReaderFactory;
|
||||||
|
import org.hibernate.orm.test.envers.BaseEnversJPAFunctionalTestCase;
|
||||||
|
import org.hibernate.orm.test.envers.Priority;
|
||||||
|
|
||||||
|
import org.hibernate.testing.orm.junit.JiraKey;
|
||||||
|
import org.hibernate.testing.transaction.TransactionUtil;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Chris Cranford
|
||||||
|
*/
|
||||||
|
@JiraKey("HHH-17189")
|
||||||
|
public class AuditedEmbeddableWithNoDeclaredDataTest extends BaseEnversJPAFunctionalTestCase {
|
||||||
|
|
||||||
|
private long id;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<?>[] getAnnotatedClasses() {
|
||||||
|
return new Class[] {
|
||||||
|
EntityWithAuditedEmbeddableWithNoDeclaredData.class,
|
||||||
|
AbstractAuditedEmbeddable.class,
|
||||||
|
AuditedEmbeddableWithDeclaredData.class
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Priority(10)
|
||||||
|
public void initData() {
|
||||||
|
this.id = TransactionUtil.doInJPA( this::entityManagerFactory, entityManager -> {
|
||||||
|
final EntityWithAuditedEmbeddableWithNoDeclaredData entity = new EntityWithAuditedEmbeddableWithNoDeclaredData();
|
||||||
|
entity.setName( "Entity 1" );
|
||||||
|
entity.setValue( new AuditedEmbeddableWithNoDeclaredData( 42 ) );
|
||||||
|
|
||||||
|
entityManager.persist(entity);
|
||||||
|
return entity.getId();
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEmbeddableThatExtendsAuditedMappedSuperclass() {
|
||||||
|
TransactionUtil.doInJPA( this::entityManagerFactory, entityManager -> {
|
||||||
|
final EntityWithAuditedEmbeddableWithNoDeclaredData entity = entityManager.find(
|
||||||
|
EntityWithAuditedEmbeddableWithNoDeclaredData.class,
|
||||||
|
id
|
||||||
|
);
|
||||||
|
|
||||||
|
final AuditReader auditReader = AuditReaderFactory.get( entityManager );
|
||||||
|
|
||||||
|
final List<Number> revisions = auditReader.getRevisions( EntityWithAuditedEmbeddableWithNoDeclaredData.class, id );
|
||||||
|
assertThat( revisions ).hasSize( 1 );
|
||||||
|
|
||||||
|
final EntityWithAuditedEmbeddableWithNoDeclaredData entityRevision1 = auditReader.find(
|
||||||
|
EntityWithAuditedEmbeddableWithNoDeclaredData.class,
|
||||||
|
id,
|
||||||
|
revisions.get( 0 )
|
||||||
|
);
|
||||||
|
assertThat( entityRevision1.getName() ).isEqualTo( entity.getName() );
|
||||||
|
|
||||||
|
// All fields should be audited because the mapped superclass is annotated
|
||||||
|
assertThat( entityRevision1.getValue().getCode() ).isEqualTo( 42 );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,88 @@
|
||||||
|
/*
|
||||||
|
* 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.orm.test.envers.integration.components.mappedsuperclass;
|
||||||
|
|
||||||
|
import jakarta.persistence.Access;
|
||||||
|
import jakarta.persistence.AccessType;
|
||||||
|
import jakarta.persistence.Column;
|
||||||
|
import jakarta.persistence.Embedded;
|
||||||
|
import jakarta.persistence.Entity;
|
||||||
|
import jakarta.persistence.GeneratedValue;
|
||||||
|
import jakarta.persistence.Id;
|
||||||
|
import jakarta.persistence.Table;
|
||||||
|
|
||||||
|
import org.hibernate.envers.Audited;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Chris Cranford
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
@Table(name="EntEmbWAuditedDeclData")
|
||||||
|
@Access(AccessType.FIELD)
|
||||||
|
@Audited
|
||||||
|
public class EntityWithAuditedEmbeddableWithDeclaredData {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue
|
||||||
|
private long id;
|
||||||
|
|
||||||
|
@Column(name = "NAME", length = 100)
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@Embedded
|
||||||
|
private AuditedEmbeddableWithDeclaredData value;
|
||||||
|
|
||||||
|
public long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AuditedEmbeddableWithDeclaredData getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue(AuditedEmbeddableWithDeclaredData value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result = 1;
|
||||||
|
result = prime * result + (int) ( id ^ ( id >>> 32 ) );
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if ( this == obj ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if ( obj == null ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( getClass() != obj.getClass() ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
EntityWithAuditedEmbeddableWithDeclaredData other = (EntityWithAuditedEmbeddableWithDeclaredData) obj;
|
||||||
|
if ( id != other.id ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,88 @@
|
||||||
|
/*
|
||||||
|
* 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.orm.test.envers.integration.components.mappedsuperclass;
|
||||||
|
|
||||||
|
import jakarta.persistence.Access;
|
||||||
|
import jakarta.persistence.AccessType;
|
||||||
|
import jakarta.persistence.Column;
|
||||||
|
import jakarta.persistence.Embedded;
|
||||||
|
import jakarta.persistence.Entity;
|
||||||
|
import jakarta.persistence.GeneratedValue;
|
||||||
|
import jakarta.persistence.Id;
|
||||||
|
import jakarta.persistence.Table;
|
||||||
|
|
||||||
|
import org.hibernate.envers.Audited;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Chris Cranford
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
@Table(name="EntEmbWAuditedNoDeclData")
|
||||||
|
@Access(AccessType.FIELD)
|
||||||
|
@Audited
|
||||||
|
public class EntityWithAuditedEmbeddableWithNoDeclaredData {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue
|
||||||
|
private long id;
|
||||||
|
|
||||||
|
@Column(name = "NAME", length = 100)
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@Embedded
|
||||||
|
private AuditedEmbeddableWithNoDeclaredData value;
|
||||||
|
|
||||||
|
public long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AuditedEmbeddableWithNoDeclaredData getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue(AuditedEmbeddableWithNoDeclaredData value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result = 1;
|
||||||
|
result = prime * result + (int) ( id ^ ( id >>> 32 ) );
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if ( this == obj ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if ( obj == null ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( getClass() != obj.getClass() ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
EntityWithAuditedEmbeddableWithNoDeclaredData other = (EntityWithAuditedEmbeddableWithNoDeclaredData) obj;
|
||||||
|
if ( id != other.id ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue