HHH-12965 Avoid creating foreign keys between audit and main tables

* Added test case
This commit is contained in:
Chris Cranford 2019-10-01 10:32:23 -04:00 committed by Andrea Boriero
parent b28c7b0761
commit 72b81eebfe
5 changed files with 274 additions and 0 deletions

View File

@ -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.test.integration.manytoone.foreignkey;
import java.time.LocalDate;
import java.util.ArrayList;
import org.hibernate.envers.test.BaseEnversJPAFunctionalTestCase;
import org.junit.Test;
import org.hibernate.testing.TestForIssue;
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
/**
* Tests that no foreign key should be generated from audit schema to main schema.
*
* @author Chris Cranford
*/
@TestForIssue(jiraKey = "HHH-12965")
public class ForeignKeyExclusionTest extends BaseEnversJPAFunctionalTestCase {
private RootLayer rootLayer;
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class<?>[] { RootLayer.class, MiddleLayer.class, LeafLayer.class };
}
@Test
public void testRemovingAuditedEntityWithIdClassAndManyToOneForeignKeyConstraint() {
// Revision 1 - Add Root/Middle/Leaf layers
this.rootLayer = doInJPA( this::entityManagerFactory, entityManager -> {
final RootLayer rootLayer = new RootLayer();
rootLayer.setMiddleLayers( new ArrayList<>() );
MiddleLayer middleLayer = new MiddleLayer();
rootLayer.getMiddleLayers().add( middleLayer );
middleLayer.setRootLayer( rootLayer );
middleLayer.setValidFrom( LocalDate.of( 2019, 3, 19 ) );
middleLayer.setLeafLayers( new ArrayList<>() );
LeafLayer leafLayer = new LeafLayer();
leafLayer.setMiddleLayer( middleLayer );
middleLayer.getLeafLayers().add( leafLayer );
entityManager.persist( rootLayer );
return rootLayer;
} );
// Revision 2 - Delete Root/Middle/Leaf layers
// This causes FK violation
doInJPA( this::entityManagerFactory, entityManager -> {
final RootLayer rootLayer = entityManager.find( RootLayer.class, this.rootLayer.getId() );
entityManager.remove( rootLayer );
} );
}
}

View File

@ -0,0 +1,49 @@
/*
* 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.manytoone.foreignkey;
import javax.persistence.Entity;
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 org.hibernate.envers.Audited;
/**
* @author Chris Cranford
*/
@Entity(name = "LeafLayer")
@Audited
public class LeafLayer {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@ManyToOne(optional = false)
@JoinColumns({
@JoinColumn(name = "middle_layer_valid_from_fk", referencedColumnName = "valid_from"),
@JoinColumn(name = "middle_layer_root_layer_fk", referencedColumnName = "root_layer_fk") })
private MiddleLayer middleLayer;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public MiddleLayer getMiddleLayer() {
return middleLayer;
}
public void setMiddleLayer(MiddleLayer middleLayer) {
this.middleLayer = middleLayer;
}
}

View File

@ -0,0 +1,63 @@
/*
* 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.manytoone.foreignkey;
import java.time.LocalDate;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.IdClass;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import org.hibernate.envers.Audited;
/**
* @author Chris Cranford
*/
@Audited
@Entity
@IdClass(MiddleLayerPK.class)
public class MiddleLayer {
@Id
@Column(name = "valid_from", nullable = false)
private LocalDate validFrom;
@Id
@ManyToOne
@JoinColumn(name = "root_layer_fk")
private RootLayer rootLayer;
@OneToMany(mappedBy = "middleLayer", cascade = CascadeType.ALL, orphanRemoval = true)
private List<LeafLayer> leafLayers;
public LocalDate getValidFrom() {
return validFrom;
}
public void setValidFrom(LocalDate validFrom) {
this.validFrom = validFrom;
}
public RootLayer getRootLayer() {
return rootLayer;
}
public void setRootLayer(RootLayer rootLayer) {
this.rootLayer = rootLayer;
}
public List<LeafLayer> getLeafLayers() {
return leafLayers;
}
public void setLeafLayers(List<LeafLayer> leafLayers) {
this.leafLayers = leafLayers;
}
}

View File

@ -0,0 +1,53 @@
/*
* 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.manytoone.foreignkey;
import java.io.Serializable;
import java.time.LocalDate;
import java.util.Objects;
/**
* @author Chris Cranford
*/
public class MiddleLayerPK implements Serializable {
private Long rootLayer;
private LocalDate validFrom;
public Long getRootLayer() {
return rootLayer;
}
public void setRootLayer(Long rootLayer) {
this.rootLayer = rootLayer;
}
public LocalDate getValidFrom() {
return validFrom;
}
public void setValidFrom(LocalDate validFrom) {
this.validFrom = validFrom;
}
@Override
public boolean equals(Object o) {
if ( this == o ) {
return true;
}
if ( o == null || getClass() != o.getClass() ) {
return false;
}
MiddleLayerPK that = (MiddleLayerPK) o;
return Objects.equals( rootLayer, that.rootLayer ) &&
Objects.equals( validFrom, that.validFrom );
}
@Override
public int hashCode() {
return Objects.hash( rootLayer, validFrom );
}
}

View File

@ -0,0 +1,47 @@
/*
* 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.manytoone.foreignkey;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import org.hibernate.envers.Audited;
/**
* @author Chris Cranford
*/
@Entity(name = "RootLayer")
@Audited
public class RootLayer {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@OneToMany(mappedBy = "rootLayer", cascade = CascadeType.ALL, orphanRemoval = true)
private List<MiddleLayer> middleLayers;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public List<MiddleLayer> getMiddleLayers() {
return middleLayers;
}
public void setMiddleLayers(List<MiddleLayer> middleLayers) {
this.middleLayers = middleLayers;
}
}