HHH-18194 - Remove @Proxy
This commit is contained in:
parent
53bca2467d
commit
4309cffb4d
|
@ -453,50 +453,6 @@ when executing an HQL or JPQL which selects from the `AccountSummary` entity,
|
||||||
Hibernate will trigger a Persistence Context flush if there are pending `Account`, `Client` or `AccountTransaction` entity state transitions.
|
Hibernate will trigger a Persistence Context flush if there are pending `Account`, `Client` or `AccountTransaction` entity state transitions.
|
||||||
====
|
====
|
||||||
|
|
||||||
[[entity-proxy]]
|
|
||||||
==== Define a custom entity proxy
|
|
||||||
|
|
||||||
By default, when it needs to use a proxy instead of the actual POJO, Hibernate is going to use a Bytecode manipulation library like
|
|
||||||
https://bytebuddy.net/[Byte Buddy].
|
|
||||||
|
|
||||||
However, if the entity class is final, a proxy will not be created; you will get a POJO even when you only need a proxy reference.
|
|
||||||
In this case, you could proxy an interface that this particular entity implements, as illustrated by the following example.
|
|
||||||
|
|
||||||
NOTE: Supplying a custom proxy class has been allowed historically, but has never seen much use. Also, setting the `lazy` property to `false`, effectively disallowing proxy creation for an entity type, can easily lead to performance degradation due to the N + 1 query issue. As of 6.2 `@Proxy` has been formally deprecated.
|
|
||||||
|
|
||||||
See the <<concrete-proxy,@ConcreteProxy>> paragraph if you wish to resolve the concrete type of proxies for the purpose of `instanceof` checks and typecasts.
|
|
||||||
|
|
||||||
[[entity-proxy-interface-mapping]]
|
|
||||||
.Final entity class implementing the `Identifiable` interface
|
|
||||||
====
|
|
||||||
[source,java]
|
|
||||||
----
|
|
||||||
include::{example-dir-proxy}/ProxyInterfaceTest.java[tag=entity-proxy-interface-mapping,indent=0]
|
|
||||||
----
|
|
||||||
====
|
|
||||||
|
|
||||||
The https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibernate/annotations/Proxy.html[`@Proxy`]
|
|
||||||
annotation is used to specify a custom proxy implementation for the current annotated entity.
|
|
||||||
|
|
||||||
When loading the `Book` entity proxy, Hibernate is going to proxy the `Identifiable` interface instead as illustrated by the following example:
|
|
||||||
|
|
||||||
[[entity-proxy-persist-mapping]]
|
|
||||||
.Proxying the final entity class implementing the `Identifiable` interface
|
|
||||||
====
|
|
||||||
[source,java]
|
|
||||||
----
|
|
||||||
include::{example-dir-proxy}/ProxyInterfaceTest.java[tag=entity-proxy-persist-mapping,indent=0]
|
|
||||||
----
|
|
||||||
|
|
||||||
[source,sql]
|
|
||||||
----
|
|
||||||
include::{extrasdir}/entity/entity-proxy-persist-mapping.sql[]
|
|
||||||
----
|
|
||||||
====
|
|
||||||
|
|
||||||
As you can see in the associated SQL snippet, Hibernate issues no SQL SELECT query since the proxy can be
|
|
||||||
constructed without needing to fetch the actual entity POJO.
|
|
||||||
|
|
||||||
[[concrete-proxy]]
|
[[concrete-proxy]]
|
||||||
==== Create proxies that resolve their inheritance subtype
|
==== Create proxies that resolve their inheritance subtype
|
||||||
|
|
||||||
|
|
|
@ -1,35 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.annotations;
|
|
||||||
|
|
||||||
import java.lang.annotation.Retention;
|
|
||||||
import java.lang.annotation.Target;
|
|
||||||
|
|
||||||
import static java.lang.annotation.ElementType.TYPE;
|
|
||||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Allows the proxy class of an entity class to be explicitly specified.
|
|
||||||
*
|
|
||||||
* @deprecated This annotation is almost never useful.
|
|
||||||
*
|
|
||||||
* @author Emmanuel Bernard
|
|
||||||
*/
|
|
||||||
@Deprecated(since = "6.2")
|
|
||||||
@Target(TYPE)
|
|
||||||
@Retention(RUNTIME)
|
|
||||||
public @interface Proxy {
|
|
||||||
/**
|
|
||||||
* Whether this class may be proxied. Default to true.
|
|
||||||
*/
|
|
||||||
boolean lazy() default true;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Proxy class or interface used. Default is to the annotated entity class itself.
|
|
||||||
*/
|
|
||||||
Class<?> proxyClass() default void.class;
|
|
||||||
}
|
|
|
@ -37,7 +37,6 @@ import org.hibernate.annotations.NaturalIdCache;
|
||||||
import org.hibernate.annotations.OnDelete;
|
import org.hibernate.annotations.OnDelete;
|
||||||
import org.hibernate.annotations.OptimisticLockType;
|
import org.hibernate.annotations.OptimisticLockType;
|
||||||
import org.hibernate.annotations.OptimisticLocking;
|
import org.hibernate.annotations.OptimisticLocking;
|
||||||
import org.hibernate.annotations.Proxy;
|
|
||||||
import org.hibernate.annotations.QueryCacheLayout;
|
import org.hibernate.annotations.QueryCacheLayout;
|
||||||
import org.hibernate.annotations.RowId;
|
import org.hibernate.annotations.RowId;
|
||||||
import org.hibernate.annotations.SQLDelete;
|
import org.hibernate.annotations.SQLDelete;
|
||||||
|
@ -1590,27 +1589,9 @@ public class EntityBinder {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void bindProxy() {
|
public void bindProxy() {
|
||||||
final Proxy proxy = annotatedClass.getAnnotationUsage( Proxy.class, getSourceModelContext() );
|
//needed to allow association lazy loading.
|
||||||
if ( proxy != null ) {
|
lazy = true;
|
||||||
lazy = proxy.lazy();
|
proxyClass = annotatedClass;
|
||||||
proxyClass = lazy ? resolveProxyClass( proxy, annotatedClass, getSourceModelContext() ) : null;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
//needed to allow association lazy loading.
|
|
||||||
lazy = true;
|
|
||||||
proxyClass = annotatedClass;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ClassDetails resolveProxyClass(
|
|
||||||
Proxy proxy,
|
|
||||||
ClassDetails annotatedClass,
|
|
||||||
SourceModelBuildingContext sourceModelContext) {
|
|
||||||
final Class<?> explicitProxyClass = proxy.proxyClass();
|
|
||||||
if ( explicitProxyClass == void.class ) {
|
|
||||||
return annotatedClass;
|
|
||||||
}
|
|
||||||
return sourceModelContext.getClassDetailsRegistry().resolveClassDetails( explicitProxyClass.getName() );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void bindConcreteProxy() {
|
public void bindConcreteProxy() {
|
||||||
|
|
|
@ -488,10 +488,6 @@ public interface HibernateAnnotations {
|
||||||
PartitionKey.class,
|
PartitionKey.class,
|
||||||
PartitionKeyAnnotation.class
|
PartitionKeyAnnotation.class
|
||||||
);
|
);
|
||||||
OrmAnnotationDescriptor<Proxy,ProxyAnnotation> PROXY = new OrmAnnotationDescriptor<>(
|
|
||||||
Proxy.class,
|
|
||||||
ProxyAnnotation.class
|
|
||||||
);
|
|
||||||
OrmAnnotationDescriptor<PropertyRef,PropertyRefAnnotation> PROPERTY_REF = new OrmAnnotationDescriptor<>(
|
OrmAnnotationDescriptor<PropertyRef,PropertyRefAnnotation> PROPERTY_REF = new OrmAnnotationDescriptor<>(
|
||||||
PropertyRef.class,
|
PropertyRef.class,
|
||||||
PropertyRefAnnotation.class
|
PropertyRefAnnotation.class
|
||||||
|
|
|
@ -1,74 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.boot.models.annotations.internal;
|
|
||||||
|
|
||||||
import java.lang.annotation.Annotation;
|
|
||||||
|
|
||||||
import org.hibernate.annotations.Proxy;
|
|
||||||
import org.hibernate.boot.models.HibernateAnnotations;
|
|
||||||
import org.hibernate.models.spi.SourceModelBuildingContext;
|
|
||||||
|
|
||||||
import org.jboss.jandex.AnnotationInstance;
|
|
||||||
|
|
||||||
import static org.hibernate.boot.models.internal.OrmAnnotationHelper.extractJandexValue;
|
|
||||||
|
|
||||||
@SuppressWarnings({ "ClassExplicitlyAnnotation", "unused" })
|
|
||||||
@jakarta.annotation.Generated("org.hibernate.orm.build.annotations.ClassGeneratorProcessor")
|
|
||||||
public class ProxyAnnotation implements Proxy {
|
|
||||||
private boolean lazy;
|
|
||||||
private java.lang.Class<?> proxyClass;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Used in creating dynamic annotation instances (e.g. from XML)
|
|
||||||
*/
|
|
||||||
public ProxyAnnotation(SourceModelBuildingContext modelContext) {
|
|
||||||
this.lazy = true;
|
|
||||||
this.proxyClass = void.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Used in creating annotation instances from JDK variant
|
|
||||||
*/
|
|
||||||
public ProxyAnnotation(Proxy annotation, SourceModelBuildingContext modelContext) {
|
|
||||||
this.lazy = annotation.lazy();
|
|
||||||
this.proxyClass = annotation.proxyClass();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Used in creating annotation instances from Jandex variant
|
|
||||||
*/
|
|
||||||
public ProxyAnnotation(AnnotationInstance annotation, SourceModelBuildingContext modelContext) {
|
|
||||||
this.lazy = extractJandexValue( annotation, HibernateAnnotations.PROXY, "lazy", modelContext );
|
|
||||||
this.proxyClass = extractJandexValue( annotation, HibernateAnnotations.PROXY, "proxyClass", modelContext );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<? extends Annotation> annotationType() {
|
|
||||||
return Proxy.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean lazy() {
|
|
||||||
return lazy;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void lazy(boolean value) {
|
|
||||||
this.lazy = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public java.lang.Class<?> proxyClass() {
|
|
||||||
return proxyClass;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void proxyClass(java.lang.Class<?> value) {
|
|
||||||
this.proxyClass = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
|
@ -16,7 +16,6 @@ import org.hibernate.annotations.BatchSize;
|
||||||
import org.hibernate.annotations.DynamicInsert;
|
import org.hibernate.annotations.DynamicInsert;
|
||||||
import org.hibernate.annotations.DynamicUpdate;
|
import org.hibernate.annotations.DynamicUpdate;
|
||||||
import org.hibernate.annotations.Immutable;
|
import org.hibernate.annotations.Immutable;
|
||||||
import org.hibernate.annotations.Proxy;
|
|
||||||
import org.hibernate.annotations.ResultCheckStyle;
|
import org.hibernate.annotations.ResultCheckStyle;
|
||||||
import org.hibernate.annotations.SQLDelete;
|
import org.hibernate.annotations.SQLDelete;
|
||||||
import org.hibernate.annotations.SQLInsert;
|
import org.hibernate.annotations.SQLInsert;
|
||||||
|
@ -40,7 +39,6 @@ import jakarta.persistence.Cacheable;
|
||||||
import jakarta.persistence.DiscriminatorValue;
|
import jakarta.persistence.DiscriminatorValue;
|
||||||
import jakarta.persistence.Entity;
|
import jakarta.persistence.Entity;
|
||||||
|
|
||||||
import static org.hibernate.boot.models.categorize.internal.CategorizationHelper.toClassDetails;
|
|
||||||
import static org.hibernate.internal.util.StringHelper.EMPTY_STRINGS;
|
import static org.hibernate.internal.util.StringHelper.EMPTY_STRINGS;
|
||||||
import static org.hibernate.internal.util.StringHelper.isNotEmpty;
|
import static org.hibernate.internal.util.StringHelper.isNotEmpty;
|
||||||
import static org.hibernate.internal.util.StringHelper.unqualify;
|
import static org.hibernate.internal.util.StringHelper.unqualify;
|
||||||
|
@ -106,29 +104,9 @@ public class EntityTypeMetadataImpl
|
||||||
this.customUpdateMap = extractCustomSql( classDetails, SQLUpdate.class );
|
this.customUpdateMap = extractCustomSql( classDetails, SQLUpdate.class );
|
||||||
this.customDeleteMap = extractCustomSql( classDetails, SQLDelete.class );
|
this.customDeleteMap = extractCustomSql( classDetails, SQLDelete.class );
|
||||||
|
|
||||||
//noinspection deprecation
|
// defaults are that it is lazy and that the class itself is the proxy class
|
||||||
final Proxy proxyAnnotation = classDetails.getDirectAnnotationUsage( Proxy.class );
|
this.isLazy = true;
|
||||||
if ( proxyAnnotation != null ) {
|
this.proxy = getEntityName();
|
||||||
this.isLazy = proxyAnnotation.lazy();
|
|
||||||
|
|
||||||
if ( this.isLazy ) {
|
|
||||||
final ClassDetails proxyClassDetails = toClassDetails( proxyAnnotation.proxyClass(), modelContext.getClassDetailsRegistry() );
|
|
||||||
if ( proxyClassDetails != null ) {
|
|
||||||
this.proxy = proxyClassDetails.getName();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.proxy = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.proxy = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// defaults are that it is lazy and that the class itself is the proxy class
|
|
||||||
this.isLazy = true;
|
|
||||||
this.proxy = getEntityName();
|
|
||||||
}
|
|
||||||
|
|
||||||
final DiscriminatorValue discriminatorValueAnn = classDetails.getDirectAnnotationUsage( DiscriminatorValue.class );
|
final DiscriminatorValue discriminatorValueAnn = classDetails.getDirectAnnotationUsage( DiscriminatorValue.class );
|
||||||
if ( discriminatorValueAnn != null ) {
|
if ( discriminatorValueAnn != null ) {
|
||||||
|
@ -175,29 +153,9 @@ public class EntityTypeMetadataImpl
|
||||||
this.customUpdateMap = extractCustomSql( classDetails, SQLUpdate.class );
|
this.customUpdateMap = extractCustomSql( classDetails, SQLUpdate.class );
|
||||||
this.customDeleteMap = extractCustomSql( classDetails, SQLDelete.class );
|
this.customDeleteMap = extractCustomSql( classDetails, SQLDelete.class );
|
||||||
|
|
||||||
//noinspection deprecation
|
// defaults are that it is lazy and that the class itself is the proxy class
|
||||||
final Proxy proxyAnnotation = classDetails.getDirectAnnotationUsage( Proxy.class );
|
this.isLazy = true;
|
||||||
if ( proxyAnnotation != null ) {
|
this.proxy = getEntityName();
|
||||||
this.isLazy = proxyAnnotation.lazy();
|
|
||||||
|
|
||||||
if ( this.isLazy ) {
|
|
||||||
final ClassDetails proxyClassDetails = toClassDetails( proxyAnnotation.proxyClass(), modelContext.getClassDetailsRegistry() );
|
|
||||||
if ( proxyClassDetails != null ) {
|
|
||||||
this.proxy = proxyClassDetails.getName();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.proxy = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.proxy = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// defaults are that it is lazy and that the class itself is the proxy class
|
|
||||||
this.isLazy = true;
|
|
||||||
this.proxy = getEntityName();
|
|
||||||
}
|
|
||||||
|
|
||||||
final DiscriminatorValue discriminatorValueAnn = classDetails.getDirectAnnotationUsage( DiscriminatorValue.class );
|
final DiscriminatorValue discriminatorValueAnn = classDetails.getDirectAnnotationUsage( DiscriminatorValue.class );
|
||||||
if ( discriminatorValueAnn != null ) {
|
if ( discriminatorValueAnn != null ) {
|
||||||
|
|
|
@ -228,27 +228,24 @@ public class BasicHibernateAnnotationsTest extends BaseCoreFunctionalTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testNonLazy() throws Exception {
|
public void testLoading() throws Exception {
|
||||||
Session s;
|
final Forest created = fromTransaction( (session) -> {
|
||||||
Transaction tx;
|
Forest f = new Forest();
|
||||||
s = openSession();
|
session.persist( f );
|
||||||
tx = s.beginTransaction();
|
return f;
|
||||||
Forest f = new Forest();
|
} );
|
||||||
Tree t = new Tree();
|
|
||||||
t.setName( "Basic one" );
|
|
||||||
s.persist( f );
|
|
||||||
s.persist( t );
|
|
||||||
tx.commit();
|
|
||||||
s.close();
|
|
||||||
|
|
||||||
s = openSession();
|
// getReference
|
||||||
tx = s.beginTransaction();
|
inTransaction( (session) -> {
|
||||||
f = (Forest) s.load( Forest.class, f.getId() );
|
final Forest reference = session.getReference( Forest.class, created.getId() );
|
||||||
t = (Tree) s.load( Tree.class, t.getId() );
|
assertFalse( Hibernate.isInitialized( reference ) );
|
||||||
assertFalse( "Default should be lazy", Hibernate.isInitialized( f ) );
|
} );
|
||||||
assertTrue( "Tree is not lazy", Hibernate.isInitialized( t ) );
|
|
||||||
tx.commit();
|
// find
|
||||||
s.close();
|
inTransaction( (session) -> {
|
||||||
|
final Forest reference = session.find( Forest.class, created.getId() );
|
||||||
|
assertTrue( Hibernate.isInitialized( reference ) );
|
||||||
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -7,19 +7,15 @@
|
||||||
|
|
||||||
//$Id$
|
//$Id$
|
||||||
package org.hibernate.orm.test.annotations.entity;
|
package org.hibernate.orm.test.annotations.entity;
|
||||||
|
|
||||||
import jakarta.persistence.Entity;
|
import jakarta.persistence.Entity;
|
||||||
import jakarta.persistence.GeneratedValue;
|
import jakarta.persistence.GeneratedValue;
|
||||||
import jakarta.persistence.Id;
|
import jakarta.persistence.Id;
|
||||||
|
|
||||||
import org.hibernate.annotations.Proxy;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Non lazy entity
|
|
||||||
*
|
|
||||||
* @author Emmanuel Bernard
|
* @author Emmanuel Bernard
|
||||||
*/
|
*/
|
||||||
@Entity
|
@Entity
|
||||||
@Proxy(lazy = false)
|
|
||||||
public class Tree {
|
public class Tree {
|
||||||
private Integer id;
|
private Integer id;
|
||||||
private String name;
|
private String name;
|
||||||
|
|
|
@ -7,12 +7,12 @@
|
||||||
|
|
||||||
//$
|
//$
|
||||||
package org.hibernate.orm.test.annotations.idmanytoone;
|
package org.hibernate.orm.test.annotations.idmanytoone;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import jakarta.persistence.Basic;
|
|
||||||
import jakarta.persistence.CascadeType;
|
import jakarta.persistence.CascadeType;
|
||||||
import jakarta.persistence.Column;
|
import jakarta.persistence.Column;
|
||||||
import jakarta.persistence.Entity;
|
import jakarta.persistence.Entity;
|
||||||
import jakarta.persistence.FetchType;
|
|
||||||
import jakarta.persistence.Id;
|
import jakarta.persistence.Id;
|
||||||
import jakarta.persistence.IdClass;
|
import jakarta.persistence.IdClass;
|
||||||
import jakarta.persistence.JoinColumn;
|
import jakarta.persistence.JoinColumn;
|
||||||
|
@ -21,7 +21,6 @@ import jakarta.persistence.Table;
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name="BasketItems")
|
@Table(name="BasketItems")
|
||||||
@org.hibernate.annotations.Proxy(lazy=false)
|
|
||||||
@IdClass(BasketItemsPK.class)
|
@IdClass(BasketItemsPK.class)
|
||||||
public class BasketItems implements Serializable {
|
public class BasketItems implements Serializable {
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,9 @@
|
||||||
|
|
||||||
//$
|
//$
|
||||||
package org.hibernate.orm.test.annotations.idmanytoone;
|
package org.hibernate.orm.test.annotations.idmanytoone;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
import jakarta.persistence.CascadeType;
|
import jakarta.persistence.CascadeType;
|
||||||
import jakarta.persistence.Column;
|
import jakarta.persistence.Column;
|
||||||
import jakarta.persistence.Entity;
|
import jakarta.persistence.Entity;
|
||||||
|
@ -17,7 +19,6 @@ import jakarta.persistence.Table;
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name="Customers")
|
@Table(name="Customers")
|
||||||
@org.hibernate.annotations.Proxy(lazy=false)
|
|
||||||
public class Customers implements Serializable {
|
public class Customers implements Serializable {
|
||||||
|
|
||||||
private static final long serialVersionUID = -885167444315163039L;
|
private static final long serialVersionUID = -885167444315163039L;
|
||||||
|
|
|
@ -7,12 +7,12 @@
|
||||||
|
|
||||||
//$
|
//$
|
||||||
package org.hibernate.orm.test.annotations.idmanytoone;
|
package org.hibernate.orm.test.annotations.idmanytoone;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import jakarta.persistence.Basic;
|
|
||||||
import jakarta.persistence.CascadeType;
|
import jakarta.persistence.CascadeType;
|
||||||
import jakarta.persistence.Column;
|
import jakarta.persistence.Column;
|
||||||
import jakarta.persistence.Entity;
|
import jakarta.persistence.Entity;
|
||||||
import jakarta.persistence.FetchType;
|
|
||||||
import jakarta.persistence.Id;
|
import jakarta.persistence.Id;
|
||||||
import jakarta.persistence.IdClass;
|
import jakarta.persistence.IdClass;
|
||||||
import jakarta.persistence.JoinColumn;
|
import jakarta.persistence.JoinColumn;
|
||||||
|
@ -22,7 +22,6 @@ import jakarta.persistence.Table;
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name="ShoppingBasket")
|
@Table(name="ShoppingBasket")
|
||||||
@org.hibernate.annotations.Proxy(lazy=false)
|
|
||||||
@IdClass(ShoppingBasketsPK.class)
|
@IdClass(ShoppingBasketsPK.class)
|
||||||
public class ShoppingBaskets implements Serializable {
|
public class ShoppingBaskets implements Serializable {
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,6 @@ import jakarta.persistence.Table;
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Inheritance( strategy = InheritanceType.JOINED )
|
@Inheritance( strategy = InheritanceType.JOINED )
|
||||||
@org.hibernate.annotations.Proxy( proxyClass = A.class )
|
|
||||||
@Table( name = "ENTITYA" )
|
@Table( name = "ENTITYA" )
|
||||||
public class AImpl implements A {
|
public class AImpl implements A {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
|
@ -11,7 +11,6 @@ import jakarta.persistence.Entity;
|
||||||
import jakarta.persistence.Table;
|
import jakarta.persistence.Table;
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@org.hibernate.annotations.Proxy( proxyClass = B.class )
|
|
||||||
@Table( name = "ENTITYB" )
|
@Table( name = "ENTITYB" )
|
||||||
public class BImpl extends AImpl implements B {
|
public class BImpl extends AImpl implements B {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
|
@ -20,7 +20,6 @@ import jakarta.persistence.Table;
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Inheritance( strategy = InheritanceType.JOINED )
|
@Inheritance( strategy = InheritanceType.JOINED )
|
||||||
@org.hibernate.annotations.Proxy( proxyClass = Z.class )
|
|
||||||
@Table( name = "ENTITYZ" )
|
@Table( name = "ENTITYZ" )
|
||||||
public class ZImpl implements Z {
|
public class ZImpl implements Z {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
|
@ -7,7 +7,6 @@ import org.hibernate.Hibernate;
|
||||||
import org.hibernate.annotations.BatchSize;
|
import org.hibernate.annotations.BatchSize;
|
||||||
import org.hibernate.annotations.Fetch;
|
import org.hibernate.annotations.Fetch;
|
||||||
import org.hibernate.annotations.FetchMode;
|
import org.hibernate.annotations.FetchMode;
|
||||||
import org.hibernate.annotations.Proxy;
|
|
||||||
import org.hibernate.cfg.AvailableSettings;
|
import org.hibernate.cfg.AvailableSettings;
|
||||||
|
|
||||||
import org.hibernate.testing.orm.junit.DomainModel;
|
import org.hibernate.testing.orm.junit.DomainModel;
|
||||||
|
@ -15,6 +14,7 @@ import org.hibernate.testing.orm.junit.JiraKey;
|
||||||
import org.hibernate.testing.orm.junit.SessionFactory;
|
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||||
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||||
import org.hibernate.testing.orm.junit.Setting;
|
import org.hibernate.testing.orm.junit.Setting;
|
||||||
|
import org.junit.jupiter.api.Assertions;
|
||||||
import org.junit.jupiter.api.BeforeAll;
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
@ -29,7 +29,6 @@ import jakarta.persistence.criteria.CriteriaBuilder;
|
||||||
import jakarta.persistence.criteria.CriteriaQuery;
|
import jakarta.persistence.criteria.CriteriaQuery;
|
||||||
import jakarta.persistence.criteria.Root;
|
import jakarta.persistence.criteria.Root;
|
||||||
|
|
||||||
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
@ -104,7 +103,11 @@ public class BatchEntityWithDisabledProxyTest {
|
||||||
s.getSessionFactory().getCache().evictAllRegions();
|
s.getSessionFactory().getCache().evictAllRegions();
|
||||||
|
|
||||||
Product product = s.getReference( Product.class, 3 );
|
Product product = s.getReference( Product.class, 3 );
|
||||||
assertTrue( Hibernate.isInitialized(product) );
|
assertFalse( Hibernate.isInitialized( product) );
|
||||||
|
|
||||||
|
Hibernate.initialize( product );
|
||||||
|
|
||||||
|
assertTrue( Hibernate.isInitialized( product) );
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,7 +140,6 @@ public class BatchEntityWithDisabledProxyTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Entity(name = "Product")
|
@Entity(name = "Product")
|
||||||
@Proxy(lazy = false)
|
|
||||||
@BatchSize(size = 512)
|
@BatchSize(size = 512)
|
||||||
@Cacheable
|
@Cacheable
|
||||||
public static class Product {
|
public static class Product {
|
||||||
|
|
|
@ -7,7 +7,6 @@ import org.hibernate.Hibernate;
|
||||||
import org.hibernate.annotations.BatchSize;
|
import org.hibernate.annotations.BatchSize;
|
||||||
import org.hibernate.annotations.Fetch;
|
import org.hibernate.annotations.Fetch;
|
||||||
import org.hibernate.annotations.FetchMode;
|
import org.hibernate.annotations.FetchMode;
|
||||||
import org.hibernate.annotations.Proxy;
|
|
||||||
import org.hibernate.cfg.AvailableSettings;
|
import org.hibernate.cfg.AvailableSettings;
|
||||||
|
|
||||||
import org.hibernate.testing.bytecode.enhancement.extension.BytecodeEnhanced;
|
import org.hibernate.testing.bytecode.enhancement.extension.BytecodeEnhanced;
|
||||||
|
@ -151,7 +150,6 @@ public class BatchEntityOneToManyWithDisabledProxyTest {
|
||||||
|
|
||||||
@Entity(name = "Product")
|
@Entity(name = "Product")
|
||||||
@BatchSize(size = 512)
|
@BatchSize(size = 512)
|
||||||
@Proxy(lazy = false)
|
|
||||||
@Cacheable
|
@Cacheable
|
||||||
public static class Product {
|
public static class Product {
|
||||||
@Id
|
@Id
|
||||||
|
|
|
@ -6,7 +6,6 @@ import org.hibernate.Hibernate;
|
||||||
import org.hibernate.annotations.BatchSize;
|
import org.hibernate.annotations.BatchSize;
|
||||||
import org.hibernate.annotations.Fetch;
|
import org.hibernate.annotations.Fetch;
|
||||||
import org.hibernate.annotations.FetchMode;
|
import org.hibernate.annotations.FetchMode;
|
||||||
import org.hibernate.annotations.Proxy;
|
|
||||||
import org.hibernate.cfg.AvailableSettings;
|
import org.hibernate.cfg.AvailableSettings;
|
||||||
|
|
||||||
import org.hibernate.testing.bytecode.enhancement.extension.BytecodeEnhanced;
|
import org.hibernate.testing.bytecode.enhancement.extension.BytecodeEnhanced;
|
||||||
|
@ -183,7 +182,6 @@ public class BatchEntityWithSelectFetchWithDisableProxyTest {
|
||||||
@Entity(name = "Product")
|
@Entity(name = "Product")
|
||||||
@BatchSize(size = 512)
|
@BatchSize(size = 512)
|
||||||
@Cacheable
|
@Cacheable
|
||||||
@Proxy(lazy = false)
|
|
||||||
public static class Product {
|
public static class Product {
|
||||||
@Id
|
@Id
|
||||||
Long id;
|
Long id;
|
||||||
|
|
|
@ -5,7 +5,6 @@ import org.hibernate.annotations.Cache;
|
||||||
import org.hibernate.annotations.CacheConcurrencyStrategy;
|
import org.hibernate.annotations.CacheConcurrencyStrategy;
|
||||||
import org.hibernate.annotations.Fetch;
|
import org.hibernate.annotations.Fetch;
|
||||||
import org.hibernate.annotations.FetchMode;
|
import org.hibernate.annotations.FetchMode;
|
||||||
import org.hibernate.annotations.Proxy;
|
|
||||||
import org.hibernate.cfg.AvailableSettings;
|
import org.hibernate.cfg.AvailableSettings;
|
||||||
|
|
||||||
import org.hibernate.testing.bytecode.enhancement.extension.BytecodeEnhanced;
|
import org.hibernate.testing.bytecode.enhancement.extension.BytecodeEnhanced;
|
||||||
|
@ -109,7 +108,6 @@ public class AbstractManyToOneNoProxyTest {
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "users")
|
@Table(name = "users")
|
||||||
@Proxy(lazy = false)
|
|
||||||
@BatchSize(size = 512)
|
@BatchSize(size = 512)
|
||||||
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
|
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
|
||||||
@Cacheable
|
@Cacheable
|
||||||
|
@ -144,7 +142,6 @@ public class AbstractManyToOneNoProxyTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Proxy(lazy = false)
|
|
||||||
@BatchSize(size = 512)
|
@BatchSize(size = 512)
|
||||||
@DiscriminatorValue(value = "USER")
|
@DiscriminatorValue(value = "USER")
|
||||||
public static class User extends Actor {
|
public static class User extends Actor {
|
||||||
|
@ -166,7 +163,6 @@ public class AbstractManyToOneNoProxyTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Proxy(lazy = false)
|
|
||||||
@DiscriminatorValue("USERS")
|
@DiscriminatorValue("USERS")
|
||||||
@BatchSize(size = 256)
|
@BatchSize(size = 256)
|
||||||
public static class UserGroup extends ActorGroup<User> {
|
public static class UserGroup extends ActorGroup<User> {
|
||||||
|
@ -176,7 +172,6 @@ public class AbstractManyToOneNoProxyTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Proxy(lazy = false)
|
|
||||||
@Table(name = "actor_group")
|
@Table(name = "actor_group")
|
||||||
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
|
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
|
||||||
@DiscriminatorColumn(name = "TYPE")
|
@DiscriminatorColumn(name = "TYPE")
|
||||||
|
|
|
@ -5,7 +5,6 @@ import org.hibernate.annotations.Cache;
|
||||||
import org.hibernate.annotations.CacheConcurrencyStrategy;
|
import org.hibernate.annotations.CacheConcurrencyStrategy;
|
||||||
import org.hibernate.annotations.Fetch;
|
import org.hibernate.annotations.Fetch;
|
||||||
import org.hibernate.annotations.FetchMode;
|
import org.hibernate.annotations.FetchMode;
|
||||||
import org.hibernate.annotations.Proxy;
|
|
||||||
import org.hibernate.cfg.AvailableSettings;
|
import org.hibernate.cfg.AvailableSettings;
|
||||||
|
|
||||||
import org.hibernate.testing.bytecode.enhancement.extension.BytecodeEnhanced;
|
import org.hibernate.testing.bytecode.enhancement.extension.BytecodeEnhanced;
|
||||||
|
@ -110,7 +109,6 @@ public class ManyToOneNoProxyTest {
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "users")
|
@Table(name = "users")
|
||||||
@Proxy(lazy = false)
|
|
||||||
@BatchSize(size = 512)
|
@BatchSize(size = 512)
|
||||||
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
|
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
|
||||||
@Cacheable
|
@Cacheable
|
||||||
|
@ -145,7 +143,6 @@ public class ManyToOneNoProxyTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Proxy(lazy = false)
|
|
||||||
@BatchSize(size = 512)
|
@BatchSize(size = 512)
|
||||||
@DiscriminatorValue(value = "USER")
|
@DiscriminatorValue(value = "USER")
|
||||||
public static class User extends Actor {
|
public static class User extends Actor {
|
||||||
|
@ -167,7 +164,6 @@ public class ManyToOneNoProxyTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Proxy(lazy = false)
|
|
||||||
@DiscriminatorValue("USERS")
|
@DiscriminatorValue("USERS")
|
||||||
@BatchSize(size = 256)
|
@BatchSize(size = 256)
|
||||||
public static class UserGroup extends ActorGroup<User> {
|
public static class UserGroup extends ActorGroup<User> {
|
||||||
|
@ -177,7 +173,6 @@ public class ManyToOneNoProxyTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Proxy(lazy = false)
|
|
||||||
@Table(name = "actor_group")
|
@Table(name = "actor_group")
|
||||||
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
|
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
|
||||||
@DiscriminatorColumn(name = "TYPE")
|
@DiscriminatorColumn(name = "TYPE")
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package org.hibernate.orm.test.bytecode.enhancement.lazy;
|
package org.hibernate.orm.test.bytecode.enhancement.lazy;
|
||||||
|
|
||||||
import org.hibernate.annotations.Proxy;
|
import org.hibernate.annotations.ConcreteProxy;
|
||||||
|
|
||||||
import org.hibernate.testing.bytecode.enhancement.extension.BytecodeEnhanced;
|
import org.hibernate.testing.bytecode.enhancement.extension.BytecodeEnhanced;
|
||||||
import org.hibernate.testing.jdbc.SQLStatementInspector;
|
import org.hibernate.testing.jdbc.SQLStatementInspector;
|
||||||
|
@ -74,9 +74,7 @@ public class LazyAbstractManyToOneNoProxyTest {
|
||||||
assertThat( user ).isNotNull();
|
assertThat( user ).isNotNull();
|
||||||
assertThat( user.getName() ).isEqualTo( USER_1_NAME );
|
assertThat( user.getName() ).isEqualTo( USER_1_NAME );
|
||||||
|
|
||||||
// The User#team type has subclasses so even if it is lazy we need to initialize it because we do not know
|
assertThat( statementInspector.getSqlQueries().size() ).isEqualTo( 1 );
|
||||||
// the real type and Proxy creation is disabled
|
|
||||||
assertThat( statementInspector.getSqlQueries().size() ).isEqualTo( 2 );
|
|
||||||
|
|
||||||
statementInspector.clear();
|
statementInspector.clear();
|
||||||
|
|
||||||
|
@ -84,14 +82,15 @@ public class LazyAbstractManyToOneNoProxyTest {
|
||||||
assertThat( team ).isInstanceOf( UserGroup.class );
|
assertThat( team ).isInstanceOf( UserGroup.class );
|
||||||
UserGroup userGroup = (UserGroup) team;
|
UserGroup userGroup = (UserGroup) team;
|
||||||
assertThat( userGroup.getName() ).isEqualTo( USER_GROUP_1_NAME );
|
assertThat( userGroup.getName() ).isEqualTo( USER_GROUP_1_NAME );
|
||||||
assertThat( statementInspector.getSqlQueries().size() ).isEqualTo( 0 );
|
|
||||||
|
// accessing the name
|
||||||
|
assertThat( statementInspector.getSqlQueries().size() ).isEqualTo( 1 );
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Entity(name = "User")
|
@Entity(name = "User")
|
||||||
@Table(name = "usr_tbl")
|
@Table(name = "usr_tbl")
|
||||||
@Proxy(lazy = false)
|
|
||||||
public static class User {
|
public static class User {
|
||||||
@Id
|
@Id
|
||||||
Long id;
|
Long id;
|
||||||
|
@ -127,7 +126,7 @@ public class LazyAbstractManyToOneNoProxyTest {
|
||||||
@Entity(name = "ActorGroup")
|
@Entity(name = "ActorGroup")
|
||||||
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
|
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
|
||||||
@DiscriminatorColumn(name = "TYPE")
|
@DiscriminatorColumn(name = "TYPE")
|
||||||
@Proxy(lazy = false)
|
@ConcreteProxy
|
||||||
public abstract static class ActorGroup {
|
public abstract static class ActorGroup {
|
||||||
@Id
|
@Id
|
||||||
Long id;
|
Long id;
|
||||||
|
@ -141,7 +140,6 @@ public class LazyAbstractManyToOneNoProxyTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Entity(name = "UserGroup")
|
@Entity(name = "UserGroup")
|
||||||
@Proxy(lazy = false)
|
|
||||||
@DiscriminatorValue("USERS")
|
@DiscriminatorValue("USERS")
|
||||||
public static class UserGroup extends ActorGroup {
|
public static class UserGroup extends ActorGroup {
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
package org.hibernate.orm.test.bytecode.enhancement.lazy;
|
package org.hibernate.orm.test.bytecode.enhancement.lazy;
|
||||||
|
|
||||||
import org.hibernate.annotations.Proxy;
|
|
||||||
|
|
||||||
import org.hibernate.testing.bytecode.enhancement.extension.BytecodeEnhanced;
|
import org.hibernate.testing.bytecode.enhancement.extension.BytecodeEnhanced;
|
||||||
import org.hibernate.testing.jdbc.SQLStatementInspector;
|
import org.hibernate.testing.jdbc.SQLStatementInspector;
|
||||||
import org.hibernate.testing.orm.junit.DomainModel;
|
import org.hibernate.testing.orm.junit.DomainModel;
|
||||||
|
@ -85,7 +83,6 @@ public class LazyManyToOneNoProxyTest {
|
||||||
|
|
||||||
@Entity(name = "User")
|
@Entity(name = "User")
|
||||||
@Table(name = "usr_tbl")
|
@Table(name = "usr_tbl")
|
||||||
@Proxy(lazy = false)
|
|
||||||
public static class User {
|
public static class User {
|
||||||
@Id
|
@Id
|
||||||
Long id;
|
Long id;
|
||||||
|
@ -119,7 +116,6 @@ public class LazyManyToOneNoProxyTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Entity(name = "UserGroup")
|
@Entity(name = "UserGroup")
|
||||||
@Proxy(lazy = false)
|
|
||||||
public static class UserGroup {
|
public static class UserGroup {
|
||||||
@Id
|
@Id
|
||||||
Long id;
|
Long id;
|
||||||
|
|
|
@ -10,7 +10,6 @@ import org.hibernate.Session;
|
||||||
import org.hibernate.annotations.Cache;
|
import org.hibernate.annotations.Cache;
|
||||||
import org.hibernate.annotations.CacheConcurrencyStrategy;
|
import org.hibernate.annotations.CacheConcurrencyStrategy;
|
||||||
import org.hibernate.annotations.Immutable;
|
import org.hibernate.annotations.Immutable;
|
||||||
import org.hibernate.annotations.Proxy;
|
|
||||||
import org.hibernate.cfg.AvailableSettings;
|
import org.hibernate.cfg.AvailableSettings;
|
||||||
import org.hibernate.cfg.Configuration;
|
import org.hibernate.cfg.Configuration;
|
||||||
import org.hibernate.engine.spi.EntityEntry;
|
import org.hibernate.engine.spi.EntityEntry;
|
||||||
|
@ -18,6 +17,7 @@ import org.hibernate.engine.spi.ManagedEntity;
|
||||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
import org.hibernate.engine.spi.Status;
|
import org.hibernate.engine.spi.Status;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
|
|
||||||
import org.hibernate.testing.TestForIssue;
|
import org.hibernate.testing.TestForIssue;
|
||||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
@ -227,7 +227,6 @@ public class ByteCodeEnhancedImmutableReferenceCacheTest extends BaseCoreFunctio
|
||||||
@Immutable
|
@Immutable
|
||||||
@Cacheable
|
@Cacheable
|
||||||
@Cache(usage = CacheConcurrencyStrategy.READ_ONLY)
|
@Cache(usage = CacheConcurrencyStrategy.READ_ONLY)
|
||||||
@Proxy(lazy = false)
|
|
||||||
@SuppressWarnings("UnusedDeclaration")
|
@SuppressWarnings("UnusedDeclaration")
|
||||||
public static class MyEnhancedReferenceData implements ManagedEntity {
|
public static class MyEnhancedReferenceData implements ManagedEntity {
|
||||||
@Id
|
@Id
|
||||||
|
|
|
@ -6,22 +6,20 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.orm.test.cache;
|
package org.hibernate.orm.test.cache;
|
||||||
|
|
||||||
import jakarta.persistence.Cacheable;
|
|
||||||
import jakarta.persistence.Entity;
|
|
||||||
import jakarta.persistence.Id;
|
|
||||||
|
|
||||||
import org.hibernate.Session;
|
import org.hibernate.Session;
|
||||||
import org.hibernate.annotations.Cache;
|
import org.hibernate.annotations.Cache;
|
||||||
import org.hibernate.annotations.CacheConcurrencyStrategy;
|
import org.hibernate.annotations.CacheConcurrencyStrategy;
|
||||||
import org.hibernate.annotations.Immutable;
|
import org.hibernate.annotations.Immutable;
|
||||||
import org.hibernate.annotations.Proxy;
|
|
||||||
import org.hibernate.cfg.AvailableSettings;
|
import org.hibernate.cfg.AvailableSettings;
|
||||||
import org.hibernate.cfg.Configuration;
|
import org.hibernate.cfg.Configuration;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
|
|
||||||
|
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
import jakarta.persistence.Cacheable;
|
||||||
|
import jakarta.persistence.Entity;
|
||||||
|
import jakarta.persistence.Id;
|
||||||
|
|
||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
@ -91,7 +89,6 @@ public class ReferenceCacheTest extends BaseCoreFunctionalTestCase {
|
||||||
@Immutable
|
@Immutable
|
||||||
@Cacheable
|
@Cacheable
|
||||||
@Cache( usage = CacheConcurrencyStrategy.READ_ONLY )
|
@Cache( usage = CacheConcurrencyStrategy.READ_ONLY )
|
||||||
@Proxy( lazy = false )
|
|
||||||
@SuppressWarnings("UnusedDeclaration")
|
@SuppressWarnings("UnusedDeclaration")
|
||||||
public static class MyReferenceData {
|
public static class MyReferenceData {
|
||||||
@Id
|
@Id
|
||||||
|
|
|
@ -1,204 +0,0 @@
|
||||||
package org.hibernate.orm.test.caching;
|
|
||||||
|
|
||||||
import org.hibernate.Hibernate;
|
|
||||||
import org.hibernate.annotations.BatchSize;
|
|
||||||
import org.hibernate.annotations.Cache;
|
|
||||||
import org.hibernate.annotations.CacheConcurrencyStrategy;
|
|
||||||
import org.hibernate.annotations.Fetch;
|
|
||||||
import org.hibernate.annotations.FetchMode;
|
|
||||||
import org.hibernate.annotations.Proxy;
|
|
||||||
import org.hibernate.cfg.AvailableSettings;
|
|
||||||
|
|
||||||
import org.hibernate.testing.orm.junit.DomainModel;
|
|
||||||
import org.hibernate.testing.orm.junit.Jira;
|
|
||||||
import org.hibernate.testing.orm.junit.ServiceRegistry;
|
|
||||||
import org.hibernate.testing.orm.junit.SessionFactory;
|
|
||||||
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
|
||||||
import org.hibernate.testing.orm.junit.Setting;
|
|
||||||
import org.junit.jupiter.api.AfterAll;
|
|
||||||
import org.junit.jupiter.api.BeforeAll;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
import jakarta.persistence.Cacheable;
|
|
||||||
import jakarta.persistence.Entity;
|
|
||||||
import jakarta.persistence.FetchType;
|
|
||||||
import jakarta.persistence.Id;
|
|
||||||
import jakarta.persistence.ManyToOne;
|
|
||||||
import jakarta.persistence.PostLoad;
|
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
|
||||||
|
|
||||||
@DomainModel( annotatedClasses = {
|
|
||||||
CachingBatchLoadNoProxiesAndCircularRelationshipTest.Category.class,
|
|
||||||
CachingBatchLoadNoProxiesAndCircularRelationshipTest.CategoryHolder.class,
|
|
||||||
} )
|
|
||||||
@SessionFactory
|
|
||||||
@ServiceRegistry( settings = @Setting( name = AvailableSettings.USE_SECOND_LEVEL_CACHE, value = "true" ) )
|
|
||||||
@Jira( "https://hibernate.atlassian.net/browse/HHH-17918" )
|
|
||||||
@Jira( "https://hibernate.atlassian.net/browse/HHH-17983" )
|
|
||||||
public class CachingBatchLoadNoProxiesAndCircularRelationshipTest {
|
|
||||||
private static final int NUMBER_OF_CATEGORIES = 5;
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void recursiveBatchLoadingWithCircularRelationship(SessionFactoryScope scope) {
|
|
||||||
// Set the state of the 2nd-level cache, so it contains #1 (and potentially others) but not #0 or #3
|
|
||||||
scope.getSessionFactory().getCache().evict( Category.class );
|
|
||||||
scope.inTransaction( session -> session.getReference( Category.class, 1 ) );
|
|
||||||
scope.getSessionFactory().getCache().evict( Category.class, 0 );
|
|
||||||
scope.getSessionFactory().getCache().evict( Category.class, 3 );
|
|
||||||
|
|
||||||
scope.inSession( session -> {
|
|
||||||
final CategoryHolder result = session.createQuery(
|
|
||||||
"from CategoryHolder where id = 0",
|
|
||||||
CategoryHolder.class
|
|
||||||
).getSingleResult();
|
|
||||||
Category category = result.getLeftCategory();
|
|
||||||
for ( int i = 0; i < NUMBER_OF_CATEGORIES; i++ ) {
|
|
||||||
assertThat( category ).matches( Hibernate::isInitialized, "Category was not initialized" )
|
|
||||||
.extracting( Category::getId )
|
|
||||||
.isEqualTo( i );
|
|
||||||
if ( i == 3 ) {
|
|
||||||
assertThat( category ).isSameAs( result.getRightCategory() );
|
|
||||||
}
|
|
||||||
else if ( i == NUMBER_OF_CATEGORIES - 1 ) {
|
|
||||||
assertThat( category.getNextCategory() ).isSameAs( result.getLeftCategory() );
|
|
||||||
}
|
|
||||||
category = category.getNextCategory();
|
|
||||||
}
|
|
||||||
} );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void recursiveBatchLoadingSameQueryTest(SessionFactoryScope scope) {
|
|
||||||
scope.getSessionFactory().getCache().evict( Category.class );
|
|
||||||
scope.inSession( session -> {
|
|
||||||
final CategoryHolder result = session.find( CategoryHolder.class, 1 );
|
|
||||||
Category category = result.getLeftCategory();
|
|
||||||
for ( int i = 0; i < NUMBER_OF_CATEGORIES; i++ ) {
|
|
||||||
assertThat( category ).matches( Hibernate::isInitialized, "Category was not initialized" )
|
|
||||||
.extracting( Category::getId )
|
|
||||||
.isEqualTo( i );
|
|
||||||
if ( i == NUMBER_OF_CATEGORIES - 1 ) {
|
|
||||||
assertThat( category ).isSameAs( result.getRightCategory() );
|
|
||||||
assertThat( category.getNextCategory() ).isSameAs( result.getLeftCategory() );
|
|
||||||
}
|
|
||||||
category = category.getNextCategory();
|
|
||||||
}
|
|
||||||
} );
|
|
||||||
}
|
|
||||||
|
|
||||||
@BeforeAll
|
|
||||||
public void setupEntities(SessionFactoryScope scope) {
|
|
||||||
scope.inTransaction( session -> {
|
|
||||||
final Category[] categories = new Category[NUMBER_OF_CATEGORIES];
|
|
||||||
for ( int i = 0; i < categories.length; i++ ) {
|
|
||||||
categories[i] = new Category( i, "category_" + i );
|
|
||||||
session.persist( categories[i] );
|
|
||||||
}
|
|
||||||
// Chain-link the categories (#n points to #n+1, last one points to #0)
|
|
||||||
for ( int i = 0; i < categories.length - 1; i++ ) {
|
|
||||||
categories[i].setNextCategory( categories[i + 1] );
|
|
||||||
}
|
|
||||||
categories[categories.length - 1].nextCategory = categories[0];
|
|
||||||
final CategoryHolder holder1 = new CategoryHolder( 0 );
|
|
||||||
holder1.leftCategory = categories[0];
|
|
||||||
holder1.rightCategory = categories[3];
|
|
||||||
session.persist( holder1 );
|
|
||||||
final CategoryHolder holder2 = new CategoryHolder( 1 );
|
|
||||||
holder2.leftCategory = categories[0];
|
|
||||||
holder2.rightCategory = categories[4];
|
|
||||||
session.persist( holder2 );
|
|
||||||
} );
|
|
||||||
}
|
|
||||||
|
|
||||||
@AfterAll
|
|
||||||
public void tearDown(SessionFactoryScope scope) {
|
|
||||||
scope.inTransaction( session -> {
|
|
||||||
session.createMutationQuery( "delete from CategoryHolder" ).executeUpdate();
|
|
||||||
session.createQuery( "from Category", Category.class )
|
|
||||||
.getResultList()
|
|
||||||
.forEach( c -> c.setNextCategory( null ) );
|
|
||||||
session.createMutationQuery( "delete from Category" ).executeUpdate();
|
|
||||||
} );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Proxy( lazy = false )
|
|
||||||
@Entity( name = "Category" )
|
|
||||||
@BatchSize( size = 10 )
|
|
||||||
@Cacheable
|
|
||||||
@Cache( usage = CacheConcurrencyStrategy.READ_WRITE )
|
|
||||||
static class Category {
|
|
||||||
@Id
|
|
||||||
private Integer id;
|
|
||||||
|
|
||||||
private String name;
|
|
||||||
|
|
||||||
@ManyToOne( fetch = FetchType.LAZY )
|
|
||||||
@Fetch( value = FetchMode.SELECT )
|
|
||||||
private Category nextCategory;
|
|
||||||
|
|
||||||
public Category() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public Category(Integer id, String name) {
|
|
||||||
this.id = id;
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Integer getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Category getNextCategory() {
|
|
||||||
return nextCategory;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setNextCategory(Category nextCategory) {
|
|
||||||
this.nextCategory = nextCategory;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
@PostLoad
|
|
||||||
public void postLoad() {
|
|
||||||
assertThat( name ).isNotNull().isEqualTo( "category_" + id );
|
|
||||||
assertThat( nextCategory.getId() ).isNotNull();
|
|
||||||
// note : nextCategory.name will be null here since the instance will not have been initialized yet
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Entity( name = "CategoryHolder" )
|
|
||||||
static class CategoryHolder {
|
|
||||||
@Id
|
|
||||||
private Integer id;
|
|
||||||
|
|
||||||
@ManyToOne( fetch = FetchType.LAZY )
|
|
||||||
@Fetch( value = FetchMode.SELECT )
|
|
||||||
private Category leftCategory;
|
|
||||||
|
|
||||||
@ManyToOne( fetch = FetchType.LAZY )
|
|
||||||
@Fetch( value = FetchMode.SELECT )
|
|
||||||
private Category rightCategory;
|
|
||||||
|
|
||||||
public CategoryHolder() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public CategoryHolder(Integer id) {
|
|
||||||
this.id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Integer getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Category getLeftCategory() {
|
|
||||||
return leftCategory;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Category getRightCategory() {
|
|
||||||
return rightCategory;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,84 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.classloader;
|
|
||||||
|
|
||||||
import jakarta.persistence.Entity;
|
|
||||||
import jakarta.persistence.Id;
|
|
||||||
|
|
||||||
import org.hibernate.Session;
|
|
||||||
import org.hibernate.Transaction;
|
|
||||||
import org.hibernate.annotations.Proxy;
|
|
||||||
import org.hibernate.proxy.HibernateProxy;
|
|
||||||
|
|
||||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
|
||||||
import org.junit.Assert;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests if instrumentation is done with the proper classloader for entities with proxy class. The classloader
|
|
||||||
* of {@link HibernateProxy} will not see {@link IPerson}, since it is only accessible from this package. But: the
|
|
||||||
* classloader of {@link IPerson} will see {@link HibernateProxy}, so instrumentation will only work if this classloader
|
|
||||||
* is chosen for creating the instrumented proxy class. We need to check the class of a loaded object though, since
|
|
||||||
* building the configuration will not fail, only log the error and fall back to using the entity class itself as a
|
|
||||||
* proxy.
|
|
||||||
*
|
|
||||||
* @author lgathy
|
|
||||||
*/
|
|
||||||
public class ProxyInterfaceClassLoaderTest extends BaseCoreFunctionalTestCase {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Class<?>[] getAnnotatedClasses() {
|
|
||||||
return new Class[] { Person.class };
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testProxyClassLoader() {
|
|
||||||
|
|
||||||
Session s = openSession();
|
|
||||||
Transaction t = s.beginTransaction();
|
|
||||||
IPerson p = new Person();
|
|
||||||
p.setId( 1 );
|
|
||||||
s.persist( p );
|
|
||||||
s.flush();
|
|
||||||
s.clear();
|
|
||||||
|
|
||||||
Object lp = s.load( Person.class, p.getId() );
|
|
||||||
|
|
||||||
Assert.assertTrue( "Loaded entity is not an instance of the proxy interface", IPerson.class.isInstance( lp ) );
|
|
||||||
Assert.assertFalse( "Proxy class was not created", Person.class.isInstance( lp ) );
|
|
||||||
|
|
||||||
s.remove( lp );
|
|
||||||
t.commit();
|
|
||||||
s.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface IPerson {
|
|
||||||
|
|
||||||
int getId();
|
|
||||||
|
|
||||||
void setId(int id);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Entity( name = "Person" )
|
|
||||||
@Proxy(proxyClass = IPerson.class)
|
|
||||||
static class Person implements IPerson {
|
|
||||||
|
|
||||||
@Id
|
|
||||||
private int id;
|
|
||||||
|
|
||||||
public int getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setId(int id) {
|
|
||||||
this.id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -8,84 +8,55 @@ package org.hibernate.orm.test.fetchstrategyhelper;
|
||||||
|
|
||||||
import org.hibernate.annotations.Fetch;
|
import org.hibernate.annotations.Fetch;
|
||||||
import org.hibernate.annotations.FetchMode;
|
import org.hibernate.annotations.FetchMode;
|
||||||
import org.hibernate.annotations.Proxy;
|
|
||||||
import org.hibernate.engine.FetchStyle;
|
import org.hibernate.engine.FetchStyle;
|
||||||
import org.hibernate.engine.FetchTiming;
|
import org.hibernate.engine.FetchTiming;
|
||||||
import org.hibernate.metamodel.mapping.internal.FetchOptionsHelper;
|
import org.hibernate.metamodel.mapping.AttributeMapping;
|
||||||
import org.hibernate.persister.entity.AbstractEntityPersister;
|
import org.hibernate.persister.entity.AbstractEntityPersister;
|
||||||
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
|
import org.hibernate.sql.results.graph.FetchOptions;
|
||||||
import org.hibernate.type.AssociationType;
|
import org.hibernate.type.AssociationType;
|
||||||
|
|
||||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import jakarta.persistence.Entity;
|
||||||
import jakarta.persistence.GeneratedValue;
|
import jakarta.persistence.GeneratedValue;
|
||||||
import jakarta.persistence.Id;
|
import jakarta.persistence.Id;
|
||||||
import jakarta.persistence.ManyToOne;
|
import jakarta.persistence.ManyToOne;
|
||||||
import jakarta.persistence.Table;
|
import jakarta.persistence.Table;
|
||||||
|
|
||||||
import static org.junit.Assert.assertSame;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Gail Badner
|
* @author Gail Badner
|
||||||
*/
|
*/
|
||||||
public class NoProxyFetchStrategyHelperTest extends BaseCoreFunctionalTestCase {
|
public class FetchStrategyDeterminationTests extends BaseCoreFunctionalTestCase {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testManyToOneDefaultFetch() {
|
public void testManyToOneDefaultFetch() {
|
||||||
final AssociationType associationType = determineAssociationType( AnEntity.class, "otherEntityDefault" );
|
final EntityPersister entityDescriptor = sessionFactory().getMappingMetamodel().getEntityDescriptor( AnEntity.class );
|
||||||
final org.hibernate.FetchMode fetchMode = determineFetchMode( AnEntity.class, "otherEntityDefault" );
|
final AttributeMapping attributeMapping = entityDescriptor.findAttributeMapping( "otherEntityDefault" );
|
||||||
assertSame( org.hibernate.FetchMode.JOIN, fetchMode );
|
final FetchOptions mappedFetchOptions = attributeMapping.getMappedFetchOptions();
|
||||||
final FetchStyle fetchStyle = FetchOptionsHelper.determineFetchStyleByMetadata(
|
assertEquals( mappedFetchOptions.getTiming(), FetchTiming.IMMEDIATE );
|
||||||
fetchMode,
|
assertEquals( mappedFetchOptions.getStyle(), FetchStyle.JOIN );
|
||||||
associationType,
|
|
||||||
sessionFactory()
|
|
||||||
);
|
|
||||||
assertSame( FetchStyle.JOIN, fetchStyle );
|
|
||||||
final FetchTiming fetchTiming = FetchOptionsHelper.determineFetchTiming(
|
|
||||||
fetchStyle,
|
|
||||||
associationType,
|
|
||||||
sessionFactory()
|
|
||||||
);
|
|
||||||
assertSame( FetchTiming.IMMEDIATE, fetchTiming );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testManyToOneJoinFetch() {
|
public void testManyToOneJoinFetch() {
|
||||||
final AssociationType associationType = determineAssociationType( AnEntity.class, "otherEntityJoin" );
|
final EntityPersister entityDescriptor = sessionFactory().getMappingMetamodel().getEntityDescriptor( AnEntity.class );
|
||||||
final org.hibernate.FetchMode fetchMode = determineFetchMode( AnEntity.class, "otherEntityJoin" );
|
final AttributeMapping attributeMapping = entityDescriptor.findAttributeMapping( "otherEntityJoin" );
|
||||||
assertSame( org.hibernate.FetchMode.JOIN, fetchMode );
|
final FetchOptions mappedFetchOptions = attributeMapping.getMappedFetchOptions();
|
||||||
final FetchStyle fetchStyle = FetchOptionsHelper.determineFetchStyleByMetadata(
|
assertEquals( mappedFetchOptions.getTiming(), FetchTiming.IMMEDIATE );
|
||||||
fetchMode,
|
assertEquals( mappedFetchOptions.getStyle(), FetchStyle.JOIN );
|
||||||
associationType,
|
|
||||||
sessionFactory()
|
|
||||||
);
|
|
||||||
assertSame( FetchStyle.JOIN, fetchStyle );
|
|
||||||
final FetchTiming fetchTiming = FetchOptionsHelper.determineFetchTiming(
|
|
||||||
fetchStyle,
|
|
||||||
associationType,
|
|
||||||
sessionFactory()
|
|
||||||
);
|
|
||||||
assertSame( FetchTiming.IMMEDIATE, fetchTiming );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testManyToOneSelectFetch() {
|
public void testManyToOneSelectFetch() {
|
||||||
final AssociationType associationType = determineAssociationType( AnEntity.class, "otherEntitySelect" );
|
final EntityPersister entityDescriptor = sessionFactory().getMappingMetamodel().getEntityDescriptor( AnEntity.class );
|
||||||
final org.hibernate.FetchMode fetchMode = determineFetchMode( AnEntity.class, "otherEntitySelect" );
|
final AttributeMapping attributeMapping = entityDescriptor.findAttributeMapping( "otherEntitySelect" );
|
||||||
assertSame( org.hibernate.FetchMode.SELECT, fetchMode );
|
final FetchOptions mappedFetchOptions = attributeMapping.getMappedFetchOptions();
|
||||||
final FetchStyle fetchStyle = FetchOptionsHelper.determineFetchStyleByMetadata(
|
assertEquals( mappedFetchOptions.getTiming(), FetchTiming.IMMEDIATE );
|
||||||
fetchMode,
|
assertEquals( mappedFetchOptions.getStyle(), FetchStyle.SELECT );
|
||||||
associationType,
|
|
||||||
sessionFactory()
|
|
||||||
);
|
|
||||||
assertSame( FetchStyle.SELECT, fetchStyle );
|
|
||||||
final FetchTiming fetchTiming = FetchOptionsHelper.determineFetchTiming(
|
|
||||||
fetchStyle,
|
|
||||||
associationType,
|
|
||||||
sessionFactory()
|
|
||||||
);
|
|
||||||
// Proxies are not allowed, so it should be FetchTiming.IMMEDIATE
|
|
||||||
assertSame( FetchTiming.IMMEDIATE, fetchTiming );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private org.hibernate.FetchMode determineFetchMode(Class<?> entityClass, String path) {
|
private org.hibernate.FetchMode determineFetchMode(Class<?> entityClass, String path) {
|
||||||
|
@ -108,7 +79,7 @@ public class NoProxyFetchStrategyHelperTest extends BaseCoreFunctionalTestCase {
|
||||||
OtherEntity.class
|
OtherEntity.class
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@jakarta.persistence.Entity
|
@Entity
|
||||||
@Table(name="entity")
|
@Table(name="entity")
|
||||||
public static class AnEntity {
|
public static class AnEntity {
|
||||||
@Id
|
@Id
|
||||||
|
@ -129,9 +100,8 @@ public class NoProxyFetchStrategyHelperTest extends BaseCoreFunctionalTestCase {
|
||||||
// @Fetch(FetchMode.SUBSELECT) is not allowed for ToOne associations
|
// @Fetch(FetchMode.SUBSELECT) is not allowed for ToOne associations
|
||||||
}
|
}
|
||||||
|
|
||||||
@jakarta.persistence.Entity
|
@Entity
|
||||||
@Table(name="otherentity")
|
@Table(name="otherentity")
|
||||||
@Proxy(lazy = false)
|
|
||||||
public static class OtherEntity {
|
public static class OtherEntity {
|
||||||
@Id
|
@Id
|
||||||
@GeneratedValue
|
@GeneratedValue
|
|
@ -9,6 +9,10 @@
|
||||||
package org.hibernate.orm.test.jpa.cascade;
|
package org.hibernate.orm.test.jpa.cascade;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import org.hibernate.annotations.DynamicInsert;
|
||||||
|
import org.hibernate.annotations.DynamicUpdate;
|
||||||
|
|
||||||
import jakarta.persistence.Column;
|
import jakarta.persistence.Column;
|
||||||
import jakarta.persistence.Entity;
|
import jakarta.persistence.Entity;
|
||||||
import jakarta.persistence.GeneratedValue;
|
import jakarta.persistence.GeneratedValue;
|
||||||
|
@ -17,17 +21,12 @@ import jakarta.persistence.JoinColumn;
|
||||||
import jakarta.persistence.OneToOne;
|
import jakarta.persistence.OneToOne;
|
||||||
import jakarta.persistence.Table;
|
import jakarta.persistence.Table;
|
||||||
|
|
||||||
import org.hibernate.annotations.DynamicInsert;
|
|
||||||
import org.hibernate.annotations.DynamicUpdate;
|
|
||||||
import org.hibernate.annotations.Proxy;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Emmanuel Bernard
|
* @author Emmanuel Bernard
|
||||||
*/
|
*/
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "portal_pk_docs_extraction")
|
@Table(name = "portal_pk_docs_extraction")
|
||||||
@DynamicUpdate @DynamicInsert
|
@DynamicUpdate @DynamicInsert
|
||||||
@Proxy
|
|
||||||
public class ExtractionDocument implements Serializable {
|
public class ExtractionDocument implements Serializable {
|
||||||
private Long id;
|
private Long id;
|
||||||
private byte[] body;
|
private byte[] body;
|
||||||
|
|
|
@ -1,161 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.ops.genericApi;
|
|
||||||
|
|
||||||
import jakarta.persistence.Entity;
|
|
||||||
import jakarta.persistence.GeneratedValue;
|
|
||||||
import jakarta.persistence.Id;
|
|
||||||
import jakarta.persistence.Table;
|
|
||||||
|
|
||||||
import org.hibernate.LockMode;
|
|
||||||
import org.hibernate.LockOptions;
|
|
||||||
import org.hibernate.annotations.GenericGenerator;
|
|
||||||
import org.hibernate.annotations.Proxy;
|
|
||||||
|
|
||||||
import org.hibernate.testing.orm.junit.DomainModel;
|
|
||||||
import org.hibernate.testing.orm.junit.SessionFactory;
|
|
||||||
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Steve Ebersole
|
|
||||||
*/
|
|
||||||
@DomainModel(
|
|
||||||
annotatedClasses = ProxiedGetLoadAccessTest.UserImpl.class
|
|
||||||
)
|
|
||||||
@SessionFactory
|
|
||||||
public class ProxiedGetLoadAccessTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testIt(SessionFactoryScope scope) {
|
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
// create a row
|
|
||||||
scope.inTransaction(
|
|
||||||
session ->
|
|
||||||
session.persist( new UserImpl( "steve" ) )
|
|
||||||
);
|
|
||||||
|
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
// test `get` access
|
|
||||||
scope.inTransaction(
|
|
||||||
session -> {
|
|
||||||
// THis technically works
|
|
||||||
session.get( UserImpl.class, 1 );
|
|
||||||
session.get( User.class, 1 );
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
scope.inTransaction(
|
|
||||||
session -> {
|
|
||||||
session.get( UserImpl.class, 1, LockMode.PESSIMISTIC_WRITE );
|
|
||||||
session.get( User.class, 1, LockMode.PESSIMISTIC_WRITE );
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
scope.inTransaction(
|
|
||||||
session -> {
|
|
||||||
session.get( UserImpl.class, 1, LockOptions.UPGRADE );
|
|
||||||
session.get( User.class, 1, LockOptions.UPGRADE );
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
scope.inTransaction(
|
|
||||||
session -> {
|
|
||||||
session.byId( UserImpl.class ).load( 1 );
|
|
||||||
session.byId( User.class ).load( 1 );
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
scope.inTransaction(
|
|
||||||
session -> {
|
|
||||||
session.byId( UserImpl.class ).with( LockOptions.UPGRADE ).load( 1 );
|
|
||||||
session.byId( User.class ).with( LockOptions.UPGRADE ).load( 1 );
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
// test `load` access
|
|
||||||
scope.inTransaction(
|
|
||||||
session -> {
|
|
||||||
session.load( UserImpl.class, 1 );
|
|
||||||
session.load( User.class, 1 );
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
scope.inTransaction(
|
|
||||||
session -> {
|
|
||||||
session.load( UserImpl.class, 1, LockMode.PESSIMISTIC_WRITE );
|
|
||||||
session.load( User.class, 1, LockMode.PESSIMISTIC_WRITE );
|
|
||||||
}
|
|
||||||
);
|
|
||||||
scope.inTransaction(
|
|
||||||
session -> {
|
|
||||||
session.load( UserImpl.class, 1, LockOptions.UPGRADE );
|
|
||||||
session.load( User.class, 1, LockOptions.UPGRADE );
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
scope.inTransaction(
|
|
||||||
session -> {
|
|
||||||
session.byId( UserImpl.class ).getReference( 1 );
|
|
||||||
session.byId( User.class ).getReference( 1 );
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
scope.inTransaction(
|
|
||||||
session -> {
|
|
||||||
session.byId( UserImpl.class ).with( LockOptions.UPGRADE ).getReference( 1 );
|
|
||||||
session.byId( User.class ).with( LockOptions.UPGRADE ).getReference( 1 );
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface User {
|
|
||||||
Integer getId();
|
|
||||||
|
|
||||||
String getName();
|
|
||||||
|
|
||||||
void setName(String name);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Entity(name = "User")
|
|
||||||
@Table(name = "my_user")
|
|
||||||
@Proxy(proxyClass = User.class)
|
|
||||||
public static class UserImpl implements User {
|
|
||||||
private Integer id;
|
|
||||||
private String name;
|
|
||||||
|
|
||||||
public UserImpl() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public UserImpl(String name) {
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Id
|
|
||||||
@GeneratedValue(generator = "increment")
|
|
||||||
@GenericGenerator(name = "increment", strategy = "increment")
|
|
||||||
@Override
|
|
||||||
public Integer getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setId(Integer id) {
|
|
||||||
this.id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setName(String name) {
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,111 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.proxy;
|
|
||||||
|
|
||||||
import jakarta.persistence.Entity;
|
|
||||||
import jakarta.persistence.Id;
|
|
||||||
|
|
||||||
import org.hibernate.annotations.Proxy;
|
|
||||||
|
|
||||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
|
|
||||||
import static org.junit.Assert.assertFalse;
|
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author lgathy
|
|
||||||
*/
|
|
||||||
public class ProxyInterfaceTest extends BaseCoreFunctionalTestCase {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Class<?>[] getAnnotatedClasses() {
|
|
||||||
return new Class[] { Book.class };
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testProxyClassLoader() {
|
|
||||||
|
|
||||||
//tag::entity-proxy-persist-mapping[]
|
|
||||||
doInHibernate(this::sessionFactory, session -> {
|
|
||||||
Book book = new Book();
|
|
||||||
book.setId(1L);
|
|
||||||
book.setTitle("High-Performance Java Persistence");
|
|
||||||
book.setAuthor("Vlad Mihalcea");
|
|
||||||
|
|
||||||
session.persist(book);
|
|
||||||
});
|
|
||||||
|
|
||||||
doInHibernate(this::sessionFactory, session -> {
|
|
||||||
Identifiable book = session.getReference(Book.class, 1L);
|
|
||||||
|
|
||||||
assertTrue(
|
|
||||||
"Loaded entity is not an instance of the proxy interface",
|
|
||||||
book instanceof Identifiable
|
|
||||||
);
|
|
||||||
assertFalse(
|
|
||||||
"Proxy class was not created",
|
|
||||||
book instanceof Book
|
|
||||||
);
|
|
||||||
});
|
|
||||||
//end::entity-proxy-persist-mapping[]
|
|
||||||
}
|
|
||||||
|
|
||||||
//tag::entity-proxy-interface-mapping[]
|
|
||||||
public interface Identifiable {
|
|
||||||
|
|
||||||
Long getId();
|
|
||||||
|
|
||||||
void setId(Long id);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Entity(name = "Book")
|
|
||||||
@Proxy(proxyClass = Identifiable.class)
|
|
||||||
public static final class Book implements Identifiable {
|
|
||||||
|
|
||||||
@Id
|
|
||||||
private Long id;
|
|
||||||
|
|
||||||
private String title;
|
|
||||||
|
|
||||||
private String author;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Long getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setId(Long id) {
|
|
||||||
this.id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Other getters and setters omitted for brevity
|
|
||||||
//end::entity-proxy-interface-mapping[]
|
|
||||||
|
|
||||||
public String getTitle() {
|
|
||||||
return title;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTitle(String title) {
|
|
||||||
this.title = title;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getAuthor() {
|
|
||||||
return author;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAuthor(String author) {
|
|
||||||
this.author = author;
|
|
||||||
}
|
|
||||||
//tag::entity-proxy-interface-mapping[]
|
|
||||||
}
|
|
||||||
//end::entity-proxy-interface-mapping[]
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,263 +0,0 @@
|
||||||
package org.hibernate.orm.test.proxy;
|
|
||||||
|
|
||||||
import jakarta.persistence.*;
|
|
||||||
import org.hibernate.annotations.Proxy;
|
|
||||||
import org.hibernate.proxy.HibernateProxy;
|
|
||||||
import org.hibernate.testing.orm.junit.DomainModel;
|
|
||||||
import org.hibernate.testing.orm.junit.JiraKey;
|
|
||||||
import org.hibernate.testing.orm.junit.SessionFactory;
|
|
||||||
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertNotNull;
|
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Oliver Henlich
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* Test that demonstrates the intermittent {@link ClassCastException} that occurs
|
|
||||||
* when trying to call a method on a {@link HibernateProxy} where the parameter
|
|
||||||
* type is defined by generics.
|
|
||||||
*/
|
|
||||||
@JiraKey("HHH-17578")
|
|
||||||
@DomainModel(
|
|
||||||
annotatedClasses = {
|
|
||||||
ProxyWithGenericsTest.AbstractEntityImpl.class,
|
|
||||||
ProxyWithGenericsTest.AbstractShapeEntityImpl.class,
|
|
||||||
ProxyWithGenericsTest.CircleEntityImpl.class,
|
|
||||||
ProxyWithGenericsTest.SquareEntityImpl.class,
|
|
||||||
ProxyWithGenericsTest.CircleContainerEntityImpl.class,
|
|
||||||
ProxyWithGenericsTest.SquareContainerEntityImpl.class,
|
|
||||||
ProxyWithGenericsTest.MainEntityImpl.class
|
|
||||||
}
|
|
||||||
)
|
|
||||||
@SessionFactory
|
|
||||||
@SuppressWarnings("ALL")
|
|
||||||
public class ProxyWithGenericsTest {
|
|
||||||
|
|
||||||
@BeforeEach
|
|
||||||
void setUp(SessionFactoryScope scope) {
|
|
||||||
scope.inTransaction(session -> {
|
|
||||||
EntityManager em = session.unwrap(EntityManager.class);
|
|
||||||
|
|
||||||
// Shape 1
|
|
||||||
CircleEntityImpl cirlce1 = new CircleEntityImpl();
|
|
||||||
cirlce1.radius = BigDecimal.valueOf(1);
|
|
||||||
em.persist(cirlce1);
|
|
||||||
|
|
||||||
// Shape 2
|
|
||||||
SquareEntityImpl square1 = new SquareEntityImpl();
|
|
||||||
square1.width = BigDecimal.valueOf(1);
|
|
||||||
square1.height = BigDecimal.valueOf(2);
|
|
||||||
em.persist(square1);
|
|
||||||
|
|
||||||
// Container 1
|
|
||||||
CircleContainerEntity circleContainer1 = new CircleContainerEntityImpl();
|
|
||||||
em.persist(circleContainer1);
|
|
||||||
|
|
||||||
// Container 2
|
|
||||||
SquareContainerEntity squareContainer1 = new SquareContainerEntityImpl();
|
|
||||||
em.persist(squareContainer1);
|
|
||||||
|
|
||||||
// Main
|
|
||||||
MainEntityImpl main = new MainEntityImpl();
|
|
||||||
main.circleContainer = circleContainer1;
|
|
||||||
main.squareContainer = squareContainer1;
|
|
||||||
em.persist(main);
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void test(SessionFactoryScope scope) throws Exception {
|
|
||||||
|
|
||||||
scope.inTransaction(session -> {
|
|
||||||
EntityManager em = session.unwrap(EntityManager.class);
|
|
||||||
|
|
||||||
MainEntityImpl main = em.find(MainEntityImpl.class, 1L);
|
|
||||||
assertNotNull(main);
|
|
||||||
|
|
||||||
CircleContainerEntity circleContainer = main.getCircleContainer();
|
|
||||||
assertNotNull(circleContainer);
|
|
||||||
assertTrue(circleContainer instanceof HibernateProxy);
|
|
||||||
CircleEntity circle1 = em.find(CircleEntityImpl.class, 1L);
|
|
||||||
circleContainer.add(circle1); // This method fails with ClassCastException without the fix
|
|
||||||
|
|
||||||
SquareContainerEntity squareContainer = main.getSquareContainer();
|
|
||||||
assertNotNull(squareContainer);
|
|
||||||
assertTrue(squareContainer instanceof HibernateProxy);
|
|
||||||
SquareEntity square1 = em.find(SquareEntityImpl.class, 2L);
|
|
||||||
squareContainer.add(square1); // This method fails with ClassCastException without the fix
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Shapes hierarchy -------------------------------------------------------
|
|
||||||
public interface ShapeEntity {
|
|
||||||
BigDecimal getArea();
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface CircleEntity extends ShapeEntity {
|
|
||||||
BigDecimal getRadius();
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface SquareEntity extends ShapeEntity {
|
|
||||||
BigDecimal getWidth();
|
|
||||||
|
|
||||||
BigDecimal getHeight();
|
|
||||||
}
|
|
||||||
|
|
||||||
@MappedSuperclass
|
|
||||||
@Access(AccessType.FIELD)
|
|
||||||
public static abstract class AbstractEntityImpl {
|
|
||||||
@Id
|
|
||||||
@GeneratedValue
|
|
||||||
@Column(name = "ID")
|
|
||||||
Long id;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Entity
|
|
||||||
@Table(name = "SHAPE")
|
|
||||||
@Access(AccessType.FIELD)
|
|
||||||
@Proxy(proxyClass = ShapeEntity.class)
|
|
||||||
@DiscriminatorColumn(name = "TYPE", length = 20)
|
|
||||||
public static abstract class AbstractShapeEntityImpl
|
|
||||||
extends AbstractEntityImpl
|
|
||||||
implements ShapeEntity {
|
|
||||||
public abstract BigDecimal getArea();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Entity
|
|
||||||
@Proxy(proxyClass = CircleEntity.class)
|
|
||||||
@Access(AccessType.FIELD)
|
|
||||||
@DiscriminatorValue("CIRCLE")
|
|
||||||
public static class CircleEntityImpl
|
|
||||||
extends AbstractShapeEntityImpl
|
|
||||||
implements CircleEntity {
|
|
||||||
@Column(name = "RADIUS", nullable = true)
|
|
||||||
private BigDecimal radius;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BigDecimal getArea() {
|
|
||||||
return new BigDecimal(Math.PI).multiply(radius.pow(2));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BigDecimal getRadius() {
|
|
||||||
return radius;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Entity
|
|
||||||
@Proxy(proxyClass = SquareEntity.class)
|
|
||||||
@Access(AccessType.FIELD)
|
|
||||||
@DiscriminatorValue("SQUARE")
|
|
||||||
public static class SquareEntityImpl
|
|
||||||
extends AbstractShapeEntityImpl
|
|
||||||
implements SquareEntity {
|
|
||||||
|
|
||||||
@Column(name = "WIDTH", nullable = true)
|
|
||||||
private BigDecimal width;
|
|
||||||
|
|
||||||
@Column(name = "HEIGHT", nullable = true)
|
|
||||||
private BigDecimal height;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BigDecimal getArea() {
|
|
||||||
return width.multiply(height);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BigDecimal getWidth() {
|
|
||||||
return width;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BigDecimal getHeight() {
|
|
||||||
return height;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ShapeContainer hierarchy -----------------------------------------------
|
|
||||||
|
|
||||||
public interface ShapeContainerEntity<T extends ShapeEntity> {
|
|
||||||
void add(T shape);
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface CircleContainerEntity extends ShapeContainerEntity<CircleEntity> {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface SquareContainerEntity extends ShapeContainerEntity<SquareEntity> {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Entity
|
|
||||||
@Table(name = "CONTAINER")
|
|
||||||
@Access(AccessType.FIELD)
|
|
||||||
@Proxy(proxyClass = ShapeContainerEntity.class)
|
|
||||||
@DiscriminatorColumn(name = "TYPE", length = 20)
|
|
||||||
public static abstract class AbstractShapeContainerEntityImpl<T extends ShapeEntity>
|
|
||||||
extends AbstractEntityImpl
|
|
||||||
implements ShapeContainerEntity<T> {
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Entity
|
|
||||||
@Proxy(proxyClass = SquareContainerEntity.class)
|
|
||||||
@Access(AccessType.FIELD)
|
|
||||||
@DiscriminatorValue("SQUARE")
|
|
||||||
public static class SquareContainerEntityImpl
|
|
||||||
extends AbstractShapeContainerEntityImpl<SquareEntity>
|
|
||||||
implements SquareContainerEntity {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void add(SquareEntity shape) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Entity
|
|
||||||
@Proxy(proxyClass = CircleContainerEntity.class)
|
|
||||||
@Access(AccessType.FIELD)
|
|
||||||
@DiscriminatorValue("CIRCLE")
|
|
||||||
public static class CircleContainerEntityImpl
|
|
||||||
extends AbstractShapeContainerEntityImpl<CircleEntity>
|
|
||||||
implements CircleContainerEntity {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void add(CircleEntity shape) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Main test entity that has lazy references to the two types of {@link ShapeContainerEntity containers}.
|
|
||||||
*/
|
|
||||||
@Entity
|
|
||||||
@Table(name = "Main")
|
|
||||||
@Access(AccessType.FIELD)
|
|
||||||
public static class MainEntityImpl
|
|
||||||
extends AbstractEntityImpl {
|
|
||||||
|
|
||||||
@ManyToOne(targetEntity = AbstractShapeContainerEntityImpl.class, optional = true, fetch = FetchType.LAZY)
|
|
||||||
@JoinColumn(name = "CIRCLE_CONTAINER_ID")
|
|
||||||
private CircleContainerEntity circleContainer;
|
|
||||||
|
|
||||||
@ManyToOne(targetEntity = AbstractShapeContainerEntityImpl.class, optional = true, fetch = FetchType.LAZY)
|
|
||||||
@JoinColumn(name = "SQUARE_CONTAINER_ID")
|
|
||||||
private SquareContainerEntity squareContainer;
|
|
||||||
|
|
||||||
public CircleContainerEntity getCircleContainer() {
|
|
||||||
return circleContainer;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SquareContainerEntity getSquareContainer() {
|
|
||||||
return squareContainer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -7,20 +7,19 @@
|
||||||
package org.hibernate.orm.test.envers.entities;
|
package org.hibernate.orm.test.envers.entities;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import org.hibernate.envers.Audited;
|
||||||
|
|
||||||
import jakarta.persistence.Entity;
|
import jakarta.persistence.Entity;
|
||||||
import jakarta.persistence.GeneratedValue;
|
import jakarta.persistence.GeneratedValue;
|
||||||
import jakarta.persistence.Id;
|
import jakarta.persistence.Id;
|
||||||
import jakarta.persistence.Table;
|
import jakarta.persistence.Table;
|
||||||
|
|
||||||
import org.hibernate.annotations.Proxy;
|
|
||||||
import org.hibernate.envers.Audited;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
|
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
|
||||||
*/
|
*/
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "STR_TEST_NP")
|
@Table(name = "STR_TEST_NP")
|
||||||
@Proxy(lazy = false)
|
|
||||||
public class StrTestNoProxyEntity implements Serializable {
|
public class StrTestNoProxyEntity implements Serializable {
|
||||||
@Id
|
@Id
|
||||||
@GeneratedValue
|
@GeneratedValue
|
||||||
|
|
|
@ -6,6 +6,9 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.orm.test.envers.entities.onetoone;
|
package org.hibernate.orm.test.envers.entities.onetoone;
|
||||||
|
|
||||||
|
import org.hibernate.envers.Audited;
|
||||||
|
import org.hibernate.envers.NotAudited;
|
||||||
|
|
||||||
import jakarta.persistence.Entity;
|
import jakarta.persistence.Entity;
|
||||||
import jakarta.persistence.FetchType;
|
import jakarta.persistence.FetchType;
|
||||||
import jakarta.persistence.GeneratedValue;
|
import jakarta.persistence.GeneratedValue;
|
||||||
|
@ -13,16 +16,11 @@ import jakarta.persistence.Id;
|
||||||
import jakarta.persistence.OneToOne;
|
import jakarta.persistence.OneToOne;
|
||||||
import jakarta.persistence.Table;
|
import jakarta.persistence.Table;
|
||||||
|
|
||||||
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.
|
* Test class for issue HHH-3854. Restricting creation of proxy objects is essential.
|
||||||
*/
|
*/
|
||||||
@Entity
|
@Entity
|
||||||
@Audited
|
@Audited
|
||||||
@Proxy(lazy = false)
|
|
||||||
// Class name is too long of an identifier for Oracle.
|
// Class name is too long of an identifier for Oracle.
|
||||||
@Table(name = "EdOneToOne")
|
@Table(name = "EdOneToOne")
|
||||||
public final class BidirectionalEagerAnnotationRefEdOneToOne {
|
public final class BidirectionalEagerAnnotationRefEdOneToOne {
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.orm.test.envers.entities.onetoone;
|
package org.hibernate.orm.test.envers.entities.onetoone;
|
||||||
|
|
||||||
|
import org.hibernate.envers.Audited;
|
||||||
|
|
||||||
import jakarta.persistence.CascadeType;
|
import jakarta.persistence.CascadeType;
|
||||||
import jakarta.persistence.Entity;
|
import jakarta.persistence.Entity;
|
||||||
import jakarta.persistence.FetchType;
|
import jakarta.persistence.FetchType;
|
||||||
|
@ -15,15 +17,11 @@ import jakarta.persistence.JoinColumn;
|
||||||
import jakarta.persistence.OneToOne;
|
import jakarta.persistence.OneToOne;
|
||||||
import jakarta.persistence.Table;
|
import jakarta.persistence.Table;
|
||||||
|
|
||||||
import org.hibernate.annotations.Proxy;
|
|
||||||
import org.hibernate.envers.Audited;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test class for issue HHH-3854. Restricting creation of proxy objects is essential.
|
* Test class for issue HHH-3854. Restricting creation of proxy objects is essential.
|
||||||
*/
|
*/
|
||||||
@Entity
|
@Entity
|
||||||
@Audited
|
@Audited
|
||||||
@Proxy(lazy = false)
|
|
||||||
//Class name is too long of an identifier for Oracle.
|
//Class name is too long of an identifier for Oracle.
|
||||||
@Table(name = "IngOneToOne")
|
@Table(name = "IngOneToOne")
|
||||||
public final class BidirectionalEagerAnnotationRefIngOneToOne {
|
public final class BidirectionalEagerAnnotationRefIngOneToOne {
|
||||||
|
|
|
@ -30,13 +30,9 @@ public class AccountNotAuditedOwners implements Serializable {
|
||||||
|
|
||||||
private String type;
|
private String type;
|
||||||
|
|
||||||
@OneToOne(mappedBy = "account", optional = false)
|
|
||||||
@Audited(targetAuditMode = RelationTargetAuditMode.NOT_AUDITED)
|
|
||||||
private NotAuditedNoProxyPerson owner;
|
|
||||||
|
|
||||||
@OneToOne(mappedBy = "account", optional = false, fetch = FetchType.LAZY)
|
@OneToOne(mappedBy = "account", optional = false, fetch = FetchType.LAZY)
|
||||||
@Audited(targetAuditMode = RelationTargetAuditMode.NOT_AUDITED)
|
@Audited(targetAuditMode = RelationTargetAuditMode.NOT_AUDITED)
|
||||||
private NotAuditedProxyPerson coOwner;
|
private NotAuditedPerson owner;
|
||||||
|
|
||||||
public AccountNotAuditedOwners() {
|
public AccountNotAuditedOwners() {
|
||||||
}
|
}
|
||||||
|
@ -91,22 +87,14 @@ public class AccountNotAuditedOwners implements Serializable {
|
||||||
this.accountId = accountId;
|
this.accountId = accountId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public NotAuditedNoProxyPerson getOwner() {
|
public NotAuditedPerson getOwner() {
|
||||||
return owner;
|
return owner;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setOwner(NotAuditedNoProxyPerson owner) {
|
public void setOwner(NotAuditedPerson owner) {
|
||||||
this.owner = owner;
|
this.owner = owner;
|
||||||
}
|
}
|
||||||
|
|
||||||
public NotAuditedProxyPerson getCoOwner() {
|
|
||||||
return coOwner;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCoOwner(NotAuditedProxyPerson coOwner) {
|
|
||||||
this.coOwner = coOwner;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getType() {
|
public String getType() {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,10 @@
|
||||||
package org.hibernate.orm.test.envers.integration.onetoone.bidirectional.primarykeyjoincolumn;
|
package org.hibernate.orm.test.envers.integration.onetoone.bidirectional.primarykeyjoincolumn;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import org.hibernate.annotations.GenericGenerator;
|
||||||
|
import org.hibernate.annotations.Parameter;
|
||||||
|
|
||||||
import jakarta.persistence.Column;
|
import jakarta.persistence.Column;
|
||||||
import jakarta.persistence.Entity;
|
import jakarta.persistence.Entity;
|
||||||
import jakarta.persistence.GeneratedValue;
|
import jakarta.persistence.GeneratedValue;
|
||||||
|
@ -14,15 +18,10 @@ import jakarta.persistence.Id;
|
||||||
import jakarta.persistence.OneToOne;
|
import jakarta.persistence.OneToOne;
|
||||||
import jakarta.persistence.PrimaryKeyJoinColumn;
|
import jakarta.persistence.PrimaryKeyJoinColumn;
|
||||||
|
|
||||||
import org.hibernate.annotations.GenericGenerator;
|
|
||||||
import org.hibernate.annotations.Parameter;
|
|
||||||
import org.hibernate.annotations.Proxy;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
|
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
|
||||||
*/
|
*/
|
||||||
@Entity
|
@Entity
|
||||||
@Proxy(lazy = false)
|
|
||||||
public class NotAuditedNoProxyPerson implements Serializable {
|
public class NotAuditedNoProxyPerson implements Serializable {
|
||||||
@Id
|
@Id
|
||||||
@Column(name = "PERSON_ID")
|
@Column(name = "PERSON_ID")
|
||||||
|
|
|
@ -7,6 +7,10 @@
|
||||||
package org.hibernate.orm.test.envers.integration.onetoone.bidirectional.primarykeyjoincolumn;
|
package org.hibernate.orm.test.envers.integration.onetoone.bidirectional.primarykeyjoincolumn;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import org.hibernate.annotations.GenericGenerator;
|
||||||
|
import org.hibernate.annotations.Parameter;
|
||||||
|
|
||||||
import jakarta.persistence.Column;
|
import jakarta.persistence.Column;
|
||||||
import jakarta.persistence.Entity;
|
import jakarta.persistence.Entity;
|
||||||
import jakarta.persistence.FetchType;
|
import jakarta.persistence.FetchType;
|
||||||
|
@ -15,16 +19,11 @@ import jakarta.persistence.Id;
|
||||||
import jakarta.persistence.OneToOne;
|
import jakarta.persistence.OneToOne;
|
||||||
import jakarta.persistence.PrimaryKeyJoinColumn;
|
import jakarta.persistence.PrimaryKeyJoinColumn;
|
||||||
|
|
||||||
import org.hibernate.annotations.GenericGenerator;
|
|
||||||
import org.hibernate.annotations.Parameter;
|
|
||||||
import org.hibernate.annotations.Proxy;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
|
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
|
||||||
*/
|
*/
|
||||||
@Entity
|
@Entity
|
||||||
@Proxy(lazy = true)
|
public class NotAuditedPerson implements Serializable {
|
||||||
public class NotAuditedProxyPerson implements Serializable {
|
|
||||||
@Id
|
@Id
|
||||||
@Column(name = "PERSON_ID")
|
@Column(name = "PERSON_ID")
|
||||||
@GeneratedValue(generator = "NotAuditedProxyKeyGenerator")
|
@GeneratedValue(generator = "NotAuditedProxyKeyGenerator")
|
||||||
|
@ -38,14 +37,14 @@ public class NotAuditedProxyPerson implements Serializable {
|
||||||
@PrimaryKeyJoinColumn(name = "PERSON_ID", referencedColumnName = "ACCOUNT_ID")
|
@PrimaryKeyJoinColumn(name = "PERSON_ID", referencedColumnName = "ACCOUNT_ID")
|
||||||
private AccountNotAuditedOwners account;
|
private AccountNotAuditedOwners account;
|
||||||
|
|
||||||
public NotAuditedProxyPerson() {
|
public NotAuditedPerson() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public NotAuditedProxyPerson(String name) {
|
public NotAuditedPerson(String name) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public NotAuditedProxyPerson(Long personId, String name) {
|
public NotAuditedPerson(Long personId, String name) {
|
||||||
this.personId = personId;
|
this.personId = personId;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
@ -55,11 +54,11 @@ public class NotAuditedProxyPerson implements Serializable {
|
||||||
if ( this == o ) {
|
if ( this == o ) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if ( !(o instanceof NotAuditedProxyPerson) ) {
|
if ( !(o instanceof NotAuditedPerson ) ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
NotAuditedProxyPerson person = (NotAuditedProxyPerson) o;
|
NotAuditedPerson person = (NotAuditedPerson) o;
|
||||||
|
|
||||||
if ( personId != null ? !personId.equals( person.personId ) : person.personId != null ) {
|
if ( personId != null ? !personId.equals( person.personId ) : person.personId != null ) {
|
||||||
return false;
|
return false;
|
|
@ -7,7 +7,6 @@
|
||||||
package org.hibernate.orm.test.envers.integration.onetoone.bidirectional.primarykeyjoincolumn;
|
package org.hibernate.orm.test.envers.integration.onetoone.bidirectional.primarykeyjoincolumn;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import jakarta.persistence.EntityManager;
|
|
||||||
|
|
||||||
import org.hibernate.envers.RevisionType;
|
import org.hibernate.envers.RevisionType;
|
||||||
import org.hibernate.envers.query.AuditEntity;
|
import org.hibernate.envers.query.AuditEntity;
|
||||||
|
@ -19,6 +18,8 @@ import org.hibernate.testing.TestForIssue;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import jakarta.persistence.EntityManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
|
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
|
||||||
*/
|
*/
|
||||||
|
@ -27,7 +28,6 @@ public class OneToOneWithPrimaryKeyJoinTest extends BaseEnversJPAFunctionalTestC
|
||||||
private Long personId = null;
|
private Long personId = null;
|
||||||
private Long accountId = null;
|
private Long accountId = null;
|
||||||
private Long proxyPersonId = null;
|
private Long proxyPersonId = null;
|
||||||
private Long noProxyPersonId = null;
|
|
||||||
private Long accountNotAuditedOwnersId = null;
|
private Long accountNotAuditedOwnersId = null;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -36,8 +36,7 @@ public class OneToOneWithPrimaryKeyJoinTest extends BaseEnversJPAFunctionalTestC
|
||||||
Person.class,
|
Person.class,
|
||||||
Account.class,
|
Account.class,
|
||||||
AccountNotAuditedOwners.class,
|
AccountNotAuditedOwners.class,
|
||||||
NotAuditedNoProxyPerson.class,
|
NotAuditedPerson.class
|
||||||
NotAuditedProxyPerson.class
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,15 +57,11 @@ public class OneToOneWithPrimaryKeyJoinTest extends BaseEnversJPAFunctionalTestC
|
||||||
|
|
||||||
// Revision 2
|
// Revision 2
|
||||||
em.getTransaction().begin();
|
em.getTransaction().begin();
|
||||||
NotAuditedNoProxyPerson noProxyPerson = new NotAuditedNoProxyPerson( "Kinga" );
|
NotAuditedPerson proxyPerson = new NotAuditedPerson( "Lukasz" );
|
||||||
NotAuditedProxyPerson proxyPerson = new NotAuditedProxyPerson( "Lukasz" );
|
|
||||||
AccountNotAuditedOwners accountNotAuditedOwners = new AccountNotAuditedOwners( "Standard" );
|
AccountNotAuditedOwners accountNotAuditedOwners = new AccountNotAuditedOwners( "Standard" );
|
||||||
noProxyPerson.setAccount( accountNotAuditedOwners );
|
|
||||||
proxyPerson.setAccount( accountNotAuditedOwners );
|
proxyPerson.setAccount( accountNotAuditedOwners );
|
||||||
accountNotAuditedOwners.setOwner( noProxyPerson );
|
accountNotAuditedOwners.setOwner( proxyPerson );
|
||||||
accountNotAuditedOwners.setCoOwner( proxyPerson );
|
|
||||||
em.persist( accountNotAuditedOwners );
|
em.persist( accountNotAuditedOwners );
|
||||||
em.persist( noProxyPerson );
|
|
||||||
em.persist( proxyPerson );
|
em.persist( proxyPerson );
|
||||||
em.getTransaction().commit();
|
em.getTransaction().commit();
|
||||||
|
|
||||||
|
@ -74,7 +69,6 @@ public class OneToOneWithPrimaryKeyJoinTest extends BaseEnversJPAFunctionalTestC
|
||||||
accountId = account.getAccountId();
|
accountId = account.getAccountId();
|
||||||
accountNotAuditedOwnersId = accountNotAuditedOwners.getAccountId();
|
accountNotAuditedOwnersId = accountNotAuditedOwners.getAccountId();
|
||||||
proxyPersonId = proxyPerson.getPersonId();
|
proxyPersonId = proxyPerson.getPersonId();
|
||||||
noProxyPersonId = noProxyPerson.getPersonId();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -127,16 +121,13 @@ public class OneToOneWithPrimaryKeyJoinTest extends BaseEnversJPAFunctionalTestC
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testHistoryOfAccountNotAuditedOwners() {
|
public void testHistoryOfAccountNotAuditedOwners() {
|
||||||
NotAuditedNoProxyPerson noProxyPersonVer1 = new NotAuditedNoProxyPerson( noProxyPersonId, "Kinga" );
|
NotAuditedPerson proxyPersonVer1 = new NotAuditedPerson( proxyPersonId, "Lukasz" );
|
||||||
NotAuditedProxyPerson proxyPersonVer1 = new NotAuditedProxyPerson( proxyPersonId, "Lukasz" );
|
|
||||||
AccountNotAuditedOwners accountNotAuditedOwnersVer1 = new AccountNotAuditedOwners(
|
AccountNotAuditedOwners accountNotAuditedOwnersVer1 = new AccountNotAuditedOwners(
|
||||||
accountNotAuditedOwnersId,
|
accountNotAuditedOwnersId,
|
||||||
"Standard"
|
"Standard"
|
||||||
);
|
);
|
||||||
noProxyPersonVer1.setAccount( accountNotAuditedOwnersVer1 );
|
|
||||||
proxyPersonVer1.setAccount( accountNotAuditedOwnersVer1 );
|
proxyPersonVer1.setAccount( accountNotAuditedOwnersVer1 );
|
||||||
accountNotAuditedOwnersVer1.setOwner( noProxyPersonVer1 );
|
accountNotAuditedOwnersVer1.setOwner( proxyPersonVer1 );
|
||||||
accountNotAuditedOwnersVer1.setCoOwner( proxyPersonVer1 );
|
|
||||||
|
|
||||||
Object[] result = ((Object[]) getAuditReader().createQuery()
|
Object[] result = ((Object[]) getAuditReader().createQuery()
|
||||||
.forRevisionsOfEntity( AccountNotAuditedOwners.class, false, true )
|
.forRevisionsOfEntity( AccountNotAuditedOwners.class, false, true )
|
||||||
|
@ -146,13 +137,10 @@ public class OneToOneWithPrimaryKeyJoinTest extends BaseEnversJPAFunctionalTestC
|
||||||
|
|
||||||
Assert.assertEquals( accountNotAuditedOwnersVer1, result[0] );
|
Assert.assertEquals( accountNotAuditedOwnersVer1, result[0] );
|
||||||
Assert.assertEquals( RevisionType.ADD, result[2] );
|
Assert.assertEquals( RevisionType.ADD, result[2] );
|
||||||
// Checking non-proxy reference
|
Assert.assertTrue( ((AccountNotAuditedOwners) result[0]).getOwner() instanceof HibernateProxy );
|
||||||
Assert.assertEquals( accountNotAuditedOwnersVer1.getOwner(), ((AccountNotAuditedOwners) result[0]).getOwner() );
|
|
||||||
// Checking proxy reference
|
|
||||||
Assert.assertTrue( ((AccountNotAuditedOwners) result[0]).getCoOwner() instanceof HibernateProxy );
|
|
||||||
Assert.assertEquals(
|
Assert.assertEquals(
|
||||||
proxyPersonVer1.getPersonId(),
|
proxyPersonVer1.getPersonId(),
|
||||||
((AccountNotAuditedOwners) result[0]).getCoOwner().getPersonId()
|
((AccountNotAuditedOwners) result[0]).getOwner().getPersonId()
|
||||||
);
|
);
|
||||||
|
|
||||||
Assert.assertEquals(
|
Assert.assertEquals(
|
||||||
|
|
|
@ -115,6 +115,26 @@ String isDefault();
|
||||||
----
|
----
|
||||||
|
|
||||||
|
|
||||||
|
[[proxy-annotation]]
|
||||||
|
== Replace @Proxy
|
||||||
|
|
||||||
|
Applications will need to replace usages of the removed `@Proxy` annotation.
|
||||||
|
|
||||||
|
`@Proxy#proxyClass` has no direct replacement, but was also never needed/useful.
|
||||||
|
|
||||||
|
Here we focus on `@Proxy#laxy` attribute which, again, was hardly ever useful.
|
||||||
|
By default (true), Hibernate would proxy an entity when possible and when asked for.
|
||||||
|
"Asked for" includes calls to `Session#getReference` and lazy associations.
|
||||||
|
All such cases though are already controllable by the application.
|
||||||
|
|
||||||
|
* Instead of `Session#getReference`, use `Session#find`
|
||||||
|
* Use eager associations, using
|
||||||
|
** `FetchType.EAGER` (the default for to-one associations anyway), possibly combined with `@Fetch`
|
||||||
|
** `EntityGraph`
|
||||||
|
** `@FetchProfiles`
|
||||||
|
|
||||||
|
The effect can also often be mitigated using Hibernate's bytecode-based laziness (possibly combined with `@ConcreteProxy`).
|
||||||
|
|
||||||
|
|
||||||
[[flush-persist]]
|
[[flush-persist]]
|
||||||
== Session flush and persist
|
== Session flush and persist
|
||||||
|
|
Loading…
Reference in New Issue