HHH-11186 - Add examples for all Hibernate annotations

Document @Proxy annotation
This commit is contained in:
Vlad Mihalcea 2017-06-22 17:33:29 +03:00
parent 2353697a03
commit a53e11822b
4 changed files with 162 additions and 1 deletions

View File

@ -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`

View File

@ -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

View File

@ -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]

View File

@ -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[]
}