HHH-11186 - Add examples for all Hibernate annotations
Document @Proxy annotation
This commit is contained in:
parent
2353697a03
commit
a53e11822b
|
@ -1165,7 +1165,7 @@ See the <<chapters/domain/inheritance.adoc#entity-inheritance-polymorphism, `@Po
|
||||||
|
|
||||||
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.
|
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.
|
||||||
|
|
||||||
//TODO: Add example
|
See the <<chapters/domain/entity.adoc#entity-proxy, `@Proxy` mapping>> section for more info.
|
||||||
|
|
||||||
[[annotations-hibernate-rowid]]
|
[[annotations-hibernate-rowid]]
|
||||||
==== `@RowId`
|
==== `@RowId`
|
||||||
|
|
|
@ -317,6 +317,47 @@ The goal of the `@Synchronize` annotation in the `AccountSummary` entity mapping
|
||||||
underlying `@Subselect` SQL query. This way, when executing a HQL or JPQL which selects from the `AccountSummary` entity,
|
underlying `@Subselect` SQL query. This way, when executing a 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
|
||||||
|
http://jboss-javassist.github.io/javassist/[Javassist] or
|
||||||
|
http://bytebuddy.net/[Byte Buddy].
|
||||||
|
|
||||||
|
However, if the entity class is final, Javassist will not create a Proxy and 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.
|
||||||
|
|
||||||
|
[[entity-proxy-interface-mapping]]
|
||||||
|
.Final entity class implementing the `Identifiable` interface
|
||||||
|
====
|
||||||
|
[source,java]
|
||||||
|
----
|
||||||
|
include::{sourcedir-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 illustarted by the following example:
|
||||||
|
|
||||||
|
[[entity-proxy-persist-mapping]]
|
||||||
|
.Proxying the final entity class implementing the `Identifiable` interface
|
||||||
|
====
|
||||||
|
[source,java]
|
||||||
|
----
|
||||||
|
include::{sourcedir-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.
|
||||||
|
|
||||||
[[entity-tuplizer]]
|
[[entity-tuplizer]]
|
||||||
==== Dynamic entity proxies using the @Tuplizer annotation
|
==== Dynamic entity proxies using the @Tuplizer annotation
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
into
|
||||||
|
Book
|
||||||
|
(author, title, id)
|
||||||
|
values
|
||||||
|
(?, ?, ?)
|
||||||
|
|
||||||
|
-- binding parameter [1] as [VARCHAR] - [Vlad Mihalcea]
|
||||||
|
-- binding parameter [2] as [VARCHAR] - [High-Performance Java Persistence]
|
||||||
|
-- binding parameter [3] as [BIGINT] - [1]
|
|
@ -0,0 +1,111 @@
|
||||||
|
/*
|
||||||
|
* 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.userguide.proxy;
|
||||||
|
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.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",
|
||||||
|
Identifiable.class.isInstance( book )
|
||||||
|
);
|
||||||
|
assertFalse(
|
||||||
|
"Proxy class was not created",
|
||||||
|
Book.class.isInstance( 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[]
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue