Merge remote-tracking branch 'upstream/master' into wip/6.0_merge

This commit is contained in:
Andrea Boriero 2020-09-08 08:19:13 +01:00
commit 8b938610cf
13 changed files with 884 additions and 32 deletions

View File

@ -337,16 +337,12 @@ task copyResourcesToIntelliJOutFolder(type: Task, dependsOn: project.tasks.proce
Afterward, you can run any test from the IDE against that particular DB.
*/
task setDataBase {
inputs.property( "db", db )
doLast {
processTestResources
copyResourcesToIntelliJOutFolder
task setDataBase dependsOn( processTestResources, copyResourcesToIntelliJOutFolder ) {
println( 'Setting current database to ' + db )
}
}
copyResourcesToIntelliJOutFolder.mustRunAfter processTestResources
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Report configs

View File

@ -27,6 +27,8 @@ import org.hibernate.Transaction;
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.DynamicUpdate;
import org.hibernate.testing.DialectChecks;
import org.hibernate.testing.RequiresDialectFeature;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.After;
@ -39,6 +41,7 @@ import org.junit.Test;
* @author Nathan Xu
*/
@TestForIssue( jiraKey = "HHH-14178" )
@RequiresDialectFeature(DialectChecks.SupportsIdentityColumns.class)
public class NewlyInstantiatdCollectionSkipDeleteOrphanTest extends BaseCoreFunctionalTestCase {
private UnversionedParent up;
@ -177,6 +180,8 @@ public class NewlyInstantiatdCollectionSkipDeleteOrphanTest extends BaseCoreFunc
private Integer id;
private Long version;
private String name;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "Id", nullable = false)
@ -188,6 +193,14 @@ public class NewlyInstantiatdCollectionSkipDeleteOrphanTest extends BaseCoreFunc
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Version
@Column(name = "Version", nullable = false)
public Long getVersion() {
@ -265,12 +278,14 @@ public class NewlyInstantiatdCollectionSkipDeleteOrphanTest extends BaseCoreFunc
}
@Entity(name = "UnversionedParent")
@Table(name = "UnversionedParent")
@Table(name = "UnversParent")
@DynamicUpdate
public static class UnversionedParent {
private Integer id;
private Set<VersionedMappingUnversionedParent> versionedMappings;
private String name;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="Id", nullable=false)
@ -291,6 +306,14 @@ public class NewlyInstantiatdCollectionSkipDeleteOrphanTest extends BaseCoreFunc
}
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@OneToMany(mappedBy="parent", cascade={ javax.persistence.CascadeType.DETACH, javax.persistence.CascadeType.MERGE, javax.persistence.CascadeType.REFRESH, javax.persistence.CascadeType.REMOVE }, orphanRemoval=true)
@Cascade({ org.hibernate.annotations.CascadeType.DELETE, org.hibernate.annotations.CascadeType.LOCK, org.hibernate.annotations.CascadeType.REPLICATE })
protected Set<VersionedMappingUnversionedParent> getVersionedMappings() {
@ -346,12 +369,13 @@ public class NewlyInstantiatdCollectionSkipDeleteOrphanTest extends BaseCoreFunc
}
@Entity(name = "VersionedParent")
@Table(name = "VersionedParent")
@Table(name = "VersParent")
@DynamicUpdate
public static class VersionedParent {
private Integer id;
private Long version;
private Set<VersionedMappingVersionedParent> children;
private String name;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@ -373,6 +397,14 @@ public class NewlyInstantiatdCollectionSkipDeleteOrphanTest extends BaseCoreFunc
}
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Version
@Column(name="Version", nullable=false)
public Long getVersion() {
@ -438,12 +470,13 @@ public class NewlyInstantiatdCollectionSkipDeleteOrphanTest extends BaseCoreFunc
}
@Entity(name = "VersionedMappingUnversionedParent")
@Table(name = "VersionedMappingUnversionedParent")
@Table(name = "VersdMapUnversParent")
@DynamicUpdate
public static class VersionedMappingUnversionedParent {
private MappingId id;
private Child child;
private Long version;
private String name;
@EmbeddedId
public MappingId getId() {
@ -464,6 +497,14 @@ public class NewlyInstantiatdCollectionSkipDeleteOrphanTest extends BaseCoreFunc
this.version = version;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
protected UnversionedParent parent;
@ManyToOne(optional=false, fetch=FetchType.LAZY)
@ -551,12 +592,13 @@ public class NewlyInstantiatdCollectionSkipDeleteOrphanTest extends BaseCoreFunc
}
@Entity(name = "VersionedMappingVersionedParent")
@Table(name = "VersionedMappingVersionedParent")
@Table(name = "VersMapVersParent")
@DynamicUpdate
public static class VersionedMappingVersionedParent {
private MappingId id;
private Child child;
private Long version;
private String name;
@EmbeddedId
public MappingId getId() {
@ -577,6 +619,14 @@ public class NewlyInstantiatdCollectionSkipDeleteOrphanTest extends BaseCoreFunc
this.version = version;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
protected VersionedParent parent;
@ManyToOne(optional=false, fetch=FetchType.LAZY)

View File

@ -0,0 +1,254 @@
package org.hibernate.jpa.test.graphs;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.persistence.CollectionTable;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.EntityGraph;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToMany;
import javax.persistence.NamedAttributeNode;
import javax.persistence.NamedEntityGraph;
import javax.persistence.Table;
import org.hibernate.graph.GraphSemantic;
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
import org.hibernate.testing.TestForIssue;
import org.junit.Before;
import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThat;
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
/**
* @author Benjamin M.
* @author Nathan Xu
*/
@TestForIssue( jiraKey = "HHH-14113" )
@SuppressWarnings({ "unchecked", "rawtypes" })
public class EntityGraphAttributeResolutionTest extends BaseEntityManagerFunctionalTestCase {
private User u;
private Group g1, g2;
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class<?>[] { User.class, Group.class };
}
@Before
public void setUp() {
doInJPA( this::entityManagerFactory, em -> {
g1 = new Group();
g1.addPermission( Permission.BAR );
em.persist( g1 );
g2 = new Group();
g2.addPermission( Permission.BAZ );
em.persist( g2 );
u = new User();
em.persist( u );
u.addGroup( g1 );
u.addGroup( g2 );
} );
}
@Test
public void fetchAssocWithNamedFetchGraph() {
doInJPA( this::entityManagerFactory, em -> {
List result = em.createQuery( "SELECT u.groups FROM User u WHERE u.id = ?1" )
.setParameter(1, u.getId() )
.setHint( GraphSemantic.FETCH.getJpaHintName(), em.getEntityGraph( Group.ENTITY_GRAPH ) )
.getResultList();
assertThat( result ).containsExactlyInAnyOrder( g1, g2 );
} );
}
@Test
public void fetchAssocWithNamedFetchGraphAndJoin() {
doInJPA( this::entityManagerFactory, em -> {
List result = em.createQuery( "SELECT g FROM User u JOIN u.groups g WHERE u.id = ?1" )
.setParameter( 1, u.getId() )
.setHint( GraphSemantic.FETCH.getJpaHintName(), em.getEntityGraph( Group.ENTITY_GRAPH ) )
.getResultList();
assertThat( result ).containsExactlyInAnyOrder( g1, g2 );
} );
}
@Test
public void fetchAssocWithAdhocFetchGraph() {
doInJPA( this::entityManagerFactory, em -> {
EntityGraph<Group> eg = em.createEntityGraph( Group.class );
eg.addAttributeNodes( "permissions" );
List result = em.createQuery( "SELECT u.groups FROM User u WHERE u.id = ?1" )
.setParameter(1, u.getId() )
.setHint( GraphSemantic.FETCH.getJpaHintName(), eg )
.getResultList();
assertThat( result ).containsExactlyInAnyOrder( g1, g2 );
} );
}
@Entity(name = "Group")
@NamedEntityGraph(name = Group.ENTITY_GRAPH,
attributeNodes = {
@NamedAttributeNode("permissions")
})
@Table(name = "groups") // Name 'group' not accepted by H2
public static class Group {
public static final String ENTITY_GRAPH = "group-with-permissions";
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Enumerated(EnumType.STRING)
@ElementCollection(targetClass = Permission.class)
@CollectionTable(
name = "GROUPS_PERMISSIONS",
joinColumns = @JoinColumn(name = "gid")
)
private Set<Permission> permissions = EnumSet.noneOf( Permission.class );
public Group() {}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Set<Permission> getPermissions() {
return permissions;
}
public void setPermissions(Set<Permission> permissions) {
this.permissions = permissions;
}
public void addPermission(Permission p) {
this.permissions.add( p );
}
@Override
public boolean equals(Object o) {
if ( this == o ) return true;
if ( !( o instanceof Group ) )
return false;
Group other = (Group) o;
return id != null &&
id.equals( other.getId() );
}
@Override
public int hashCode() {
return 31;
}
@Override
public String toString() {
return "Group{" +
"id=" + id +
'}';
}
}
@Entity(name = "User")
@Table(name = "users")
public static class User {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Enumerated(EnumType.STRING)
@ElementCollection(targetClass = Permission.class)
@CollectionTable(name = "USERS_PERMISSIONS", joinColumns = @JoinColumn(name = "user_id"))
private Set<Permission> permissions = EnumSet.of( Permission.FOO );
@ManyToMany(fetch = FetchType.LAZY)
private Set<Group> groups = new HashSet<>();
public User() {}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Set<Permission> getPermissions() {
return permissions;
}
public void setPermissions(Set<Permission> permissions) {
this.permissions = permissions;
}
public void addPermission(Permission p) {
this.permissions.add( p );
}
public Set<Group> getGroups() {
return groups;
}
public void setGroups(Set<Group> groups) {
this.groups = groups;
}
public void addGroup(Group g) {
this.groups.add( g );
}
@Override
public boolean equals(Object o) {
if ( this == o ) return true;
if ( !( o instanceof User ) )
return false;
User other = (User) o;
return id != null &&
id.equals( other.getId() );
}
@Override
public int hashCode() {
return 31;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
'}';
}
}
public enum Permission {
FOO, BAR, BAZ
}
}

View File

@ -0,0 +1,133 @@
package org.hibernate.query.criteria.internal.hhh13058;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.From;
import javax.persistence.criteria.JoinType;
import javax.persistence.criteria.Root;
import javax.persistence.criteria.Subquery;
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
import org.hibernate.testing.TestForIssue;
import org.junit.Before;
import org.junit.Test;
import static org.hamcrest.CoreMatchers.is;
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
import static org.junit.Assert.assertThat;
/**
* @author Archie Cobbs
* @author Nathan Xu
*/
@TestForIssue( jiraKey = "HHH-13058" )
public class HHH13058Test extends BaseEntityManagerFunctionalTestCase {
private Set<Site> validSites;
private Task taskWithoutPatient;
private Task taskWithPatientWithoutSite;
private Task taskWithPatient1WithValidSite1;
private Task taskWithPatient2WithValidSite1;
private Task taskWithPatient3WithValidSite2;
private Task taskWithPatientWithInvalidSite;
@Override
public Class<?>[] getAnnotatedClasses() {
return new Class<?>[] {
Task.class,
Patient.class,
Site.class
};
}
@Before
public void setUp() {
doInJPA( this::entityManagerFactory, entityManager -> {
final Site validSite1 = new Site();
final Site validSite2 = new Site();
final Site invalidSite = new Site();
entityManager.persist( validSite1 );
entityManager.persist( validSite2 );
entityManager.persist( invalidSite );
validSites = new HashSet<>( Arrays.asList( validSite1, validSite2 ) );
final Patient patientWithoutSite = new Patient();
final Patient patient1WithValidSite1 = new Patient( validSite1 );
final Patient patient2WithValidSite1 = new Patient( validSite1 );
final Patient patient3WithValidSite2 = new Patient( validSite2 );
final Patient patientWithInvalidSite = new Patient( invalidSite );
entityManager.persist( patientWithoutSite );
entityManager.persist( patient1WithValidSite1 );
entityManager.persist( patient2WithValidSite1 );
entityManager.persist( patient3WithValidSite2 );
entityManager.persist( patientWithInvalidSite );
taskWithoutPatient = new Task();
taskWithoutPatient.description = "taskWithoutPatient";
taskWithPatientWithoutSite = new Task( patientWithoutSite );
taskWithPatientWithoutSite.description = "taskWithPatientWithoutSite";
taskWithPatient1WithValidSite1 = new Task( patient1WithValidSite1 );
taskWithPatient1WithValidSite1.description = "taskWithPatient1WithValidSite1";
taskWithPatient2WithValidSite1 = new Task( patient2WithValidSite1 );
taskWithPatient2WithValidSite1.description = "taskWithPatient2WithValidSite1";
taskWithPatient3WithValidSite2 = new Task( patient3WithValidSite2 );
taskWithPatient3WithValidSite2.description = "taskWithPatient3WithValidSite2";
taskWithPatientWithInvalidSite = new Task( patientWithInvalidSite );
taskWithPatientWithInvalidSite.description = "taskWithPatientWithInvalidSite";
entityManager.persist( taskWithoutPatient );
entityManager.persist( taskWithPatientWithoutSite );
entityManager.persist( taskWithPatient1WithValidSite1 );
entityManager.persist( taskWithPatient2WithValidSite1 );
entityManager.persist( taskWithPatient3WithValidSite2 );
entityManager.persist( taskWithPatientWithInvalidSite );
} );
}
@Test
public void testCorrelateSubQueryLeftJoin() {
doInJPA( this::entityManagerFactory, entityManager -> {
final CriteriaBuilder builder = entityManager.getCriteriaBuilder();
final CriteriaQuery<Task> outerQuery = builder.createQuery( Task.class );
final Root<Task> outerTask = outerQuery.from( Task.class );
final Subquery<Task> subquery = outerQuery.subquery( Task.class );
final Root<Task> subtask = subquery.correlate( outerTask );
final From<Task, Patient> patient = subtask.join( Task_.patient, JoinType.LEFT );
final From<Patient, Site> site = patient.join( Patient_.site, JoinType.LEFT );
outerQuery.where(
builder.exists(
subquery.select( subtask )
.where(
builder.or(
patient.isNull(),
site.in( validSites )
)
)
)
);
final List<Task> tasks = entityManager.createQuery( outerQuery ).getResultList();
assertThat( new HashSet<>( tasks ), is( new HashSet<>( Arrays.asList(
taskWithoutPatient,
taskWithPatient1WithValidSite1,
taskWithPatient2WithValidSite1,
taskWithPatient3WithValidSite2
) ) ) );
} );
}
}

View File

@ -0,0 +1,32 @@
package org.hibernate.query.criteria.internal.hhh13058;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
/**
* @author Archie Cobbs
* @author Nathan Xu
*/
@Entity(name = "Patient")
@Table(name = "Patient")
public class Patient {
@Id
@GeneratedValue
Long id;
@ManyToOne(fetch = FetchType.LAZY)
Site site;
public Patient() {
}
public Patient(Site site) {
this.site = site;
}
}

View File

@ -0,0 +1,20 @@
package org.hibernate.query.criteria.internal.hhh13058;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
/**
* @author Archie Cobbs
* @author Nathan Xu
*/
@Entity(name = "Site")
@Table(name = "Site")
public class Site {
@Id
@GeneratedValue
Long id;
}

View File

@ -0,0 +1,56 @@
package org.hibernate.query.criteria.internal.hhh13058;
import java.util.Objects;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
/**
* @author Archie Cobbs
* @author Nathan Xu
*/
@Entity(name = "Task")
@Table(name = "Task")
public class Task {
@Id
@GeneratedValue
Long id;
@ManyToOne(fetch = FetchType.LAZY)
Patient patient;
String description;
public Task() {
}
public Task(Patient patient) {
this.patient = patient;
}
@Override
public boolean equals(Object o) {
if ( this == o ) {
return true;
}
if ( o == null || getClass() != o.getClass() ) {
return false;
}
Task task = (Task) o;
return id.equals( task.id );
}
@Override
public int hashCode() {
return Objects.hash( id );
}
@Override
public String toString() {
return String.format( "Task(id: %d; description: %s)", id, description == null ? "null" : description );
}
}

View File

@ -0,0 +1,30 @@
package org.hibernate.query.criteria.internal.hhh14197;
import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
/**
* @author Archie Cobbs
*/
@MappedSuperclass
public abstract class AbstractPersistent {
private long id;
protected AbstractPersistent() {
}
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(nullable = false)
public long getId() {
return this.id;
}
public void setId(long id) {
this.id = id;
}
}

View File

@ -0,0 +1,32 @@
package org.hibernate.query.criteria.internal.hhh14197;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Entity;
import javax.persistence.OneToMany;
/**
* @author Archie Cobbs
*/
@Entity
public class Department extends AbstractPersistent {
private String name;
private Set<Employee> employees = new HashSet<>();
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
@OneToMany(mappedBy = "department")
public Set<Employee> getEmployees() {
return this.employees;
}
public void setEmployees(Set<Employee> employees) {
this.employees = employees;
}
}

View File

@ -0,0 +1,118 @@
package org.hibernate.query.criteria.internal.hhh14197;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.ManyToOne;
import javax.persistence.MapKeyColumn;
import javax.persistence.OneToMany;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
/**
* @author Archie Cobbs
*/
@Entity
public class Employee extends AbstractPersistent {
private String name;
private float salary;
private Seniority seniority;
private Date startDate;
private Department department;
private Employee manager;
private Set<Employee> directReports = new HashSet<>();
private Map<String, String> annotations = new HashMap<>();
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public float getSalary() {
return this.salary;
}
public void setSalary(float salary) {
this.salary = salary;
}
@Enumerated(EnumType.STRING)
public Seniority getSeniority() {
return this.seniority;
}
public void setSeniority(Seniority seniority) {
this.seniority = seniority;
}
@Temporal(TemporalType.TIMESTAMP)
public Date getStartDate() {
return this.startDate;
}
public void setStartDate(Date startDate) {
this.startDate = startDate;
}
@ManyToOne
public Employee getManager() {
return this.manager;
}
public void setManager(Employee manager) {
this.manager = manager;
}
@ManyToOne
public Department getDepartment() {
return this.department;
}
public void setDepartment(Department department) {
this.department = department;
}
@OneToMany(mappedBy = "manager")
public Set<Employee> getDirectReports() {
return this.directReports;
}
public void setDirectReports(Set<Employee> directReports) {
this.directReports = directReports;
}
@ElementCollection
@MapKeyColumn(name = "name", length = 180)
@Column(name = "value", nullable = false)
public Map<String, String> getAnnotations() {
return this.annotations;
}
public void setAnnotations(Map<String, String> annotations) {
this.annotations = annotations;
}
@Override
public String toString() {
return this.getClass().getSimpleName()
+ "[name=" + (this.name != null ? "\"" + this.name + "\"" : null)
+ ",salary=" + this.salary
+ ",startDate=" + this.startDate
+ ",department=" + this.department
+ ",manager=" + this.manager
+ ",directReports=" + this.directReports
+ ",annotations=" + this.annotations
+ "]";
}
// Seniority
public enum Seniority {
JUNIOR,
SENIOR;
}
}

View File

@ -0,0 +1,60 @@
package org.hibernate.query.criteria.internal.hhh14197;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.MapJoin;
import javax.persistence.criteria.Root;
import javax.persistence.criteria.SetJoin;
import javax.persistence.criteria.Subquery;
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
import org.hibernate.testing.FailureExpected;
import org.hibernate.testing.TestForIssue;
import org.junit.Test;
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
/**
* @author Archie Cobbs
* @author Nathan Xu
*/
@TestForIssue( jiraKey = "HHH-14197" )
public class HHH14197Test extends BaseEntityManagerFunctionalTestCase {
@Override
public Class<?>[] getAnnotatedClasses() {
return new Class<?>[] {
Department.class,
Employee.class
};
}
@Test
public void testValidSQLGenerated() {
// without fixing HHH-14197, invalid SQL would be generated without root
// "... where exists (select employee0_.id as id1_1_ from where ...) ... "
doInJPA( this::entityManagerFactory, entityManager -> {
final CriteriaBuilder cb = entityManager.getCriteriaBuilder();
final CriteriaQuery<Employee> query = cb.createQuery( Employee.class );
final Root<Employee> employee = query.from( Employee.class );
final Subquery<Employee> subquery1 = query.subquery( Employee.class );
final Root<Employee> employee2 = subquery1.correlate( employee );
final SetJoin<Employee, Employee> directReport = employee2.join( Employee_.directReports );
final Subquery<Employee> subquery2 = subquery1.subquery( Employee.class );
final SetJoin<Employee, Employee> directReport2 = subquery2.correlate( directReport );
directReport2.join( Employee_.annotations );
subquery2.select( directReport2 );
subquery1.select( employee2 ).where( cb.exists( subquery2 ) );
query.select( employee ).where( cb.exists( subquery1 ) );
entityManager.createQuery( query ).getResultList();
} );
}
}

View File

@ -0,0 +1,70 @@
package org.hibernate.test.hql;
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
import org.hibernate.testing.TestForIssue;
import org.junit.Test;
import javax.persistence.*;
import java.util.HashMap;
import java.util.Map;
import static javax.persistence.CascadeType.ALL;
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
/**
* @author Moritz Becker
*/
@TestForIssue(jiraKey = "HHH-13201")
public class FetchNonRootRelativeElementCollectionAndAssociationTest extends BaseEntityManagerFunctionalTestCase {
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class<?>[] { ProductNaturalId.class, Product.class, ProductDetail.class };
}
@Test
public void testJoinedSubclassUpdateWithCorrelation() {
doInJPA( this::entityManagerFactory, entityManager -> {
// DO NOT CHANGE this query: it used to trigger an error caused
// by the origin FromElement for the association fetch being resolved to the wrong FromElement due to the
// presence of an element collection join.
String u = "select prod from ProductNaturalId nat inner join nat.product prod " +
"left join fetch prod.productDetail " +
"left join fetch prod.normalizedPricesByUnit";
Query query = entityManager.createQuery( u, Product.class );
query.getResultList();
} );
}
@Entity(name = "ProductNaturalId")
public class ProductNaturalId {
@Id
private String naturalId;
@OneToOne(optional = false)
private Product product;
}
@Entity(name = "Product")
public class Product {
@Id
private Long id;
@OneToOne(mappedBy = "product", cascade = ALL, fetch = FetchType.LAZY)
private ProductDetail productDetail;
@OneToOne(mappedBy = "product", cascade = ALL, fetch = FetchType.LAZY)
private ProductNaturalId naturalId;
@ElementCollection(fetch = FetchType.LAZY)
private Map<String, String> normalizedPricesByUnit = new HashMap<>();
}
@Entity(name = "ProductDetail")
public class ProductDetail {
@Id
private Long id;
@OneToOne(optional = false)
@JoinColumn(name = "id")
@MapsId
private Product product;
}
}

View File

@ -108,7 +108,7 @@ public class JpaDescriptorParser {
private Persistence getPersistence() {
Persistence persistence = null;
String persistenceXmlLocation = context.getPersistenceXmlLocation();
InputStream stream = xmlParserHelper.getInputStreamForResource( persistenceXmlLocation );
final InputStream stream = xmlParserHelper.getInputStreamForResource( persistenceXmlLocation );
if ( stream == null ) {
return null;
}
@ -122,37 +122,37 @@ public class JpaDescriptorParser {
Diagnostic.Kind.WARNING, "Unable to parse persistence.xml: " + e.getMessage()
);
}
finally {
try {
stream.close();
}
catch (IOException e) {
// eat it
}
}
return persistence;
}
private void loadEntityMappings(Collection<String> mappingFileNames) {
for ( String mappingFile : mappingFileNames ) {
InputStream stream = xmlParserHelper.getInputStreamForResource( mappingFile );
final InputStream stream = xmlParserHelper.getInputStreamForResource( mappingFile );
if ( stream == null ) {
continue;
}
EntityMappings mapping = null;
try {
Schema schema = xmlParserHelper.getSchema( ORM_SCHEMA );
mapping = xmlParserHelper.getJaxbRoot( stream, EntityMappings.class, schema );
final Schema schema = xmlParserHelper.getSchema( ORM_SCHEMA );
final EntityMappings mapping = xmlParserHelper.getJaxbRoot( stream, EntityMappings.class, schema );
if ( mapping != null ) {
entityMappings.add( mapping );
}
}
catch (XmlParsingException e) {
context.logMessage(
Diagnostic.Kind.WARNING, "Unable to parse " + mappingFile + ": " + e.getMessage()
);
}
if ( mapping != null ) {
entityMappings.add( mapping );
}
finally {
try {
stream.close();
}
@ -161,6 +161,7 @@ public class JpaDescriptorParser {
}
}
}
}
private boolean mappingFilesUnchanged(Collection<String> mappingFileNames) {
boolean mappingFilesUnchanged = false;