Hibernate SVN: r18875 - core/trunk/entitymanager/src/main/docbook/en/modules.
by hibernate-commits@lists.jboss.org
Author: steve.ebersole(a)jboss.com
Date: 2010-02-24 16:40:58 -0500 (Wed, 24 Feb 2010)
New Revision: 18875
Modified:
core/trunk/entitymanager/src/main/docbook/en/modules/metamodel.xml
core/trunk/entitymanager/src/main/docbook/en/modules/query_criteria.xml
Log:
misc minor doc cleanups
Modified: core/trunk/entitymanager/src/main/docbook/en/modules/metamodel.xml
===================================================================
--- core/trunk/entitymanager/src/main/docbook/en/modules/metamodel.xml 2010-02-24 21:26:24 UTC (rev 18874)
+++ core/trunk/entitymanager/src/main/docbook/en/modules/metamodel.xml 2010-02-24 21:40:58 UTC (rev 18875)
@@ -23,8 +23,8 @@
~ Boston, MA 02110-1301 USA
-->
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
-<!ENTITY jpa2Biblio '<xref linkend="JPA2"/>'>
-<!ENTITY jpa2Cite '<citation>&jpa2Biblio;</citation>'>
+<!ENTITY jpa2Ref '<xref linkend="JPA2"/>'>
+<!ENTITY jpa2Cite '<citation>&jpa2Ref;</citation>'>
<!ENTITY criteriaRef '<xref linkend="querycriteria"/>'>
<!ENTITY apt '<ulink url="http://java.sun.com/javase/6/docs/technotes/tools/solaris/javac.html#proc...">annotation processor</ulink>'>
]>
@@ -43,20 +43,19 @@
<para>
The metamodel is a set of objects that describe your domain model.
<interfacename>javax.persistence.metamodel.Metamodel</interfacename> acts as a repository of these metamodel
- objects and provides access to them. We ask either the
+ objects and provides access to them, and can be obtained from either the
<interfacename>javax.persistence.EntityManagerFactory</interfacename> or the
- <interfacename>javax.persistence.EntityManager</interfacename> for a reference to the
- <interfacename>javax.persistence.metamodel.Metamodel</interfacename> via their
+ <interfacename>javax.persistence.EntityManager</interfacename> via their
<methodname>getMetamodel</methodname> method.
</para>
<para>
This metamodel is important in 2 ways. First, it allows providers and frameworks a generic way to
deal with an application's domain model. Persistence providers will already have some form of
- metamodel that they use to describe the domain model being mapped. This API simply allows general access
- to that existing information. A validation framework, for example, could use this information to
- understand associations; a marshaling framework might use this information to decide how much of an
- entity graph to marshal. This usage is beyond the scope of this documentation.
+ metamodel that they use to describe the domain model being mapped. This API however defines a single,
+ independent access to that existing information. A validation framework, for example, could use this
+ information to understand associations; a marshaling framework might use this information to decide how
+ much of an entity graph to marshal. This usage is beyond the scope of this documentation.
</para>
<important>
@@ -86,7 +85,7 @@
<blockquote>
<attribution>
- <citation><xref linkend="JPA2"/>, section 6.2.1.1, pp 198-199</citation>
+ <citation>&jpa2Ref;, section 6.2.1.1, pp 198-199</citation>
</attribution>
<para>
<itemizedlist>
@@ -233,7 +232,7 @@
When the Hibernate <interfacename>EntityManagerFactory</interfacename> is being built, it will
look for a canonical metamodel class for each of the managed typed is knows about and if it finds
any it will inject the appropriate metamodel information into them, as outlined in
- <citation><xref linkend="JPA2"/>, section 6.2.2, pg 200</citation>
+ <citation>&jpa2Ref;, section 6.2.2, pg 200</citation>
</para>
</section>
Modified: core/trunk/entitymanager/src/main/docbook/en/modules/query_criteria.xml
===================================================================
--- core/trunk/entitymanager/src/main/docbook/en/modules/query_criteria.xml 2010-02-24 21:26:24 UTC (rev 18874)
+++ core/trunk/entitymanager/src/main/docbook/en/modules/query_criteria.xml 2010-02-24 21:40:58 UTC (rev 18875)
@@ -22,7 +22,12 @@
~ 51 Franklin Street, Fifth Floor
~ Boston, MA 02110-1301 USA
-->
-<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" []>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+<!ENTITY jpa2Ref '<xref linkend="JPA2"/>'>
+<!ENTITY jpa2Cite '<citation>&jpa2Ref;</citation>'>
+<!ENTITY staticMetamodelRef '<xref linkend="metamodel-static"/>'>
+]>
+
<chapter id="querycriteria">
<title>Criteria Queries</title>
@@ -65,10 +70,10 @@
<note>
<para>
- <citetitle pubwork="chapter">Chapter 6 Criteria API</citetitle> of the
- <citation><xref linkend="JPA2"/></citation> already contains a decent amount of reference material
- pertaining to the various parts of a criteria query. So rather than duplicate all that content here,
- lets instead look at some of the more widely (anticipated) usages of the API.
+ <citetitle pubwork="chapter">Chapter 6 Criteria API</citetitle> of the &jpa2Cite; already contains a
+ decent amount of reference material pertaining to the various parts of a criteria query. So rather
+ than duplicate all that content here, lets instead look at some of the more widely anticipated usages
+ of the API.
</para>
</note>
@@ -124,7 +129,7 @@
<para>
<emphasis>Person_.eyeColor</emphasis> is an example of the static form of metamodel
reference. We will use that form exclusively in this chapter.
- See (todo link to metamodel section once written).
+ See &staticMetamodelRef; for details.
</para>
</callout>
</calloutlist>
@@ -486,7 +491,7 @@
<title>FROM clause</title>
<blockquote>
<attribution>
- <citation><xref linkend="JPA2"/></citation>
+ <citation>&jpa2Ref;, section 6.5.2 Query Roots, pg 262</citation>
</attribution>
<para>
A CriteriaQuery object defines a query over one or more entity, embeddable, or basic abstract
14 years, 9 months
Hibernate SVN: r18874 - in core/trunk/entitymanager/src/main/docbook/en: modules and 1 other directory.
by hibernate-commits@lists.jboss.org
Author: steve.ebersole(a)jboss.com
Date: 2010-02-24 16:26:24 -0500 (Wed, 24 Feb 2010)
New Revision: 18874
Added:
core/trunk/entitymanager/src/main/docbook/en/modules/metamodel.xml
Modified:
core/trunk/entitymanager/src/main/docbook/en/master.xml
Log:
HHH-4949 - Document JPA 2 metamodel
Modified: core/trunk/entitymanager/src/main/docbook/en/master.xml
===================================================================
--- core/trunk/entitymanager/src/main/docbook/en/master.xml 2010-02-24 21:20:26 UTC (rev 18873)
+++ core/trunk/entitymanager/src/main/docbook/en/master.xml 2010-02-24 21:26:24 UTC (rev 18874)
@@ -70,6 +70,7 @@
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="modules/architecture.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="modules/configuration.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="modules/entitymanagerapi.xml"/>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="modules/metamodel.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="modules/transactions.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="modules/listeners.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="modules/batch.xml"/>
Added: core/trunk/entitymanager/src/main/docbook/en/modules/metamodel.xml
===================================================================
--- core/trunk/entitymanager/src/main/docbook/en/modules/metamodel.xml (rev 0)
+++ core/trunk/entitymanager/src/main/docbook/en/modules/metamodel.xml 2010-02-24 21:26:24 UTC (rev 18874)
@@ -0,0 +1,240 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!--
+ ~ Hibernate, Relational Persistence for Idiomatic Java
+ ~
+ ~ Copyright (c) 2010, Red Hat Inc. or third-party contributors as
+ ~ indicated by the @author tags or express copyright attribution
+ ~ statements applied by the authors. All third-party contributions are
+ ~ distributed under license by Red Hat Inc.
+ ~
+ ~ This copyrighted material is made available to anyone wishing to use, modify,
+ ~ copy, or redistribute it subject to the terms and conditions of the GNU
+ ~ Lesser General Public License, as published by the Free Software Foundation.
+ ~
+ ~ This program is distributed in the hope that it will be useful,
+ ~ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ ~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ ~ for more details.
+ ~
+ ~ You should have received a copy of the GNU Lesser General Public License
+ ~ along with this distribution; if not, write to:
+ ~ Free Software Foundation, Inc.
+ ~ 51 Franklin Street, Fifth Floor
+ ~ Boston, MA 02110-1301 USA
+ -->
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+<!ENTITY jpa2Biblio '<xref linkend="JPA2"/>'>
+<!ENTITY jpa2Cite '<citation>&jpa2Biblio;</citation>'>
+<!ENTITY criteriaRef '<xref linkend="querycriteria"/>'>
+<!ENTITY apt '<ulink url="http://java.sun.com/javase/6/docs/technotes/tools/solaris/javac.html#proc...">annotation processor</ulink>'>
+]>
+
+<chapter id="metamodel">
+ <title>Metamodel</title>
+
+ <note>
+ <para>
+ The Metamodel itself is described in <citetitle pubwork="chapter">Chapter 5 Metamodel API</citetitle>
+ of the &jpa2Cite;. <citetitle pubwork="chapter">Chapter 6 Criteria API</citetitle> of the &jpa2Cite;
+ describes and shows uses of the metamodel in criteria queries, as does &criteriaRef;.
+ </para>
+ </note>
+
+ <para>
+ The metamodel is a set of objects that describe your domain model.
+ <interfacename>javax.persistence.metamodel.Metamodel</interfacename> acts as a repository of these metamodel
+ objects and provides access to them. We ask either the
+ <interfacename>javax.persistence.EntityManagerFactory</interfacename> or the
+ <interfacename>javax.persistence.EntityManager</interfacename> for a reference to the
+ <interfacename>javax.persistence.metamodel.Metamodel</interfacename> via their
+ <methodname>getMetamodel</methodname> method.
+ </para>
+
+ <para>
+ This metamodel is important in 2 ways. First, it allows providers and frameworks a generic way to
+ deal with an application's domain model. Persistence providers will already have some form of
+ metamodel that they use to describe the domain model being mapped. This API simply allows general access
+ to that existing information. A validation framework, for example, could use this information to
+ understand associations; a marshaling framework might use this information to decide how much of an
+ entity graph to marshal. This usage is beyond the scope of this documentation.
+ </para>
+
+ <important>
+ <para>
+ As of today the JPA 2 metamodel does not provide any facility for accessing relational information
+ pertaining to the physical model. It is expected this will be addressed in a future release of the
+ specification.
+ </para>
+ </important>
+
+ <para>
+ Second, from an application writer's perspective, it allows very fluent expression of completely type-safe
+ criteria queries, especially the <emphasis>Static Metamodel</emphasis> approach. The &jpa2Cite; defines a
+ number of ways the metamodel can be accessed and used, including the <emphasis>Static Metamodel</emphasis>
+ approach, which we will look at later. The <emphasis>Static Metamodel</emphasis> approach is wonderful
+ when the code has <ulink url="http://en.wikipedia.org/wiki/A_priori_and_a_posteriori">a priori knowledge</ulink>
+ of the domain model. &criteriaRef; uses this approach exclusively in its examples.
+ </para>
+
+ <section id="metamodel-static">
+ <title>Static metamodel</title>
+ <para>
+ A <emphasis>static metamodel</emphasis> is a series of classes that "mirror" the entities and embeddables
+ in the domain model and provide static access to the metadata about the mirrored class's attributes. We
+ will exclusively discuss what the &jpa2Cite; terms a <emphasis>Canonical Metamodel</emphasis>:
+ </para>
+
+ <blockquote>
+ <attribution>
+ <citation><xref linkend="JPA2"/>, section 6.2.1.1, pp 198-199</citation>
+ </attribution>
+ <para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ For each managed class <classname>X</classname> in package <package>p</package>,
+ a metamodel class <classname>X_</classname> in package <package>p</package> is created.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ The name of the metamodel class is derived from the name of the managed class by appending
+ "_" to the name of the managed class.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ The metamodel class <classname>X_</classname> must be annotated with the
+ <interfacename>javax.persistence.StaticMetamodel</interfacename>annotation
+ <footnote>
+ <para>
+ <emphasis>(from the original)</emphasis> If the class was generated, the
+ <interfacename>javax.annotation.Generated</interfacename> annotation should be
+ used to annotate the class. The use of any other annotations on static metamodel
+ classes is undefined.
+ </para>
+ </footnote>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ If class <classname>X</classname> extends another class <classname>S</classname>, where
+ <classname>S</classname> is the most derived managed class (i.e., entity or mapped
+ superclass) extended by <classname>X</classname>, then class <classname>X_</classname> must
+ extend class <classname>S_</classname>, where <classname>S_</classname> is the metamodel
+ class created for <classname>S</classname>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ For every persistent non-collection-valued attribute <emphasis>y</emphasis> declared by
+ class <classname>X</classname>, where the type of <emphasis>y</emphasis> is
+ <classname>Y</classname>, the metamodel class must contain a declaration as follows:
+ <programlisting><![CDATA[public static volatile SingularAttribute<X, Y> y;]]></programlisting>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ For every persistent collection-valued attribute <emphasis>z</emphasis> declared by class
+ <classname>X</classname>, where the element type of <emphasis>z</emphasis> is
+ <classname>Z</classname>, the metamodel class must contain a declaration as follows:
+ <itemizedlist>
+ <listitem>
+ <para>
+ if the collection type of <emphasis>z</emphasis> is
+ <interfacename>java.util.Collection</interfacename>, then
+ <programlisting><![CDATA[public static volatile CollectionAttribute<X, Z> z;]]></programlisting>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ if the collection type of <emphasis>z</emphasis> is
+ <interfacename>java.util.Set</interfacename>, then
+ <programlisting><![CDATA[public static volatile SetAttribute<X, Z> z;]]></programlisting>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ if the collection type of <emphasis>z</emphasis> is
+ <interfacename>java.util.List</interfacename>, then
+ <programlisting><![CDATA[public static volatile ListAttribute<X, Z> z;]]></programlisting>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ if the collection type of <emphasis>z</emphasis> is
+ <interfacename>java.util.Map</interfacename>, then
+ <programlisting><![CDATA[public static volatile MapAttribute<X, K, Z> z;]]></programlisting>
+ where <classname>K</classname> is the type of the key of the map in class
+ <classname>X</classname>
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+ <para>
+ Import statements must be included for the needed <package>javax.persistence.metamodel</package> types
+ as appropriate (e.g., <interfacename>javax.persistence.metamodel.SingularAttribute</interfacename>,
+ <interfacename>javax.persistence.metamodel.CollectionAttribute</interfacename>,
+ <interfacename>javax.persistence.metamodel.SetAttribute</interfacename>,
+ <interfacename>javax.persistence.metamodel.ListAttribute</interfacename>,
+ <interfacename>javax.persistence.metamodel.MapAttribute</interfacename>) and all classes
+ <classname>X</classname>, <classname>Y</classname>, <classname>Z</classname>, and <classname>K</classname>.
+ </para>
+ </blockquote>
+
+ <example id="metamodel-static-ex">
+ <title>Static metamodel example</title>
+ <para>
+ For the <classname>Person</classname> entity
+ <programlisting><![CDATA[package org.hibernate.jpa2.metamodel.example;
+
+import java.util.Set;
+import javax.persistence.Entity;
+
+@Entity
+public class Person {
+ @Id private Long id;
+ private String name;
+ private int age;
+ private Address address;
+ @OneToMany private Set<Order> orders;
+}]]></programlisting>
+ The corresponding canonical metamodel class, <classname>Person_</classname> would look like
+ <programlisting><![CDATA[package org.hibernate.jpa2.metamodel.example;
+
+import javax.persistence.metamodel.SingularAttribute;
+import javax.persistence.metamodel.SetAttribute;
+import javax.persistence.metamodel.StaticMetamodel;
+
+@StaticMetamodel( Person.class )
+public class Person_ {
+ public static volatile SingularAttribute<Person, Long> id;
+ public static volatile SingularAttribute<Person, String> name;
+ public static volatile SingularAttribute<Person, Integer> age;
+ public static volatile SingularAttribute<Person, Address> address;
+ public static volatile SetAttribute<Person, Order> orders;
+}]]></programlisting>
+ </para>
+ </example>
+
+ <note>
+ <para>
+ These canonical metamodel classes can be generated manually if you wish though it is expected
+ that most developers will prefer use of an &apt;. Although annotation processors themselves are
+ beyond the scope of this document, the Hibernate team does develop an annotation processor tool for
+ generating a canonical metamodel. See <citetitle>Hibernate Metamodel Generator</citetitle>.
+ </para>
+ </note>
+
+ <para>
+ When the Hibernate <interfacename>EntityManagerFactory</interfacename> is being built, it will
+ look for a canonical metamodel class for each of the managed typed is knows about and if it finds
+ any it will inject the appropriate metamodel information into them, as outlined in
+ <citation><xref linkend="JPA2"/>, section 6.2.2, pg 200</citation>
+ </para>
+ </section>
+
+</chapter>
\ No newline at end of file
14 years, 9 months
Hibernate SVN: r18873 - in core/trunk: core/src/main/java/org/hibernate/event/def and 1 other directories.
by hibernate-commits@lists.jboss.org
Author: gbadner
Date: 2010-02-24 16:20:26 -0500 (Wed, 24 Feb 2010)
New Revision: 18873
Modified:
core/trunk/core/src/main/java/org/hibernate/engine/EntityEntry.java
core/trunk/core/src/main/java/org/hibernate/event/def/AbstractReassociateEventListener.java
core/trunk/core/src/main/java/org/hibernate/event/def/AbstractSaveEventListener.java
core/trunk/core/src/main/java/org/hibernate/event/def/DefaultDeleteEventListener.java
core/trunk/core/src/main/java/org/hibernate/event/def/DefaultReplicateEventListener.java
core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/Contract.java
core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/ContractVariation.hbm.xml
core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/ContractVariation.java
core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/ImmutableTest.java
core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/Info.java
core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/Party.java
core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/Plan.java
Log:
HHH-4809 : Immutable entities added to a session have Status.MANAGED unless loaded by the Session
Modified: core/trunk/core/src/main/java/org/hibernate/engine/EntityEntry.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/engine/EntityEntry.java 2010-02-24 20:21:08 UTC (rev 18872)
+++ core/trunk/core/src/main/java/org/hibernate/engine/EntityEntry.java 2010-02-24 21:20:26 UTC (rev 18873)
@@ -309,6 +309,9 @@
loadedState = null;
}
else {
+ if ( ! persister.isMutable() ) {
+ throw new IllegalStateException( "Cannot make an immutable entity modifiable." );
+ }
setStatus( Status.MANAGED );
loadedState = getPersister().getPropertyValues( entity, entityMode );
}
Modified: core/trunk/core/src/main/java/org/hibernate/event/def/AbstractReassociateEventListener.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/event/def/AbstractReassociateEventListener.java 2010-02-24 20:21:08 UTC (rev 18872)
+++ core/trunk/core/src/main/java/org/hibernate/event/def/AbstractReassociateEventListener.java 2010-02-24 21:20:26 UTC (rev 18873)
@@ -88,7 +88,7 @@
EntityEntry newEntry = source.getPersistenceContext().addEntity(
object,
- Status.MANAGED,
+ ( persister.isMutable() ? Status.MANAGED : Status.READ_ONLY ),
values,
key,
version,
Modified: core/trunk/core/src/main/java/org/hibernate/event/def/AbstractSaveEventListener.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/event/def/AbstractSaveEventListener.java 2010-02-24 20:21:08 UTC (rev 18872)
+++ core/trunk/core/src/main/java/org/hibernate/event/def/AbstractSaveEventListener.java 2010-02-24 21:20:26 UTC (rev 18873)
@@ -333,7 +333,7 @@
Object version = Versioning.getVersion( values, persister );
source.getPersistenceContext().addEntity(
entity,
- Status.MANAGED,
+ ( persister.isMutable() ? Status.MANAGED : Status.READ_ONLY ),
values,
key,
version,
Modified: core/trunk/core/src/main/java/org/hibernate/event/def/DefaultDeleteEventListener.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/event/def/DefaultDeleteEventListener.java 2010-02-24 20:21:08 UTC (rev 18872)
+++ core/trunk/core/src/main/java/org/hibernate/event/def/DefaultDeleteEventListener.java 2010-02-24 21:20:26 UTC (rev 18873)
@@ -126,7 +126,7 @@
entityEntry = persistenceContext.addEntity(
entity,
- Status.MANAGED,
+ ( persister.isMutable() ? Status.MANAGED : Status.READ_ONLY ),
persister.getPropertyValues( entity, source.getEntityMode() ),
key,
version,
Modified: core/trunk/core/src/main/java/org/hibernate/event/def/DefaultReplicateEventListener.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/event/def/DefaultReplicateEventListener.java 2010-02-24 20:21:08 UTC (rev 18872)
+++ core/trunk/core/src/main/java/org/hibernate/event/def/DefaultReplicateEventListener.java 2010-02-24 21:20:26 UTC (rev 18873)
@@ -194,7 +194,7 @@
source.getPersistenceContext().addEntity(
entity,
- Status.MANAGED,
+ ( persister.isMutable() ? Status.MANAGED : Status.READ_ONLY ),
null,
new EntityKey( id, persister, source.getEntityMode() ),
version,
Modified: core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/Contract.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/Contract.java 2010-02-24 20:21:08 UTC (rev 18872)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/Contract.java 2010-02-24 21:20:26 UTC (rev 18873)
@@ -124,9 +124,4 @@
public void setInfos(Set infos) {
this.infos = infos;
}
-
- public void addInfo(Info info) {
- infos.add( info );
- info.setContract( this );
- }
}
Modified: core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/ContractVariation.hbm.xml
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/ContractVariation.hbm.xml 2010-02-24 20:21:08 UTC (rev 18872)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/ContractVariation.hbm.xml 2010-02-24 21:20:26 UTC (rev 18873)
@@ -15,7 +15,6 @@
<generator class="increment"/>
</id>
<property name="text"/>
- <many-to-one name="contract" not-null="false"/>
</class>
<class name="Plan" mutable="false">
@@ -27,6 +26,10 @@
<key column="plan"/>
<many-to-many column="contract" class="Contract"/>
</set>
+ <set name="infos" inverse="false" mutable="true" cascade="all-delete-orphan">
+ <key column="plan"/>
+ <one-to-many class="Info"/>
+ </set>
</class>
<class name="Party" mutable="false">
@@ -36,6 +39,10 @@
<!-- <many-to-one name="contract" update="false" insert="false"/> -->
<many-to-one name="contract" not-null="true"/>
<property name="name" not-null="true"/>
+ <set name="infos" inverse="false" mutable="true" cascade="all-delete-orphan">
+ <key column="party"/>
+ <one-to-many class="Info"/>
+ </set>
</class>
<class name="Contract" mutable="false">
@@ -64,7 +71,7 @@
<key column="contract"/>
<one-to-many class="Party"/>
</set>
- <set name="infos" inverse="true" mutable="true" cascade="all" fetch="join">
+ <set name="infos" inverse="false" mutable="true" cascade="all-delete-orphan">
<key column="contract"/>
<one-to-many class="Info"/>
</set>
@@ -76,6 +83,13 @@
<key-property name="version"/>
</composite-id>
<property name="text" type="text"/>
+ <set name="infos" inverse="false" mutable="true" cascade="all-delete-orphan">
+ <key>
+ <column name="contract"/>
+ <column name="version"/>
+ </key>
+ <one-to-many class="Info"/>
+ </set>
</class>
</hibernate-mapping>
Modified: core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/ContractVariation.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/ContractVariation.java 2010-02-24 20:21:08 UTC (rev 18872)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/ContractVariation.java 2010-02-24 21:20:26 UTC (rev 18873)
@@ -2,12 +2,15 @@
package org.hibernate.test.immutable;
import java.io.Serializable;
+import java.util.HashSet;
+import java.util.Set;
public class ContractVariation implements Serializable {
private int version;
private Contract contract;
private String text;
+ private Set infos = new HashSet();
public Contract getContract() {
return contract;
@@ -42,4 +45,12 @@
this.version = version;
contract.getVariations().add(this);
}
+
+ public Set getInfos() {
+ return infos;
+ }
+
+ public void setInfos(Set infos) {
+ this.infos = infos;
+ }
}
Modified: core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/ImmutableTest.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/ImmutableTest.java 2010-02-24 20:21:08 UTC (rev 18872)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/ImmutableTest.java 2010-02-24 21:20:26 UTC (rev 18873)
@@ -38,6 +38,7 @@
import org.hibernate.criterion.Projections;
import org.hibernate.junit.functional.FunctionalTestCase;
import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
+import org.hibernate.proxy.HibernateProxy;
/**
* @author Gavin King
@@ -61,6 +62,126 @@
return new FunctionalTestClassTestSuite( ImmutableTest.class );
}
+ public void testChangeImmutableEntityProxyToModifiable() {
+ Contract c = new Contract( null, "gavin", "phone");
+ ContractVariation cv1 = new ContractVariation(1, c);
+ cv1.setText("expensive");
+ ContractVariation cv2 = new ContractVariation(2, c);
+ cv2.setText("more expensive");
+
+ clearCounts();
+
+ Session s = openSession();
+ Transaction t = s.beginTransaction();
+ s.persist(c);
+ assertTrue( s.isReadOnly( c ) );
+ assertTrue( s.isReadOnly( cv1 ) );
+ assertTrue( s.isReadOnly( cv2 ) );
+ t.commit();
+ s.close();
+
+ assertInsertCount( 3 );
+ assertUpdateCount( 0 );
+ clearCounts();
+
+ s = openSession();
+ t = s.beginTransaction();
+ c = (Contract) s.createCriteria(Contract.class).uniqueResult();
+ assertTrue( s.isReadOnly( c ) );
+ assertEquals( c.getCustomerName(), "gavin" );
+ assertEquals( c.getVariations().size(), 2 );
+ Iterator it = c.getVariations().iterator();
+ cv1 = (ContractVariation) it.next();
+ assertEquals( cv1.getText(), "expensive" );
+ cv2 = (ContractVariation) it.next();
+ assertEquals( cv2.getText(), "more expensive" );
+ assertTrue( s.isReadOnly( cv1 ) );
+ assertTrue( s.isReadOnly( cv2 ) );
+
+ try {
+ assertTrue( c instanceof HibernateProxy );
+ s.setReadOnly( c, false );
+ }
+ catch (IllegalStateException ex) {
+ // expected
+ }
+ finally {
+ t.rollback();
+ s.close();
+ }
+
+ s = openSession();
+ t = s.beginTransaction();
+ s.delete(c);
+ assertEquals( s.createCriteria(Contract.class).setProjection( Projections.rowCount() ).uniqueResult(), new Long(0) );
+ assertEquals( s.createCriteria(ContractVariation.class).setProjection( Projections.rowCount() ).uniqueResult(), new Long(0) );
+ t.commit();
+ s.close();
+
+ assertUpdateCount( 0 );
+ assertDeleteCount( 3 );
+ }
+
+ public void testChangeImmutableEntityToModifiable() {
+ Contract c = new Contract( null, "gavin", "phone");
+ ContractVariation cv1 = new ContractVariation(1, c);
+ cv1.setText("expensive");
+ ContractVariation cv2 = new ContractVariation(2, c);
+ cv2.setText("more expensive");
+
+ clearCounts();
+
+ Session s = openSession();
+ Transaction t = s.beginTransaction();
+ s.persist(c);
+ assertTrue( s.isReadOnly( c ) );
+ assertTrue( s.isReadOnly( cv1 ) );
+ assertTrue( s.isReadOnly( cv2 ) );
+ t.commit();
+ s.close();
+
+ assertInsertCount( 3 );
+ assertUpdateCount( 0 );
+ clearCounts();
+
+ s = openSession();
+ t = s.beginTransaction();
+ c = (Contract) s.createCriteria(Contract.class).uniqueResult();
+ assertTrue( s.isReadOnly( c ) );
+ assertEquals( c.getCustomerName(), "gavin" );
+ assertEquals( c.getVariations().size(), 2 );
+ Iterator it = c.getVariations().iterator();
+ cv1 = (ContractVariation) it.next();
+ assertEquals( cv1.getText(), "expensive" );
+ cv2 = (ContractVariation) it.next();
+ assertEquals( cv2.getText(), "more expensive" );
+ assertTrue( s.isReadOnly( cv1 ) );
+ assertTrue( s.isReadOnly( cv2 ) );
+
+ try {
+ assertTrue( c instanceof HibernateProxy );
+ s.setReadOnly( ( ( HibernateProxy ) c ).getHibernateLazyInitializer().getImplementation(), false );
+ }
+ catch (IllegalStateException ex) {
+ // expected
+ }
+ finally {
+ t.rollback();
+ s.close();
+ }
+
+ s = openSession();
+ t = s.beginTransaction();
+ s.delete(c);
+ assertEquals( s.createCriteria(Contract.class).setProjection( Projections.rowCount() ).uniqueResult(), new Long(0) );
+ assertEquals( s.createCriteria(ContractVariation.class).setProjection( Projections.rowCount() ).uniqueResult(), new Long(0) );
+ t.commit();
+ s.close();
+
+ assertUpdateCount( 0 );
+ assertDeleteCount( 3 );
+ }
+
public void testPersistImmutable() {
Contract c = new Contract( null, "gavin", "phone");
ContractVariation cv1 = new ContractVariation(1, c);
@@ -73,10 +194,9 @@
Session s = openSession();
Transaction t = s.beginTransaction();
s.persist(c);
- // c, cv1, and cv2 were added to s by s.persist(c) (not hibernate), so they are modifiable
- assertFalse( s.isReadOnly( c ) );
- assertFalse( s.isReadOnly( cv1 ) );
- assertFalse( s.isReadOnly( cv2 ) );
+ assertTrue( s.isReadOnly( c ) );
+ assertTrue( s.isReadOnly( cv1 ) );
+ assertTrue( s.isReadOnly( cv2 ) );
t.commit();
s.close();
@@ -87,7 +207,6 @@
s = openSession();
t = s.beginTransaction();
c = (Contract) s.createCriteria(Contract.class).uniqueResult();
- // c was loaded into s by hibernate, so it should be read-only
assertTrue( s.isReadOnly( c ) );
assertEquals( c.getCustomerName(), "gavin" );
assertEquals( c.getVariations().size(), 2 );
@@ -96,7 +215,6 @@
assertEquals( cv1.getText(), "expensive" );
cv2 = (ContractVariation) it.next();
assertEquals( cv2.getText(), "more expensive" );
- // cv1 and cv2 were loaded into s by hibernate, so they should be read-only
assertTrue( s.isReadOnly( cv1 ) );
assertTrue( s.isReadOnly( cv2 ) );
s.delete(c);
@@ -121,10 +239,9 @@
Session s = openSession();
Transaction t = s.beginTransaction();
s.persist(c);
- // c, cv1, and cv2 were added to s by s.persist(c) (not hibernate), so they are modifiable
- assertFalse( s.isReadOnly( c ) );
- assertFalse( s.isReadOnly( cv1 ) );
- assertFalse( s.isReadOnly( cv2 ) );
+ assertTrue( s.isReadOnly( c ) );
+ assertTrue( s.isReadOnly( cv1 ) );
+ assertTrue( s.isReadOnly( cv2 ) );
c.setCustomerName( "gail" );
t.commit();
s.close();
@@ -136,7 +253,6 @@
s = openSession();
t = s.beginTransaction();
c = (Contract) s.createCriteria(Contract.class).uniqueResult();
- // c was loaded into s by hibernate, so it should be read-only
assertTrue( s.isReadOnly( c ) );
assertEquals( c.getCustomerName(), "gavin" );
assertEquals( c.getVariations().size(), 2 );
@@ -145,7 +261,6 @@
assertEquals( cv1.getText(), "expensive" );
cv2 = (ContractVariation) it.next();
assertEquals( cv2.getText(), "more expensive" );
- // cv1 and cv2 were loaded into s by hibernate, so they should be read-only
assertTrue( s.isReadOnly( cv1 ) );
assertTrue( s.isReadOnly( cv2 ) );
s.delete(c);
@@ -169,10 +284,9 @@
Session s = openSession();
Transaction t = s.beginTransaction();
s.save(c);
- // c, cv1, and cv2 were added to s by s.persist(c) (not hibernate), so they are modifiable
- assertFalse( s.isReadOnly( c ) );
- assertFalse( s.isReadOnly( cv1 ) );
- assertFalse( s.isReadOnly( cv2 ) );
+ assertTrue( s.isReadOnly( c ) );
+ assertTrue( s.isReadOnly( cv1 ) );
+ assertTrue( s.isReadOnly( cv2 ) );
t.commit();
s.close();
@@ -183,7 +297,6 @@
s = openSession();
t = s.beginTransaction();
c = (Contract) s.createCriteria(Contract.class).uniqueResult();
- // c was loaded into s by hibernate, so it should be read-only
assertTrue( s.isReadOnly( c ) );
assertEquals( c.getCustomerName(), "gavin" );
assertEquals( c.getVariations().size(), 2 );
@@ -192,7 +305,6 @@
assertEquals( cv1.getText(), "expensive" );
cv2 = (ContractVariation) it.next();
assertEquals( cv2.getText(), "more expensive" );
- // cv1 and cv2 were loaded into s by hibernate, so they should be read-only
assertTrue( s.isReadOnly( cv1 ) );
assertTrue( s.isReadOnly( cv2 ) );
s.delete(c);
@@ -216,10 +328,9 @@
Session s = openSession();
Transaction t = s.beginTransaction();
s.saveOrUpdate(c);
- // c, cv1, and cv2 were added to s by s.persist(c) (not hibernate), so they are modifiable
- assertFalse( s.isReadOnly( c ) );
- assertFalse( s.isReadOnly( cv1 ) );
- assertFalse( s.isReadOnly( cv2 ) );
+ assertTrue( s.isReadOnly( c ) );
+ assertTrue( s.isReadOnly( cv1 ) );
+ assertTrue( s.isReadOnly( cv2 ) );
t.commit();
s.close();
@@ -230,7 +341,6 @@
s = openSession();
t = s.beginTransaction();
c = (Contract) s.createCriteria(Contract.class).uniqueResult();
- // c was loaded into s by hibernate, so it should be read-only
assertTrue( s.isReadOnly( c ) );
assertEquals( c.getCustomerName(), "gavin" );
assertEquals( c.getVariations().size(), 2 );
@@ -239,7 +349,6 @@
assertEquals( cv1.getText(), "expensive" );
cv2 = (ContractVariation) it.next();
assertEquals( cv2.getText(), "more expensive" );
- // cv1 and cv2 were loaded into s by hibernate, so they should be read-only
assertTrue( s.isReadOnly( cv1 ) );
assertTrue( s.isReadOnly( cv2 ) );
s.delete(c);
@@ -263,10 +372,9 @@
Session s = openSession();
Transaction t = s.beginTransaction();
s.persist(c);
- // c, cv1, and cv2 were added to s by s.persist(c) (not hibernate), so they are modifiable
- assertFalse( s.isReadOnly( c ) );
- assertFalse( s.isReadOnly( cv1 ) );
- assertFalse( s.isReadOnly( cv2 ) );
+ assertTrue( s.isReadOnly( c ) );
+ assertTrue( s.isReadOnly( cv1 ) );
+ assertTrue( s.isReadOnly( cv2 ) );
t.commit();
s.close();
@@ -277,12 +385,10 @@
s = openSession();
t = s.beginTransaction();
c = (Contract) s.createCriteria(Contract.class).uniqueResult();
- // c was loaded into s, so it should be read-only
assertTrue( s.isReadOnly( c ) );
c.setCustomerName("foo bar");
cv1 = (ContractVariation) c.getVariations().iterator().next();
cv1.setText("blah blah");
- // cv1 and cv2 were loaded into s by hibernate, so they should be read-only
assertTrue( s.isReadOnly( cv1 ) );
assertFalse( s.contains( cv2 ) );
t.commit();
@@ -298,7 +404,6 @@
s = openSession();
t = s.beginTransaction();
c = (Contract) s.createCriteria(Contract.class).uniqueResult();
- // c was loaded into s by hibernate, so it should be read-only
assertTrue( s.isReadOnly( c ) );
assertEquals( c.getCustomerName(), "gavin" );
assertEquals( c.getVariations().size(), 2 );
@@ -307,7 +412,6 @@
assertEquals( cv1.getText(), "expensive" );
cv2 = (ContractVariation) it.next();
assertEquals( cv2.getText(), "more expensive" );
- // cv1 and cv2 were loaded into s by hibernate, so they should be read-only
assertTrue( s.isReadOnly( cv1 ) );
assertTrue( s.isReadOnly( cv2 ) );
s.delete(c);
@@ -331,10 +435,9 @@
Session s = openSession();
Transaction t = s.beginTransaction();
s.persist(c);
- // c, cv1, and cv2 were added to s by s.persist(c) (not hibernate), so they are modifiable
- assertFalse( s.isReadOnly( c ) );
- assertFalse( s.isReadOnly( cv1 ) );
- assertFalse( s.isReadOnly( cv2 ) );
+ assertTrue( s.isReadOnly( c ) );
+ assertTrue( s.isReadOnly( cv1 ) );
+ assertTrue( s.isReadOnly( cv2 ) );
c.setCustomerName( "Sherman" );
t.commit();
s.close();
@@ -346,12 +449,10 @@
s = openSession();
t = s.beginTransaction();
c = (Contract) s.createCriteria(Contract.class).uniqueResult();
- // c was loaded into s, so it should be read-only
assertTrue( s.isReadOnly( c ) );
c.setCustomerName("foo bar");
cv1 = (ContractVariation) c.getVariations().iterator().next();
cv1.setText("blah blah");
- // cv1 and cv2 were loaded into s by hibernate, so they should be read-only
assertTrue( s.isReadOnly( cv1 ) );
assertFalse( s.contains( cv2 ) );
t.commit();
@@ -367,7 +468,6 @@
s = openSession();
t = s.beginTransaction();
c = (Contract) s.createCriteria(Contract.class).uniqueResult();
- // c was loaded into s by hibernate, so it should be read-only
assertTrue( s.isReadOnly( c ) );
assertEquals( c.getCustomerName(), "gavin" );
assertEquals( c.getVariations().size(), 2 );
@@ -376,7 +476,6 @@
assertEquals( cv1.getText(), "expensive" );
cv2 = (ContractVariation) it.next();
assertEquals( cv2.getText(), "more expensive" );
- // cv1 and cv2 were loaded into s by hibernate, so they should be read-only
assertTrue( s.isReadOnly( cv1 ) );
assertTrue( s.isReadOnly( cv2 ) );
s.delete(c);
@@ -410,7 +509,6 @@
s = openSession();
t = s.beginTransaction();
c = (Contract) s.createCriteria(Contract.class).uniqueResult();
- // c was loaded into s by hibernate, so it should be read-only
assertTrue( s.isReadOnly( c ) );
assertEquals( c.getCustomerName(), "gavin" );
assertEquals( c.getVariations().size(), 2 );
@@ -419,7 +517,6 @@
assertEquals( cv1.getText(), "expensive" );
cv2 = (ContractVariation) it.next();
assertEquals( cv2.getText(), "more expensive" );
- // cv1 and cv2 were loaded into s by hibernate, so they should be read-only
assertTrue( s.isReadOnly( cv1 ) );
assertTrue( s.isReadOnly( cv2 ) );
c.setCustomerName( "Sherman" );
@@ -454,7 +551,6 @@
s = openSession();
t = s.beginTransaction();
c = (Contract) s.get( Contract.class, c.getId() );
- // c was loaded into s by hibernate, so it should be read-only
assertTrue( s.isReadOnly( c ) );
assertEquals( c.getCustomerName(), "gavin" );
assertEquals( c.getVariations().size(), 2 );
@@ -463,7 +559,6 @@
assertEquals( cv1.getText(), "expensive" );
cv2 = (ContractVariation) it.next();
assertEquals( cv2.getText(), "more expensive" );
- // cv1 and cv2 were loaded into s by hibernate, so they should be read-only
assertTrue( s.isReadOnly( cv1 ) );
assertTrue( s.isReadOnly( cv2 ) );
c.setCustomerName( "Sherman" );
@@ -559,15 +654,17 @@
t = s.beginTransaction();
c.setCustomerName("foo bar");
s.update( c );
- // c was not loaded into s by hibernate, so it should be modifiable
- assertFalse( s.isReadOnly( c ) );
- assertFalse( s.contains( cv1 ) );
- assertFalse( s.contains( cv2 ) );
+ assertTrue( s.isReadOnly( c ) );
+ for ( Iterator it = c.getVariations().iterator(); it.hasNext(); ) {
+ assertTrue( s.contains( it.next() ) );
+ }
t.commit();
- // c, cv1, and cv2 were not loaded into s by hibernate, so they are modifiable
- assertFalse( s.isReadOnly( c ) );
- assertFalse( s.isReadOnly( cv1 ) );
- assertFalse( s.isReadOnly( cv2 ) );
+ assertTrue( s.isReadOnly( c ) );
+ for ( Iterator it = c.getVariations().iterator(); it.hasNext(); ) {
+ ContractVariation cv = ( ContractVariation ) it.next();
+ assertTrue( s.contains( cv ) );
+ assertTrue( s.isReadOnly( cv ) );
+ }
s.close();
assertUpdateCount( 0 );
@@ -615,14 +712,13 @@
cv1 = (ContractVariation) c.getVariations().iterator().next();
cv1.setText("blah blah");
s.update( c );
- // c was not loaded into s by hibernate, so it should be modifiable
- assertFalse( s.isReadOnly( c ) );
- assertFalse( s.contains( cv1 ) );
- assertFalse( s.contains( cv2 ) );
+ assertTrue( s.isReadOnly( c ) );
+ assertTrue( s.contains( cv1 ) );
+ assertTrue( s.contains( cv2 ) );
t.commit();
- assertFalse( s.isReadOnly( c ) );
- assertFalse( s.isReadOnly( cv1 ) );
- assertFalse( s.isReadOnly( cv2 ) );
+ assertTrue( s.isReadOnly( c ) );
+ assertTrue( s.isReadOnly( cv1 ) );
+ assertTrue( s.isReadOnly( cv2 ) );
s.close();
assertUpdateCount( 0 );
@@ -667,8 +763,9 @@
s = openSession();
t = s.beginTransaction();
c.getVariations().add( new ContractVariation(3, c) );
+ s.update( c );
try {
- s.update( c );
+ t.commit();
fail( "should have failed because reassociated object has a dirty collection");
}
catch ( HibernateException ex ) {
@@ -722,13 +819,11 @@
s = openSession();
t = s.beginTransaction();
c = ( Contract ) s.merge( c );
- // c was loaded into s by hibernate in the merge process, so it is read-only
assertTrue( s.isReadOnly( c ) );
assertTrue( Hibernate.isInitialized( c.getVariations() ) );
Iterator it = c.getVariations().iterator();
cv1 = (ContractVariation) it.next();
cv2 = (ContractVariation) it.next();
- // cv1 and cv2 were loaded into s by hibernate in the merge process, so they are read-only
assertTrue( s.isReadOnly( cv1 ) );
assertTrue( s.isReadOnly( cv2 ) );
t.commit();
@@ -778,13 +873,11 @@
t = s.beginTransaction();
c.setCustomerName("foo bar");
c = ( Contract ) s.merge( c );
- // c was loaded into s by hibernate in the merge process, so it is read-only
assertTrue( s.isReadOnly( c ) );
assertTrue( Hibernate.isInitialized( c.getVariations() ) );
Iterator it = c.getVariations().iterator();
cv1 = (ContractVariation) it.next();
cv2 = (ContractVariation) it.next();
- // cv1 and cv2 were loaded into s by hibernate in the merge process, so they are read-only
assertTrue( s.isReadOnly( c ) );
assertTrue( s.isReadOnly( c ) );
t.commit();
@@ -836,13 +929,11 @@
cv1 = (ContractVariation) c.getVariations().iterator().next();
cv1.setText("blah blah");
c = ( Contract ) s.merge( c );
- // c was loaded into s by hibernate in the merge process, so it is read-only
assertTrue( s.isReadOnly( c ) );
assertTrue( Hibernate.isInitialized( c.getVariations() ) );
Iterator it = c.getVariations().iterator();
cv1 = (ContractVariation) it.next();
cv2 = (ContractVariation) it.next();
- // cv1 and cv2 were loaded into s by hibernate in the merge process, so they are read-only
assertTrue( s.isReadOnly( c ) );
assertTrue( s.isReadOnly( c ) );
t.commit();
@@ -925,6 +1016,212 @@
assertDeleteCount( 3 );
}
+ public void testNewEntityViaImmutableEntityWithImmutableCollectionUsingSaveOrUpdate() {
+ clearCounts();
+
+ Contract c = new Contract( null, "gavin", "phone");
+ ContractVariation cv1 = new ContractVariation(1, c);
+ cv1.setText("expensive");
+ ContractVariation cv2 = new ContractVariation(2, c);
+ cv2.setText("more expensive");
+ Session s = openSession();
+ Transaction t = s.beginTransaction();
+ s.persist(c);
+ t.commit();
+ s.close();
+
+ assertInsertCount( 3 );
+ assertUpdateCount( 0 );
+ clearCounts();
+
+ s = openSession();
+ t = s.beginTransaction();
+ cv1.getInfos().add( new Info( "cv1 info" ) );
+ s.saveOrUpdate( c );
+ t.commit();
+ s.close();
+
+ assertInsertCount( 1 );
+ assertUpdateCount( 0 );
+
+ s = openSession();
+ t = s.beginTransaction();
+ c = (Contract) s.createCriteria(Contract.class).uniqueResult();
+ assertEquals( c.getCustomerName(), "gavin" );
+ assertEquals( c.getVariations().size(), 2 );
+ Iterator it = c.getVariations().iterator();
+ cv1 = (ContractVariation) it.next();
+ assertEquals( cv1.getText(), "expensive" );
+ assertEquals( 1, cv1.getInfos().size() );
+ assertEquals( "cv1 info", ( ( Info ) cv1.getInfos().iterator().next() ).getText() );
+ cv2 = (ContractVariation) it.next();
+ assertEquals( cv2.getText(), "more expensive" );
+ s.delete(c);
+ assertEquals( s.createCriteria(Contract.class).setProjection( Projections.rowCount() ).uniqueResult(), new Long(0) );
+ assertEquals( s.createCriteria(ContractVariation.class).setProjection( Projections.rowCount() ).uniqueResult(), new Long(0) );
+ t.commit();
+ s.close();
+
+ assertUpdateCount( 0 );
+ assertDeleteCount( 4 );
+ }
+
+ public void testNewEntityViaImmutableEntityWithImmutableCollectionUsingMerge() {
+ clearCounts();
+
+ Contract c = new Contract( null, "gavin", "phone");
+ ContractVariation cv1 = new ContractVariation(1, c);
+ cv1.setText("expensive");
+ ContractVariation cv2 = new ContractVariation(2, c);
+ cv2.setText("more expensive");
+ Session s = openSession();
+ Transaction t = s.beginTransaction();
+ s.persist(c);
+ t.commit();
+ s.close();
+
+ assertInsertCount( 3 );
+ assertUpdateCount( 0 );
+ clearCounts();
+
+ s = openSession();
+ t = s.beginTransaction();
+ cv1.getInfos().add( new Info( "cv1 info" ) );
+ s.merge( c );
+ t.commit();
+ s.close();
+
+ assertInsertCount( 1 );
+ assertUpdateCount( 0 );
+
+ s = openSession();
+ t = s.beginTransaction();
+ c = (Contract) s.createCriteria(Contract.class).uniqueResult();
+ assertEquals( c.getCustomerName(), "gavin" );
+ assertEquals( c.getVariations().size(), 2 );
+ Iterator it = c.getVariations().iterator();
+ cv1 = (ContractVariation) it.next();
+ assertEquals( cv1.getText(), "expensive" );
+ assertEquals( 1, cv1.getInfos().size() );
+ assertEquals( "cv1 info", ( ( Info ) cv1.getInfos().iterator().next() ).getText() );
+ cv2 = (ContractVariation) it.next();
+ assertEquals( cv2.getText(), "more expensive" );
+ s.delete(c);
+ assertEquals( s.createCriteria(Contract.class).setProjection( Projections.rowCount() ).uniqueResult(), new Long(0) );
+ assertEquals( s.createCriteria(ContractVariation.class).setProjection( Projections.rowCount() ).uniqueResult(), new Long(0) );
+ t.commit();
+ s.close();
+
+ assertUpdateCount( 0 );
+ assertDeleteCount( 4 );
+ }
+
+ public void testUpdatedEntityViaImmutableEntityWithImmutableCollectionUsingSaveOrUpdate() {
+ clearCounts();
+
+ Contract c = new Contract( null, "gavin", "phone");
+ ContractVariation cv1 = new ContractVariation(1, c);
+ cv1.setText("expensive");
+ Info cv1Info = new Info( "cv1 info" );
+ cv1.getInfos().add( cv1Info );
+ ContractVariation cv2 = new ContractVariation(2, c);
+ cv2.setText("more expensive");
+ Session s = openSession();
+ Transaction t = s.beginTransaction();
+ s.persist(c);
+ t.commit();
+ s.close();
+
+ assertInsertCount( 4 );
+ assertUpdateCount( 0 );
+ clearCounts();
+
+ s = openSession();
+ t = s.beginTransaction();
+ cv1Info.setText( "new cv1 info" );
+ s.saveOrUpdate( c );
+ t.commit();
+ s.close();
+
+ assertInsertCount( 0 );
+ assertUpdateCount( 1 );
+ clearCounts();
+
+ s = openSession();
+ t = s.beginTransaction();
+ c = (Contract) s.createCriteria(Contract.class).uniqueResult();
+ assertEquals( c.getCustomerName(), "gavin" );
+ assertEquals( c.getVariations().size(), 2 );
+ Iterator it = c.getVariations().iterator();
+ cv1 = (ContractVariation) it.next();
+ assertEquals( cv1.getText(), "expensive" );
+ assertEquals( 1, cv1.getInfos().size() );
+ assertEquals( "new cv1 info", ( ( Info ) cv1.getInfos().iterator().next() ).getText() );
+ cv2 = (ContractVariation) it.next();
+ assertEquals( cv2.getText(), "more expensive" );
+ s.delete(c);
+ assertEquals( s.createCriteria(Contract.class).setProjection( Projections.rowCount() ).uniqueResult(), new Long(0) );
+ assertEquals( s.createCriteria(ContractVariation.class).setProjection( Projections.rowCount() ).uniqueResult(), new Long(0) );
+ t.commit();
+ s.close();
+
+ assertUpdateCount( 0 );
+ assertDeleteCount( 4 );
+ }
+
+ public void testUpdatedEntityViaImmutableEntityWithImmutableCollectionUsingMerge() {
+ clearCounts();
+
+ Contract c = new Contract( null, "gavin", "phone");
+ ContractVariation cv1 = new ContractVariation(1, c);
+ cv1.setText("expensive");
+ Info cv1Info = new Info( "cv1 info" );
+ cv1.getInfos().add( cv1Info );
+ ContractVariation cv2 = new ContractVariation(2, c);
+ cv2.setText("more expensive");
+ Session s = openSession();
+ Transaction t = s.beginTransaction();
+ s.persist(c);
+ t.commit();
+ s.close();
+
+ assertInsertCount( 4 );
+ assertUpdateCount( 0 );
+ clearCounts();
+
+ s = openSession();
+ t = s.beginTransaction();
+ cv1Info.setText( "new cv1 info" );
+ s.merge( c );
+ t.commit();
+ s.close();
+
+ assertInsertCount( 0 );
+ assertUpdateCount( 1 );
+ clearCounts();
+
+ s = openSession();
+ t = s.beginTransaction();
+ c = (Contract) s.createCriteria(Contract.class).uniqueResult();
+ assertEquals( c.getCustomerName(), "gavin" );
+ assertEquals( c.getVariations().size(), 2 );
+ Iterator it = c.getVariations().iterator();
+ cv1 = (ContractVariation) it.next();
+ assertEquals( cv1.getText(), "expensive" );
+ assertEquals( 1, cv1.getInfos().size() );
+ assertEquals( "new cv1 info", ( ( Info ) cv1.getInfos().iterator().next() ).getText() );
+ cv2 = (ContractVariation) it.next();
+ assertEquals( cv2.getText(), "more expensive" );
+ s.delete(c);
+ assertEquals( s.createCriteria(Contract.class).setProjection( Projections.rowCount() ).uniqueResult(), new Long(0) );
+ assertEquals( s.createCriteria(ContractVariation.class).setProjection( Projections.rowCount() ).uniqueResult(), new Long(0) );
+ t.commit();
+ s.close();
+
+ assertUpdateCount( 0 );
+ assertDeleteCount( 4 );
+ }
+
protected void clearCounts() {
getSessions().getStatistics().clear();
}
Modified: core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/Info.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/Info.java 2010-02-24 20:21:08 UTC (rev 18872)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/Info.java 2010-02-24 21:20:26 UTC (rev 18873)
@@ -7,7 +7,6 @@
private long id;
private String text;
- private Contract contract;
public Info() {
super();
@@ -32,12 +31,4 @@
public void setId(long id) {
this.id = id;
}
-
- public Contract getContract() {
- return contract;
- }
-
- public void setContract(Contract contract ) {
- this.contract = contract;
- }
}
\ No newline at end of file
Modified: core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/Party.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/Party.java 2010-02-24 20:21:08 UTC (rev 18872)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/Party.java 2010-02-24 21:20:26 UTC (rev 18873)
@@ -12,6 +12,7 @@
private long id;
private Contract contract;
private String name;
+ private Set infos = new HashSet();
public Party() {
super();
@@ -44,4 +45,12 @@
public void setContract(Contract contract) {
this.contract = contract;
}
+
+ public Set getInfos() {
+ return infos;
+ }
+
+ public void setInfos(Set infos) {
+ this.infos = infos;
+ }
}
\ No newline at end of file
Modified: core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/Plan.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/Plan.java 2010-02-24 20:21:08 UTC (rev 18872)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/Plan.java 2010-02-24 21:20:26 UTC (rev 18873)
@@ -11,6 +11,7 @@
private long id;
private String description;
private Set contracts;
+ private Set infos;
public Plan() {
this( null );
@@ -19,6 +20,7 @@
public Plan(String description) {
this.description = description;
contracts = new HashSet();
+ infos = new HashSet();
}
public long getId() {
@@ -77,4 +79,12 @@
contracts.remove( sub );
}
}
+
+ public Set getInfos() {
+ return infos;
+ }
+
+ public void setInfos(Set infos) {
+ this.infos = infos;
+ }
}
\ No newline at end of file
14 years, 9 months
Hibernate SVN: r18872 - core/trunk/core/src/main/java/org/hibernate/event/def.
by hibernate-commits@lists.jboss.org
Author: gbadner
Date: 2010-02-24 15:21:08 -0500 (Wed, 24 Feb 2010)
New Revision: 18872
Modified:
core/trunk/core/src/main/java/org/hibernate/event/def/DefaultSaveOrUpdateEventListener.java
Log:
HHH-4948 : Session.flush() does not always cascade save or update to read-only or immutable entities
Modified: core/trunk/core/src/main/java/org/hibernate/event/def/DefaultSaveOrUpdateEventListener.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/event/def/DefaultSaveOrUpdateEventListener.java 2010-02-24 19:11:53 UTC (rev 18871)
+++ core/trunk/core/src/main/java/org/hibernate/event/def/DefaultSaveOrUpdateEventListener.java 2010-02-24 20:21:08 UTC (rev 18872)
@@ -285,11 +285,9 @@
Object entity,
EntityPersister persister) throws HibernateException {
- if ( !persister.isMutable() ) {
- log.trace( "immutable instance passed to doUpdate(), locking" );
- reassociate( event, entity, event.getRequestedId(), persister );
- }
- else {
+ if ( !persister.isMutable() ) {
+ log.trace( "immutable instance passed to performUpdate()" );
+ }
if ( log.isTraceEnabled() ) {
log.trace(
@@ -329,7 +327,7 @@
source.getPersistenceContext().addEntity(
entity,
- Status.MANAGED,
+ ( persister.isMutable() ? Status.MANAGED : Status.READ_ONLY ),
null, //cachedState,
key,
persister.getVersion( entity, source.getEntityMode() ),
@@ -350,8 +348,6 @@
}
cascadeOnUpdate( event, persister, entity );
-
- }
}
protected boolean invokeUpdateLifecycle(Object entity, EntityPersister persister, EventSource source) {
14 years, 9 months
Hibernate SVN: r18871 - core/trunk/cache-jbosscache/src/test/java/org/hibernate/test/cache/jbc/access.
by hibernate-commits@lists.jboss.org
Author: bstansberry(a)jboss.com
Date: 2010-02-24 14:11:53 -0500 (Wed, 24 Feb 2010)
New Revision: 18871
Modified:
core/trunk/cache-jbosscache/src/test/java/org/hibernate/test/cache/jbc/access/PutFromLoadValidatorUnitTestCase.java
Log:
[HHH-3817] Add missing lock release to test
Modified: core/trunk/cache-jbosscache/src/test/java/org/hibernate/test/cache/jbc/access/PutFromLoadValidatorUnitTestCase.java
===================================================================
--- core/trunk/cache-jbosscache/src/test/java/org/hibernate/test/cache/jbc/access/PutFromLoadValidatorUnitTestCase.java 2010-02-24 18:45:11 UTC (rev 18870)
+++ core/trunk/cache-jbosscache/src/test/java/org/hibernate/test/cache/jbc/access/PutFromLoadValidatorUnitTestCase.java 2010-02-24 19:11:53 UTC (rev 18871)
@@ -91,7 +91,16 @@
if (transactional) {
tm.begin();
}
- assertTrue(testee.acquirePutFromLoadLock(KEY1));
+
+ boolean lockable = testee.acquirePutFromLoadLock(KEY1);
+ try {
+ assertTrue(lockable);
+ }
+ finally {
+ if (lockable) {
+ testee.releasePutFromLoadLock(KEY1);
+ }
+ }
}
public void testRegisteredPut() throws Exception {
14 years, 9 months
Hibernate SVN: r18870 - in core/trunk/annotations/src/test: resources/org/hibernate/test/annotations and 1 other directories.
by hibernate-commits@lists.jboss.org
Author: hardy.ferentschik
Date: 2010-02-24 13:45:11 -0500 (Wed, 24 Feb 2010)
New Revision: 18870
Added:
core/trunk/annotations/src/test/java/org/hibernate/test/annotations/onetoone/Father.java
core/trunk/annotations/src/test/java/org/hibernate/test/annotations/onetoone/Son.java
core/trunk/annotations/src/test/resources/org/hibernate/test/annotations/onetoone/
core/trunk/annotations/src/test/resources/org/hibernate/test/annotations/onetoone/orm.xml
Modified:
core/trunk/annotations/src/test/java/org/hibernate/test/annotations/onetoone/OneToOneTest.java
Log:
HHH-4606 Functionality was actually already there. Just added a test
Added: core/trunk/annotations/src/test/java/org/hibernate/test/annotations/onetoone/Father.java
===================================================================
--- core/trunk/annotations/src/test/java/org/hibernate/test/annotations/onetoone/Father.java (rev 0)
+++ core/trunk/annotations/src/test/java/org/hibernate/test/annotations/onetoone/Father.java 2010-02-24 18:45:11 UTC (rev 18870)
@@ -0,0 +1,52 @@
+// $Id$
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.test.annotations.onetoone;
+
+/**
+ * @author Hardy Ferentschik
+ */
+public class Father {
+ private int id;
+
+ private String name;
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+}
+
+
Property changes on: core/trunk/annotations/src/test/java/org/hibernate/test/annotations/onetoone/Father.java
___________________________________________________________________
Name: svn:keywords
+ Id
Modified: core/trunk/annotations/src/test/java/org/hibernate/test/annotations/onetoone/OneToOneTest.java
===================================================================
--- core/trunk/annotations/src/test/java/org/hibernate/test/annotations/onetoone/OneToOneTest.java 2010-02-24 17:11:05 UTC (rev 18869)
+++ core/trunk/annotations/src/test/java/org/hibernate/test/annotations/onetoone/OneToOneTest.java 2010-02-24 18:45:11 UTC (rev 18870)
@@ -1,9 +1,15 @@
//$Id$
package org.hibernate.test.annotations.onetoone;
+import java.util.Iterator;
+
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
+import org.hibernate.mapping.Column;
+import org.hibernate.mapping.Join;
+import org.hibernate.mapping.PersistentClass;
+import org.hibernate.mapping.Table;
import org.hibernate.test.annotations.Customer;
import org.hibernate.test.annotations.Discount;
import org.hibernate.test.annotations.Passport;
@@ -37,7 +43,7 @@
tx = s.beginTransaction();
Query q = s.createQuery( "select c from Client c where c.name = :name" );
q.setString( "name", c.getName() );
- c = (Client) q.uniqueResult();
+ c = ( Client ) q.uniqueResult();
//c = (Client) s.get(Client.class, c.getId());
assertNotNull( c );
tx.commit();
@@ -65,7 +71,7 @@
s.close();
s = openSession();
tx = s.beginTransaction();
- c = (Customer) s.get( Customer.class, c.getId() );
+ c = ( Customer ) s.get( Customer.class, c.getId() );
assertNotNull( c );
p = c.getPassport();
assertNotNull( p );
@@ -93,7 +99,7 @@
s = openSession();
tx = s.beginTransaction();
- c = (Client) s.get( Client.class, c.getId() );
+ c = ( Client ) s.get( Client.class, c.getId() );
assertNotNull( c );
assertNotNull( c.getAddress() );
assertEquals( "Paris", c.getAddress().getCity() );
@@ -105,7 +111,7 @@
Body b = new Body();
Heart h = new Heart();
b.setHeart( h );
- b.setId( new Integer( 1 ) );
+ b.setId( 1 );
h.setId( b.getId() ); //same PK
Session s;
Transaction tx;
@@ -118,7 +124,7 @@
s = openSession();
tx = s.beginTransaction();
- b = (Body) s.get( Body.class, b.getId() );
+ b = ( Body ) s.get( Body.class, b.getId() );
assertNotNull( b );
assertNotNull( b.getHeart() );
assertEquals( h.getId(), b.getHeart().getId() );
@@ -151,7 +157,7 @@
s = openSession();
tx = s.beginTransaction();
- c = (Computer) s.get( Computer.class, cid );
+ c = ( Computer ) s.get( Computer.class, cid );
assertNotNull( c );
assertNotNull( c.getSerial() );
assertEquals( sn.getValue(), c.getSerial().getValue() );
@@ -175,13 +181,13 @@
s.clear();
Transaction tx = s.beginTransaction();
- affiliate = (PartyAffiliate) s.get( PartyAffiliate.class, "id" );
+ affiliate = ( PartyAffiliate ) s.get( PartyAffiliate.class, "id" );
assertNotNull( affiliate.party );
assertEquals( affiliate.partyId, affiliate.party.partyId );
s.clear();
- party = (Party) s.get( Party.class, "id" );
+ party = ( Party ) s.get( Party.class, "id" );
assertNotNull( party.partyAffiliate );
assertEquals( party.partyId, party.partyAffiliate.partyId );
@@ -196,8 +202,8 @@
s.getTransaction().begin();
Trousers trousers = new Trousers();
TrousersZip zip = new TrousersZip();
- trousers.id = new Integer( 1 );
- zip.id = new Integer( 2 );
+ trousers.id = 1;
+ zip.id = 2;
trousers.zip = zip;
zip.trousers = trousers;
s.persist( trousers );
@@ -207,13 +213,13 @@
s.clear();
Transaction tx = s.beginTransaction();
- trousers = (Trousers) s.get( Trousers.class, trousers.id );
+ trousers = ( Trousers ) s.get( Trousers.class, trousers.id );
assertNotNull( trousers.zip );
assertEquals( zip.id, trousers.zip.id );
s.clear();
- zip = (TrousersZip) s.get( TrousersZip.class, zip.id );
+ zip = ( TrousersZip ) s.get( TrousersZip.class, zip.id );
assertNotNull( zip.trousers );
assertEquals( trousers.id, zip.trousers.id );
@@ -233,7 +239,7 @@
s.persist( owner );
s.flush();
s.clear();
- owner = (Owner) s.get( Owner.class, owner.getId() );
+ owner = ( Owner ) s.get( Owner.class, owner.getId() );
assertNotNull( owner );
assertNotNull( owner.getAddress() );
assertEquals( owner.getId(), owner.getAddress().getId() );
@@ -242,10 +248,34 @@
}
/**
+ * HHH-4606
+ */
+ public void testJoinColumnConfiguredInXml() {
+ PersistentClass pc = cfg.getClassMapping( Son.class.getName() );
+ Iterator iter = pc.getJoinIterator();
+ Table table = ( ( Join ) iter.next() ).getTable();
+ Iterator columnIter = table.getColumnIterator();
+ boolean fooFound = false;
+ boolean barFound = false;
+ while ( columnIter.hasNext() ) {
+ Column column = ( Column ) columnIter.next();
+ if ( column.getName().equals( "foo" ) ) {
+ fooFound = true;
+ }
+ if ( column.getName().equals( "bar" ) ) {
+ barFound = true;
+ }
+ }
+ assertTrue(
+ "The mapping defines join columns which could not be found in the metadata.", fooFound && barFound
+ );
+ }
+
+ /**
* @see org.hibernate.test.annotations.TestCase#getAnnotatedClasses()
*/
protected Class[] getAnnotatedClasses() {
- return new Class[]{
+ return new Class[] {
PartyAffiliate.class,
Party.class,
Trousers.class,
@@ -265,4 +295,7 @@
};
}
+ protected String[] getXmlFiles() {
+ return new String[] { "org/hibernate/test/annotations/onetoone/orm.xml" };
+ }
}
Property changes on: core/trunk/annotations/src/test/java/org/hibernate/test/annotations/onetoone/OneToOneTest.java
___________________________________________________________________
Name: svn:keywords
- Date Revision Author Id
+ Id
Added: core/trunk/annotations/src/test/java/org/hibernate/test/annotations/onetoone/Son.java
===================================================================
--- core/trunk/annotations/src/test/java/org/hibernate/test/annotations/onetoone/Son.java (rev 0)
+++ core/trunk/annotations/src/test/java/org/hibernate/test/annotations/onetoone/Son.java 2010-02-24 18:45:11 UTC (rev 18870)
@@ -0,0 +1,62 @@
+// $Id$
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.test.annotations.onetoone;
+
+/**
+ * @author Hardy Ferentschik
+ */
+public class Son {
+ private int id;
+
+ private String name;
+
+ private Father father;
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public Father getFather() {
+ return father;
+ }
+
+ public void setFather(Father father) {
+ this.father = father;
+ }
+}
+
+
Property changes on: core/trunk/annotations/src/test/java/org/hibernate/test/annotations/onetoone/Son.java
___________________________________________________________________
Name: svn:keywords
+ Id
Copied: core/trunk/annotations/src/test/resources/org/hibernate/test/annotations/onetoone/orm.xml (from rev 18869, core/trunk/annotations/src/test/resources/org/hibernate/test/annotations/onetomany/orm.xml)
===================================================================
--- core/trunk/annotations/src/test/resources/org/hibernate/test/annotations/onetoone/orm.xml (rev 0)
+++ core/trunk/annotations/src/test/resources/org/hibernate/test/annotations/onetoone/orm.xml 2010-02-24 18:45:11 UTC (rev 18870)
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ version="2.0">
+ <package>org.hibernate.test.annotations.onetoone</package>
+ <entity class="Father">
+ <attributes>
+ <id name="id">
+ <generated-value strategy="AUTO"/>
+ </id>
+ <basic name="name"/>
+ </attributes>
+ </entity>
+ <entity class="Son">
+ <attributes>
+ <id name="id">
+ <generated-value strategy="AUTO"/>
+ </id>
+ <basic name="name"/>
+ <one-to-one name="father">
+ <join-table name="father_son">
+ <join-column name="foo"/>
+ <inverse-join-column name="bar"/>
+ </join-table>
+ </one-to-one>
+ </attributes>
+ </entity>
+</entity-mappings>
\ No newline at end of file
14 years, 9 months
Hibernate SVN: r18869 - in core/trunk/annotations/src/test: java/org/hibernate/test/annotations/onetomany and 3 other directories.
by hibernate-commits@lists.jboss.org
Author: hardy.ferentschik
Date: 2010-02-24 12:11:05 -0500 (Wed, 24 Feb 2010)
New Revision: 18869
Added:
core/trunk/annotations/src/test/java/org/hibernate/test/annotations/onetomany/Manufacturer.java
core/trunk/annotations/src/test/java/org/hibernate/test/annotations/onetomany/Model.java
core/trunk/annotations/src/test/resources/org/hibernate/test/annotations/onetomany/
core/trunk/annotations/src/test/resources/org/hibernate/test/annotations/onetomany/orm.xml
Modified:
core/trunk/annotations/src/test/java/org/hibernate/test/annotations/loader/Team.java
core/trunk/annotations/src/test/java/org/hibernate/test/annotations/onetomany/OneToManyTest.java
core/trunk/annotations/src/test/resources/org/hibernate/test/annotations/access/xml/Boy.xml
core/trunk/annotations/src/test/resources/org/hibernate/test/annotations/access/xml/Cook.xml
core/trunk/annotations/src/test/resources/org/hibernate/test/annotations/access/xml/Crew.xml
core/trunk/annotations/src/test/resources/org/hibernate/test/annotations/access/xml/RentalCar.xml
core/trunk/annotations/src/test/resources/org/hibernate/test/annotations/access/xml/Tourist.xml
core/trunk/annotations/src/test/resources/org/hibernate/test/annotations/access/xml/Tourist2.xml
core/trunk/annotations/src/test/resources/org/hibernate/test/annotations/access/xml/Tourist3.xml
core/trunk/annotations/src/test/resources/org/hibernate/test/annotations/access/xml/Tourist4.xml
Log:
HHH-4605 - Add support for @OneToMany @JoinColumn in XML
Modified: core/trunk/annotations/src/test/java/org/hibernate/test/annotations/loader/Team.java
===================================================================
--- core/trunk/annotations/src/test/java/org/hibernate/test/annotations/loader/Team.java 2010-02-24 09:22:43 UTC (rev 18868)
+++ core/trunk/annotations/src/test/java/org/hibernate/test/annotations/loader/Team.java 2010-02-24 17:11:05 UTC (rev 18869)
@@ -2,7 +2,6 @@
import java.util.HashSet;
import java.util.Set;
-
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
@@ -12,18 +11,14 @@
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
import org.hibernate.annotations.Loader;
-import org.hibernate.annotations.NamedNativeQueries;
-import org.hibernate.annotations.NamedNativeQuery;
-import javax.persistence.NamedQuery;
-
@Entity
public class Team {
private Long id;
private Set<Player> players = new HashSet<Player>();
-
- @Id
- @GeneratedValue
+
+ @Id
+ @GeneratedValue
public Long getId() {
return id;
}
@@ -31,7 +26,7 @@
public void setId(Long id) {
this.id = id;
}
-
+
@OneToMany(targetEntity = Player.class, mappedBy = "team", fetch = FetchType.EAGER)
@Fetch(FetchMode.SELECT)
@Loader(namedQuery = "loadByTeam")
Copied: core/trunk/annotations/src/test/java/org/hibernate/test/annotations/onetomany/Manufacturer.java (from rev 18855, core/trunk/annotations/src/test/java/org/hibernate/test/annotations/xml/ejb3/Manufacturer.java)
===================================================================
--- core/trunk/annotations/src/test/java/org/hibernate/test/annotations/onetomany/Manufacturer.java (rev 0)
+++ core/trunk/annotations/src/test/java/org/hibernate/test/annotations/onetomany/Manufacturer.java 2010-02-24 17:11:05 UTC (rev 18869)
@@ -0,0 +1,29 @@
+//$Id$
+package org.hibernate.test.annotations.onetomany;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * @author Emmanuel Bernard
+ */
+public class Manufacturer {
+ private Integer id;
+ private Set<Model> models = new HashSet<Model>();
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public Set<Model> getModels() {
+ return models;
+ }
+
+ public void setModels(Set<Model> models) {
+ this.models = models;
+ }
+}
\ No newline at end of file
Copied: core/trunk/annotations/src/test/java/org/hibernate/test/annotations/onetomany/Model.java (from rev 18855, core/trunk/annotations/src/test/java/org/hibernate/test/annotations/xml/ejb3/Model.java)
===================================================================
--- core/trunk/annotations/src/test/java/org/hibernate/test/annotations/onetomany/Model.java (rev 0)
+++ core/trunk/annotations/src/test/java/org/hibernate/test/annotations/onetomany/Model.java 2010-02-24 17:11:05 UTC (rev 18869)
@@ -0,0 +1,36 @@
+//$Id$
+package org.hibernate.test.annotations.onetomany;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.ManyToOne;
+
+/**
+ * @author Emmanuel Bernard
+ */
+@Entity
+public class Model {
+ @Id
+ @GeneratedValue
+ private Integer id;
+
+ @ManyToOne
+ private Manufacturer manufacturer;
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public Manufacturer getManufacturer() {
+ return manufacturer;
+ }
+
+ public void setManufacturer(Manufacturer manufacturer) {
+ this.manufacturer = manufacturer;
+ }
+}
\ No newline at end of file
Modified: core/trunk/annotations/src/test/java/org/hibernate/test/annotations/onetomany/OneToManyTest.java
===================================================================
--- core/trunk/annotations/src/test/java/org/hibernate/test/annotations/onetomany/OneToManyTest.java 2010-02-24 09:22:43 UTC (rev 18868)
+++ core/trunk/annotations/src/test/java/org/hibernate/test/annotations/onetomany/OneToManyTest.java 2010-02-24 17:11:05 UTC (rev 18869)
@@ -4,6 +4,7 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.List;
import java.util.SortedSet;
import java.util.TreeSet;
@@ -12,6 +13,10 @@
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;
+import org.hibernate.junit.FailureExpected;
+import org.hibernate.mapping.Column;
+import org.hibernate.mapping.PersistentClass;
+import org.hibernate.mapping.Table;
import org.hibernate.test.annotations.Customer;
import org.hibernate.test.annotations.Discount;
import org.hibernate.test.annotations.Passport;
@@ -20,9 +25,10 @@
import org.hibernate.test.annotations.TicketComparator;
/**
- * Test various case of a one to many relationship
+ * Test various case of a one to many relationship.
*
* @author Emmanuel Bernard
+ * @author Hardy Ferentschik
*/
@SuppressWarnings("unchecked")
public class OneToManyTest extends TestCase {
@@ -77,12 +83,12 @@
s.clear();
//testing @OrderBy with explicit values including Formula
- paris = (City) s.get( City.class, paris.getId() );
+ paris = ( City ) s.get( City.class, paris.getId() );
assertEquals( 3, paris.getStreets().size() );
assertEquals( chmpsElysees.getStreetName(), paris.getStreets().get( 0 ).getStreetName() );
List<Street> mainStreets = paris.getMainStreets();
assertEquals( 2, mainStreets.size() );
- Integer previousId = new Integer( -1 );
+ Integer previousId = -1;
for ( Street street : mainStreets ) {
assertTrue( previousId < street.getId() );
previousId = street.getId();
@@ -115,7 +121,7 @@
s = openSession();
tx = s.beginTransaction();
- trainer = (Trainer) s.get( Trainer.class, trainer.getId() );
+ trainer = ( Trainer ) s.get( Trainer.class, trainer.getId() );
assertNotNull( trainer );
assertNotNull( trainer.getTrainedTigers() );
assertEquals( 2, trainer.getTrainedTigers().size() );
@@ -133,7 +139,7 @@
tx.commit();
fail( "A one to many should not allow several trainer per Tiger" );
}
- catch (HibernateException ce) {
+ catch ( HibernateException ce ) {
tx.rollback();
//success
}
@@ -162,7 +168,7 @@
s = openSession();
tx = s.beginTransaction();
- trainer = (Trainer) s.get( Trainer.class, trainer.getId() );
+ trainer = ( Trainer ) s.get( Trainer.class, trainer.getId() );
assertNotNull( trainer );
assertNotNull( trainer.getTrainedMonkeys() );
assertEquals( 2, trainer.getTrainedMonkeys().size() );
@@ -189,7 +195,7 @@
s = openSession();
tx = s.beginTransaction();
- t = (Troop) s.get( Troop.class, t.getId() );
+ t = ( Troop ) s.get( Troop.class, t.getId() );
assertNotNull( t.getSoldiers() );
assertFalse( Hibernate.isInitialized( t.getSoldiers() ) );
assertEquals( 2, t.getSoldiers().size() );
@@ -199,7 +205,7 @@
s = openSession();
tx = s.beginTransaction();
- t = (Troop) s.createQuery( "from " + Troop.class.getName() + " as t where t.id = :id" )
+ t = ( Troop ) s.createQuery( "from " + Troop.class.getName() + " as t where t.id = :id" )
.setParameter( "id", t.getId() ).uniqueResult();
assertFalse( Hibernate.isInitialized( t.getSoldiers() ) );
tx.commit();
@@ -207,14 +213,14 @@
s = openSession();
tx = s.beginTransaction();
- rambo = (Soldier) s.get( Soldier.class, rambo.getId() );
+ rambo = ( Soldier ) s.get( Soldier.class, rambo.getId() );
assertTrue( Hibernate.isInitialized( rambo.getTroop() ) );
tx.commit();
s.close();
s = openSession();
tx = s.beginTransaction();
- rambo = (Soldier) s.createQuery( "from " + Soldier.class.getName() + " as s where s.id = :rid" )
+ rambo = ( Soldier ) s.createQuery( "from " + Soldier.class.getName() + " as s where s.id = :rid" )
.setParameter( "rid", rambo.getId() ).uniqueResult();
assertTrue( "fetching strategy used when we do query", Hibernate.isInitialized( rambo.getTroop() ) );
tx.commit();
@@ -236,11 +242,10 @@
s.close();
s = openSession();
tx = s.beginTransaction();
- Troop troop = (Troop) s.get( Troop.class, disney.getId() );
- Soldier soldier = (Soldier) troop.getSoldiers().iterator().next();
+ Troop troop = ( Troop ) s.get( Troop.class, disney.getId() );
+ Soldier soldier = ( Soldier ) troop.getSoldiers().iterator().next();
tx.commit();
s.close();
- //troop.getSoldiers().remove(soldier);
troop.getSoldiers().clear();
s = openSession();
tx = s.beginTransaction();
@@ -249,9 +254,9 @@
s.close();
s = openSession();
tx = s.beginTransaction();
- soldier = (Soldier) s.get( Soldier.class, mickey.getId() );
+ soldier = ( Soldier ) s.get( Soldier.class, mickey.getId() );
assertNull( "delete-orphan should work", soldier );
- troop = (Troop) s.get( Troop.class, disney.getId() );
+ troop = ( Troop ) s.get( Troop.class, disney.getId() );
s.delete( troop );
tx.commit();
s.close();
@@ -272,13 +277,13 @@
s.close();
s = openSession();
tx = s.beginTransaction();
- Troop troop = (Troop) s.get( Troop.class, disney.getId() );
+ Troop troop = ( Troop ) s.get( Troop.class, disney.getId() );
s.delete( troop );
tx.commit();
s.close();
s = openSession();
tx = s.beginTransaction();
- Soldier soldier = (Soldier) s.get( Soldier.class, mickey.getId() );
+ Soldier soldier = ( Soldier ) s.get( Soldier.class, mickey.getId() );
assertNull( "delete-orphan should work", soldier );
tx.commit();
s.close();
@@ -306,7 +311,7 @@
s = openSession();
tx = s.beginTransaction();
- c = (Customer) s.load( Customer.class, c.getId() );
+ c = ( Customer ) s.load( Customer.class, c.getId() );
assertNotNull( c );
assertTrue( Hibernate.isInitialized( c.getTickets() ) );
assertNotNull( c.getTickets() );
@@ -335,7 +340,7 @@
s = openSession();
tx = s.beginTransaction();
- c = (Customer) s.load( Customer.class, c.getId() );
+ c = ( Customer ) s.load( Customer.class, c.getId() );
assertNotNull( c );
assertFalse( Hibernate.isInitialized( c.getDiscountTickets() ) );
assertNotNull( c.getDiscountTickets() );
@@ -371,7 +376,7 @@
s = openSession();
tx = s.beginTransaction();
- parent = (Parent) s.get( Parent.class, pk );
+ parent = ( Parent ) s.get( Parent.class, pk );
assertNotNull( parent.children );
Hibernate.initialize( parent.children );
assertEquals( 2, parent.children.size() );
@@ -379,33 +384,50 @@
s.close();
}
-// HHH-3577
-// public void testOrderByOnSuperclassProperty() {
-// OrganisationUser user = new OrganisationUser();
-// user.setFirstName( "Emmanuel" );
-// user.setLastName( "Bernard" );
-// user.setIdPerson( new Long(1) );
-// user.setSomeText( "SomeText" );
-// Organisation org = new Organisation();
-// org.setIdOrganisation( new Long(1) );
-// org.setName( "S Diego Zoo" );
-// user.setOrganisation( org );
-// Session s = openSession();
-// s.getTransaction().begin();
-// s.persist( user );
-// s.persist( org );
-// s.flush();
-// s.clear();
-// s.createQuery( "select org from Organisation org left join fetch org.organisationUsers" ).list();
-// s.getTransaction().rollback();
-// s.close();
-// }
+ @FailureExpected(jiraKey = "HHH-3577")
+ public void testOrderByOnSuperclassProperty() {
+ OrganisationUser user = new OrganisationUser();
+ user.setFirstName( "Emmanuel" );
+ user.setLastName( "Bernard" );
+ user.setIdPerson( 1l );
+ user.setSomeText( "SomeText" );
+ Organisation org = new Organisation();
+ org.setIdOrganisation( 1l );
+ org.setName( "S Diego Zoo" );
+ user.setOrganisation( org );
+ Session s = openSession();
+ s.getTransaction().begin();
+ s.persist( user );
+ s.persist( org );
+ s.flush();
+ s.clear();
+ s.createQuery( "select org from Organisation org left join fetch org.organisationUsers" ).list();
+ s.getTransaction().rollback();
+ s.close();
+ }
/**
+ * HHH-4605
+ */
+ public void testJoinColumnConfiguredInXml() {
+ PersistentClass pc = cfg.getClassMapping( Model.class.getName() );
+ Table table = pc.getRootTable();
+ Iterator iter = table.getColumnIterator();
+ boolean joinColumnFound = false;
+ while(iter.hasNext()) {
+ Column column = (Column) iter.next();
+ if(column.getName().equals( "model_manufacturer_join" )) {
+ joinColumnFound = true;
+ }
+ }
+ assertTrue( "The mapping defines a joing column which could not be found in the metadata.", joinColumnFound );
+ }
+
+ /**
* @see org.hibernate.test.annotations.TestCase#getAnnotatedClasses()
*/
protected Class[] getAnnotatedClasses() {
- return new Class[]{
+ return new Class[] {
Troop.class,
Soldier.class,
Customer.class,
@@ -423,8 +445,12 @@
Politician.class,
Person.class,
Organisation.class,
- OrganisationUser.class
+ OrganisationUser.class,
+ Model.class
};
}
+ protected String[] getXmlFiles() {
+ return new String[] { "org/hibernate/test/annotations/onetomany/orm.xml" };
+ }
}
Modified: core/trunk/annotations/src/test/resources/org/hibernate/test/annotations/access/xml/Boy.xml
===================================================================
--- core/trunk/annotations/src/test/resources/org/hibernate/test/annotations/access/xml/Boy.xml 2010-02-24 09:22:43 UTC (rev 18868)
+++ core/trunk/annotations/src/test/resources/org/hibernate/test/annotations/access/xml/Boy.xml 2010-02-24 17:11:05 UTC (rev 18869)
@@ -1,7 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm file:/Users/hardy/work/hibernate/core/trunk/annotations/src/main/resources/org/hibernate/ejb/orm_2_0.xsd"
version="2.0">
<package>org.hibernate.test.annotations.access.xml</package>
<entity class="Boy" metadata-complete="false">
Modified: core/trunk/annotations/src/test/resources/org/hibernate/test/annotations/access/xml/Cook.xml
===================================================================
--- core/trunk/annotations/src/test/resources/org/hibernate/test/annotations/access/xml/Cook.xml 2010-02-24 09:22:43 UTC (rev 18868)
+++ core/trunk/annotations/src/test/resources/org/hibernate/test/annotations/access/xml/Cook.xml 2010-02-24 17:11:05 UTC (rev 18869)
@@ -1,7 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm file:/Users/hardy/work/hibernate/core/trunk/annotations/src/main/resources/org/hibernate/ejb/orm_2_0.xsd"
version="2.0">
<package>org.hibernate.test.annotations.access.xml</package>
<entity class="Cook" metadata-complete="false">
Modified: core/trunk/annotations/src/test/resources/org/hibernate/test/annotations/access/xml/Crew.xml
===================================================================
--- core/trunk/annotations/src/test/resources/org/hibernate/test/annotations/access/xml/Crew.xml 2010-02-24 09:22:43 UTC (rev 18868)
+++ core/trunk/annotations/src/test/resources/org/hibernate/test/annotations/access/xml/Crew.xml 2010-02-24 17:11:05 UTC (rev 18869)
@@ -1,7 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm file:/Users/hardy/work/hibernate/core/trunk/annotations/src/main/resources/org/hibernate/ejb/orm_2_0.xsd"
version="2.0">
<package>org.hibernate.test.annotations.access.xml</package>
<mapped-superclass class="Crew" metadata-complete="false" access="FIELD">
@@ -11,4 +10,4 @@
</id>
</attributes>
</mapped-superclass>
-</entity-mappings>
+</entity-mappings>
\ No newline at end of file
Modified: core/trunk/annotations/src/test/resources/org/hibernate/test/annotations/access/xml/RentalCar.xml
===================================================================
--- core/trunk/annotations/src/test/resources/org/hibernate/test/annotations/access/xml/RentalCar.xml 2010-02-24 09:22:43 UTC (rev 18868)
+++ core/trunk/annotations/src/test/resources/org/hibernate/test/annotations/access/xml/RentalCar.xml 2010-02-24 17:11:05 UTC (rev 18869)
@@ -1,7 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm file:/Users/hardy/work/hibernate/core/trunk/annotations/src/main/resources/org/hibernate/ejb/orm_2_0.xsd"
version="2.0">
<package>org.hibernate.test.annotations.access.xml</package>
<entity class="RentalCar" metadata-complete="false">
Modified: core/trunk/annotations/src/test/resources/org/hibernate/test/annotations/access/xml/Tourist.xml
===================================================================
--- core/trunk/annotations/src/test/resources/org/hibernate/test/annotations/access/xml/Tourist.xml 2010-02-24 09:22:43 UTC (rev 18868)
+++ core/trunk/annotations/src/test/resources/org/hibernate/test/annotations/access/xml/Tourist.xml 2010-02-24 17:11:05 UTC (rev 18869)
@@ -1,13 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm file:/Users/hardy/work/hibernate/core/trunk/annotations/src/main/resources/org/hibernate/ejb/orm_2_0.xsd" version="2.0">
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ version="2.0">
<description>Mapping for Tourist entity</description>
<package>org.hibernate.test.annotations.access.xml</package>
<entity class="Tourist" cacheable="false" metadata-complete="false">
<attributes>
- <basic name="name" access="PROPERTY"/>
+ <basic name="name" access="PROPERTY"/>
<basic name="destination" access="PROPERTY"/>
</attributes>
- </entity>
+ </entity>
</entity-mappings>
Modified: core/trunk/annotations/src/test/resources/org/hibernate/test/annotations/access/xml/Tourist2.xml
===================================================================
--- core/trunk/annotations/src/test/resources/org/hibernate/test/annotations/access/xml/Tourist2.xml 2010-02-24 09:22:43 UTC (rev 18868)
+++ core/trunk/annotations/src/test/resources/org/hibernate/test/annotations/access/xml/Tourist2.xml 2010-02-24 17:11:05 UTC (rev 18869)
@@ -1,7 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm file:/Users/hardy/work/hibernate/core/trunk/annotations/src/main/resources/org/hibernate/ejb/orm_2_0.xsd"
version="2.0">
<description>Mapping for Tourist entity</description>
<persistence-unit-metadata>
Modified: core/trunk/annotations/src/test/resources/org/hibernate/test/annotations/access/xml/Tourist3.xml
===================================================================
--- core/trunk/annotations/src/test/resources/org/hibernate/test/annotations/access/xml/Tourist3.xml 2010-02-24 09:22:43 UTC (rev 18868)
+++ core/trunk/annotations/src/test/resources/org/hibernate/test/annotations/access/xml/Tourist3.xml 2010-02-24 17:11:05 UTC (rev 18869)
@@ -1,7 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm file:/Users/hardy/work/hibernate/core/trunk/annotations/src/main/resources/org/hibernate/ejb/orm_2_0.xsd"
version="2.0">
<description>Mapping for Tourist entity</description>
<package>org.hibernate.test.annotations.access.xml</package>
Modified: core/trunk/annotations/src/test/resources/org/hibernate/test/annotations/access/xml/Tourist4.xml
===================================================================
--- core/trunk/annotations/src/test/resources/org/hibernate/test/annotations/access/xml/Tourist4.xml 2010-02-24 09:22:43 UTC (rev 18868)
+++ core/trunk/annotations/src/test/resources/org/hibernate/test/annotations/access/xml/Tourist4.xml 2010-02-24 17:11:05 UTC (rev 18869)
@@ -1,7 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm file:/Users/hardy/work/hibernate/core/trunk/annotations/src/main/resources/org/hibernate/ejb/orm_2_0.xsd"
version="2.0">
<description>Mapping for Tourist entity</description>
<package>org.hibernate.test.annotations.access.xml</package>
Added: core/trunk/annotations/src/test/resources/org/hibernate/test/annotations/onetomany/orm.xml
===================================================================
--- core/trunk/annotations/src/test/resources/org/hibernate/test/annotations/onetomany/orm.xml (rev 0)
+++ core/trunk/annotations/src/test/resources/org/hibernate/test/annotations/onetomany/orm.xml 2010-02-24 17:11:05 UTC (rev 18869)
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ version="2.0">
+ <package>org.hibernate.test.annotations.onetomany</package>
+ <entity class="Manufacturer">
+ <attributes>
+ <id name="id">
+ <generated-value strategy="AUTO"/>
+ </id>
+ <one-to-many name="models">
+ <join-column name="model_manufacturer_join"/>
+ </one-to-many>
+ </attributes>
+ </entity>
+</entity-mappings>
\ No newline at end of file
14 years, 9 months
Hibernate SVN: r18868 - in core/trunk/cache-infinispan: src/test/java/org/hibernate/test/cache/infinispan and 1 other directory.
by hibernate-commits@lists.jboss.org
Author: galder.zamarreno(a)jboss.com
Date: 2010-02-24 04:22:43 -0500 (Wed, 24 Feb 2010)
New Revision: 18868
Modified:
core/trunk/cache-infinispan/pom.xml
core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/InfinispanRegionFactoryTestCase.java
Log:
Upgraded to Infinispan 4.0.0.FINAL
Modified: core/trunk/cache-infinispan/pom.xml
===================================================================
--- core/trunk/cache-infinispan/pom.xml 2010-02-24 07:31:58 UTC (rev 18867)
+++ core/trunk/cache-infinispan/pom.xml 2010-02-24 09:22:43 UTC (rev 18868)
@@ -18,7 +18,7 @@
<description>Integration of Hibernate with Infinispan</description>
<properties>
- <version.infinispan>4.0.0.CR4</version.infinispan>
+ <version.infinispan>4.0.0.FINAL</version.infinispan>
<version.hsqldb>1.8.0.2</version.hsqldb>
<version.cglib>2.2</version.cglib>
<version.javassist>3.4.GA</version.javassist>
Modified: core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/InfinispanRegionFactoryTestCase.java
===================================================================
--- core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/InfinispanRegionFactoryTestCase.java 2010-02-24 07:31:58 UTC (rev 18867)
+++ core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/InfinispanRegionFactoryTestCase.java 2010-02-24 09:22:43 UTC (rev 18868)
@@ -214,7 +214,6 @@
InfinispanRegionFactory factory = new InfinispanRegionFactory();
factory.start(null, p);
CacheManager manager = factory.getCacheManager();
- manager.getGlobalConfiguration().setTransportClass(null);
try {
EntityRegionImpl region = (EntityRegionImpl) factory.buildEntityRegion("com.acme.Address", p, null);
assertNull(factory.getTypeOverrides().get("com.acme.Address"));
@@ -296,7 +295,6 @@
InfinispanRegionFactory factory = new InfinispanRegionFactory();
factory.start(null, p);
CacheManager manager = factory.getCacheManager();
- manager.getGlobalConfiguration().setTransportClass(null);
try {
assertTrue(factory.getDefinedConfigurations().contains("timestamps"));
assertTrue(factory.getTypeOverrides().get("timestamps").getCacheName().equals("timestamps"));
@@ -322,7 +320,6 @@
InfinispanRegionFactory factory = new InfinispanRegionFactory();
factory.start(null, p);
CacheManager manager = factory.getCacheManager();
- manager.getGlobalConfiguration().setTransportClass(null);
try {
assertFalse(factory.getDefinedConfigurations().contains("timestamp"));
assertTrue(factory.getDefinedConfigurations().contains("unrecommended-timestamps"));
@@ -430,7 +427,6 @@
InfinispanRegionFactory factory = new InfinispanRegionFactory();
factory.start(null, p);
CacheManager manager = factory.getCacheManager();
- manager.getGlobalConfiguration().setTransportClass(null);
try {
assertTrue(manager.getGlobalConfiguration().isExposeGlobalJmxStatistics());
EntityRegionImpl region = (EntityRegionImpl) factory.buildEntityRegion("com.acme.Address", p, null);
@@ -479,7 +475,6 @@
InfinispanRegionFactory factory = new InfinispanRegionFactory();
factory.start(null, p);
CacheManager manager = factory.getCacheManager();
- manager.getGlobalConfiguration().setTransportClass(null);
try {
assertFalse(manager.getGlobalConfiguration().isExposeGlobalJmxStatistics());
EntityRegionImpl region = (EntityRegionImpl) factory.buildEntityRegion("com.acme.Address", p, null);
14 years, 9 months
Hibernate SVN: r18867 - in core/trunk: entitymanager/src/main/docbook/en/modules and 1 other directory.
by hibernate-commits@lists.jboss.org
Author: steve.ebersole(a)jboss.com
Date: 2010-02-24 02:31:58 -0500 (Wed, 24 Feb 2010)
New Revision: 18867
Modified:
core/trunk/documentation/manual/src/main/docbook/en-US/HIBERNATE_-_Relational_Persistence_for_Idiomatic_Java.ent
core/trunk/entitymanager/src/main/docbook/en/modules/query_criteria.xml
Log:
HHH-4936 - Document JPA criteria queries
Modified: core/trunk/documentation/manual/src/main/docbook/en-US/HIBERNATE_-_Relational_Persistence_for_Idiomatic_Java.ent
===================================================================
--- core/trunk/documentation/manual/src/main/docbook/en-US/HIBERNATE_-_Relational_Persistence_for_Idiomatic_Java.ent 2010-02-24 00:11:24 UTC (rev 18866)
+++ core/trunk/documentation/manual/src/main/docbook/en-US/HIBERNATE_-_Relational_Persistence_for_Idiomatic_Java.ent 2010-02-24 07:31:58 UTC (rev 18867)
@@ -1,5 +1,5 @@
<!ENTITY versionNumber "WORKING">
<!ENTITY today "TODAY">
<!ENTITY copyrightYear "2004">
-<!ENTITY copyrightHolder "Red Hat Middleware, LLC.">
+<!ENTITY copyrightHolder "Red Hat, Inc.">
<!ENTITY semi ";">
Modified: core/trunk/entitymanager/src/main/docbook/en/modules/query_criteria.xml
===================================================================
--- core/trunk/entitymanager/src/main/docbook/en/modules/query_criteria.xml 2010-02-24 00:11:24 UTC (rev 18866)
+++ core/trunk/entitymanager/src/main/docbook/en/modules/query_criteria.xml 2010-02-24 07:31:58 UTC (rev 18867)
@@ -26,218 +26,532 @@
<chapter id="querycriteria">
<title>Criteria Queries</title>
- <note>
- <para>
- This chapter elaborates on the material discussed in
- <citetitle pubwork="chapter">Chapter 6 Criteria API</citetitle>
- of<citation>JPA 2 Specification</citation>.
- </para>
- </note>
-
<para>
Criteria queries are a programmatic, type-safe way to express a query. They are type-safe
in terms of using interfaces and classes to represent various structural parts of a query
such as the query itself, or the select clause, or an order-by, etc. They can also be
type-safe in terms of referencing attributes as we will see in a bit. Users of the older
- Hibernate
- <interfacename>org.hibernate.Criteria</interfacename>
- query API will recognize
+ Hibernate <interfacename>org.hibernate.Criteria</interfacename> query API will recognize
the general approach, though we believe the JPA API to be superior as it represents a clean
- look at the lessons learned from that API. There are essentially 2 phases to performing
- a criteria query:
+ look at the lessons learned from that API.
+ </para>
- <orderedlist>
- <listitem>
- <para>
- <link linkend="querycriteria-building">Building the criteria instance</link>
- </para>
- </listitem>
- <listitem>
- <para>
- <link linkend="querycriteria-executing">Executing the criteria instance</link>
- </para>
- </listitem>
- </orderedlist>
+ <para>
+ Criteria queries are essentially an object graph, where each part of the graph represents an increasing
+ (as we navigate down this graph) more atomic part of query. The first step in performing a criteria query
+ is building this graph. The <interfacename>javax.persistence.criteria.CriteriaBuilder</interfacename>
+ interface is the first thing with which you need to become acquainted to begin using criteria queries. Its
+ role is that of a factory for all the individual pieces of the criteria. You obtain a
+ <interfacename>javax.persistence.criteria.CriteriaBuilder</interfacename> instance by calling the
+ <methodname>getCriteriaBuilder</methodname> method of the
+ <interfacename>javax.persistence.EntityManagerFactory</interfacename>
</para>
+ <programlisting>CriteriaBuilder builder = entityManagerFactory.getCriteriaBuilder();</programlisting>
- <section id="querycriteria-building">
- <title>Criteria query building</title>
+ <para>
+ The next step is to obtain a <interfacename>javax.persistence.criteria.CriteriaQuery</interfacename>.
+ You do this by one of the 3 methods on <interfacename>javax.persistence.criteria.CriteriaBuilder</interfacename>
+ for this puropse.
+ </para>
+
+ <programlisting><![CDATA[CriteriaQuery<T> createQuery(Class<T>)]]></programlisting>
+ <programlisting><![CDATA[CriteriaQuery<Tuple> createTupleQuery()]]></programlisting>
+ <programlisting><![CDATA[CriteriaQuery<Object> createQuery()]]></programlisting>
+
+ <para>
+ Each serves a different purpose depending on the expected type of the query results.
+ </para>
+
+ <note>
<para>
- Criteria queries are essentially an object graph, where each part of the graph
- represents an increasing (as we navigate down this graph) more atomic part of
- query. The first step in performing a criteria query is building this graph.
+ <citetitle pubwork="chapter">Chapter 6 Criteria API</citetitle> of the
+ <citation><xref linkend="JPA2"/></citation> already contains a decent amount of reference material
+ pertaining to the various parts of a criteria query. So rather than duplicate all that content here,
+ lets instead look at some of the more widely (anticipated) usages of the API.
</para>
- <section id="querycriteria-builder">
- <title>CriteriaBuilder</title>
+ </note>
+
+ <section id="querycriteria-typedquery">
+ <title>Typed criteria queries</title>
+ <programlisting><![CDATA[CriteriaQuery<T> createQuery(Class<T>)]]></programlisting>
+ <para>
+ The type of the criteria query (aka the <T>) indicates the expected types in the
+ query result. This might be an entity, an Integer, or any other object.
+ </para>
+
+ <section id="querycriteria-typedquery-entity">
+ <title>Selecting an entity</title>
<para>
- The
- <interfacename>javax.persistence.criteria.CriteriaBuilder</interfacename>
- interface is the
- first thing with which you need to become acquainted to begin using criteria queries. Its role
- is a factory for all the individual pieces of the criteria. You obtain a
- <interfacename>javax.persistence.criteria.CriteriaBuilder</interfacename>
- instance by calling
- the
- <methodname>javax.persistence.EntityManagerFactory.getCriteriaBuilder</methodname>
- method:
+ This the most used form of query in Hibernate Query Language (HQL) and Hibernate Criteria Queries.
+ You have an entity and you want to select one or more of that entity based on some condition.
</para>
- <programlisting>CriteriaBuilder builder = entityManagerFactory.getCriteriaBuilder();</programlisting>
+ <example id="ex-criteria-typedquery-entity">
+ <title>Selecting the root entity</title>
+ <programlistingco role="JAVA">
+ <areaspec>
+ <areaset id="ex.criteria.typedquery.entity.1" coords="">
+ <area id="ex.criteria.typedquery.entity.1.c1" coords='1'/>
+ <area id="ex.criteria.typedquery.entity.1.c2" coords='6'/>
+ </areaset>
+ <area id="ex.criteria.typedquery.entity.2" coords="3" />
+ <area id="ex.criteria.typedquery.entity.3" coords="4" />
+ </areaspec>
+ <programlisting><![CDATA[CriteriaQuery<Person> criteria = builder.createQuery( Person.class );
+Root<Person> personRoot = criteria.from( Person.class );
+criteria.select( personRoot );
+criteria.where( builder.equal( personRoot.get( Person_.eyeColor ), "brown" ) );
+List<Person> people = em.createQuery( criteria ).getResultList();
+for ( Person person : people ) { ... }]]></programlisting>
+ </programlistingco>
+ <calloutlist>
+ <callout arearefs="ex.criteria.typedquery.entity.1">
+ <para>
+ We use the form <emphasis>createQuery( Person.class )</emphasis>
+ here because the expected returns are in fact Person entities as we see when we
+ begin processing the results.
+ </para>
+ </callout>
+ <callout arearefs="ex.criteria.typedquery.entity.2">
+ <para>
+ <emphasis>personCriteria.select( personRoot )</emphasis> here is completely
+ unneeded in this specific case because of the fact that <emphasis>personRoot</emphasis>
+ will be the implied selection since we have only a single root. It was done here only
+ for completeness of an example
+ </para>
+ </callout>
+ <callout arearefs="ex.criteria.typedquery.entity.3">
+ <para>
+ <emphasis>Person_.eyeColor</emphasis> is an example of the static form of metamodel
+ reference. We will use that form exclusively in this chapter.
+ See (todo link to metamodel section once written).
+ </para>
+ </callout>
+ </calloutlist>
+ </example>
</section>
- <section id="querycriteria-criteria">
- <title>CriteriaQuery creation</title>
+
+ <section id="querycriteria-typedquery-expression">
+ <title>Selecting a value</title>
<para>
- Once you have the
- <interfacename>javax.persistence.criteria.CriteriaBuilder</interfacename>
- reference
- you can begin building the pieces of the criteria query. First, you will need a
- <interfacename>javax.persistence.criteria.CriteriaQuery</interfacename>
- instance.
- <interfacename>javax.persistence.criteria.CriteriaBuilder</interfacename>
- defines 3 methods
- for obtaining a
- <interfacename>javax.persistence.criteria.CriteriaQuery</interfacename>
- instance:
+ The simplest form of selecting a value is selecting a particular attribute from an entity. But
+ this might also be an aggregation, a mathematical operation, etc.
</para>
- <itemizedlist>
- <listitem>
- <programlisting><![CDATA[CriteriaQuery<T> createQuery(Class<T>)]]></programlisting>
- </listitem>
- <listitem>
- <programlisting><![CDATA[CriteriaQuery<Tuple> createTupleQuery()]]></programlisting>
- </listitem>
- <listitem>
- <programlisting><![CDATA[CriteriaQuery<Object> createQuery()]]></programlisting>
- </listitem>
- </itemizedlist>
+ <example id="ex-criteria-typedquery-attribute">
+ <title>Selecting an attribute</title>
+ <programlistingco role="JAVA">
+ <areaspec>
+ <areaset id="ex.criteria.typedquery.attr.1" coords="">
+ <area id="ex.criteria.typedquery.attr.1.c1" coords='1'/>
+ <area id="ex.criteria.typedquery.attr.1.c2" coords='5'/>
+ </areaset>
+ <area id="ex.criteria.typedquery.attr.2" coords="3" />
+ </areaspec>
+ <programlisting><![CDATA[CriteriaQuery<Integer> criteria = builder.createQuery( Integer.class );
+Root<Person> personRoot = criteria.from( Person.class );
+criteria.select( personRoot.get( Person_.age ) );
+criteria.where( builder.equal( personRoot.get( Person_.eyeColor ), "brown" ) );
+List<Integer> ages = em.createQuery( criteria ).getResultList();
+for ( Integer age : ages ) { ... } ]]></programlisting>
+ </programlistingco>
+ <calloutlist>
+ <callout arearefs="ex.criteria.typedquery.attr.1">
+ <para>
+ Notice again the typing of the query based on the anticipated result type(s). Here
+ we are specifying <classname>java.lang.Integer</classname> as the type of the
+ <emphasis>Person#age</emphasis> attribute is <classname>java.lang.Integer</classname>.
+ </para>
+ </callout>
+ <callout arearefs="ex.criteria.typedquery.attr.2">
+ <para>
+ We need to bind the fact that we are interested in the age associated with the
+ <emphasis>personRoot</emphasis>. We might have multiple references to the Person
+ entity in the query so we need to identify (aka qualify) which
+ <emphasis>Person#age</emphasis> we mean.
+ </para>
+ </callout>
+ </calloutlist>
+ </example>
+ <example id="ex-criteria-typedquery-expression">
+ <title>Selecting an expression</title>
+ <programlistingco role="JAVA">
+ <areaspec>
+ <area id="ex.criteria.typedquery.expr.1" coords="3" />
+ </areaspec>
+ <programlisting><![CDATA[CriteriaQuery<Integer> criteria = builder.createQuery( Integer.class );
+Root<Person> personRoot = criteria.from( Person.class );
+criteria.select( builder.max( personRoot.get( Person_.age ) ) );
+criteria.where( builder.equal( personRoot.get( Person_.eyeColor ), "brown" ) );
+Integer maxAge = em.createQuery( criteria ).getSingleResult();]]></programlisting>
+ </programlistingco>
+ <calloutlist>
+ <callout arearefs="ex.criteria.typedquery.expr.1">
+ <para>
+ Here we see <interfacename>javax.persistence.criteria.CriteriaBuilder</interfacename>
+ used to obtain a <emphasis>MAX</emphasis> expression. These expression building
+ methods return <interfacename>javax.persistence.criteria.Expression</interfacename>
+ instances typed according to various rules. The rule for a <emphasis>MAX</emphasis>
+ expression is that the expression type is the same as that of the underlying attribute.
+ </para>
+ </callout>
+ </calloutlist>
+ </example>
+ </section>
+
+ <section id="querycriteria-typedquery-multiselect">
+ <title>Selecting multiple values</title>
<para>
- Each serves a different purpose depending on the expected type of the query results. The type
- is "carried forward" to the
- <interfacename>javax.persistence.TypedQuery</interfacename>
- we
- create from this
- <interfacename>javax.persistence.criteria.CriteriaQuery</interfacename>
- as
- we will see later in<xref linkend="querycriteria-executing"/>later.
+ There are actually a few different ways to select multiple values using criteria queries. We will
+ explore 2 options here, but an alternative recommended approach is to use tuples as
+ described in <xref linkend="querycriteria-tuple"/>
</para>
- <section id="querycriteria-criteria-typed">
- <title>Typed CriteriaQuery</title>
- <programlisting>
- <![CDATA[CriteriaQuery<Person> personCriteria = builder.createQuery(Person.class);]]></programlisting>
- <para>
- Basically this is saying to create a criteria where the results of this query will be of type
- Person. Person might be an entity or it might not. The type could even be simple types like
- <classname>java.lang.Integer</classname>,<classname>java.lang.String</classname>, etc. We
- will discuss this topic in more detail in
- <xref linkend="querycriteria-selection"/>
- </para>
- </section>
- <section id="querycriteria-criteria-tuple">
- <title>Tuple CriteriaQuery</title>
- <programlisting>
- <![CDATA[CriteriaQuery<Tuple> personCriteria = builder.createTupleQuery();]]></programlisting>
- <programlisting>
- <![CDATA[CriteriaQuery<Tuple> personCriteria = builder.createQuery(Tuple.class);]]></programlisting>
- <para>
- These two forms are exactly the same. Both say to create a criteria where the results of this
- query will be of type<interfacename>javax.persistence.Tuple</interfacename>. The term tuple is
- taken from mathematics, but its intent here is simply to mean a plurality; namely we are saying
- that each query result will actually be multiple values, a projection. The
- <interfacename>javax.persistence.Tuple</interfacename>
- instance gives us typed access to these
- multiple result values after the query has been executed. We will discuss accessing the query
- results via a
- <interfacename>javax.persistence.Tuple</interfacename>
- in
- <xref linkend="querycriteria-executing"/>.
- </para>
- </section>
- <section id="querycriteria-criteria-untyped">
- <title>Untyped CriteriaQuery</title>
- <programlisting>
- <![CDATA[CriteriaQuery<Object> personCriteria = builder.createQuery();]]></programlisting>
- <programlisting>
- <![CDATA[CriteriaQuery<Object> personCriteria = builder.createQuery(Object.class);]]></programlisting>
- <para>
- These two forms are exactly the same. Both say to create a criteria where the results of this
- query could be anything. Not generally recommended as you obviously lose the type safety.
- </para>
- </section>
+ <example id="ex-criteria-typedquery-array">
+ <title>Selecting an array</title>
+ <programlistingco role="JAVA">
+ <areaspec>
+ <areaset id="ex.criteria.typedquery.array.1" coords="">
+ <area id="ex.criteria.typedquery.array.1.c1" coords='1'/>
+ <area id="ex.criteria.typedquery.array.1.c2" coords='7'/>
+ </areaset>
+ <area id="ex.criteria.typedquery.array.2" coords="5" />
+ </areaspec>
+ <programlisting><![CDATA[CriteriaQuery<Object[]> criteria = builder.createQuery( Object[].class );
+Root<Person> personRoot = criteria.from( Person.class );
+Path<Long> idPath = personRoot.get( Person_.id );
+Path<Integer> agePath = personRoot.get( Person_.age );
+criteria.select( builder.array( idPath, agePath ) );
+criteria.where( builder.equal( personRoot.get( Person_.eyeColor ), "brown" ) );
+List<Object[]> valueArray = em.createQuery( criteria ).getResultList();
+for ( Object[] values : valueArray ) {
+ final Long id = (Long) values[0];
+ final Integer age = (Integer) values[1];
+ ...
+}]]></programlisting>
+ </programlistingco>
+ <calloutlist>
+ <callout arearefs="ex.criteria.typedquery.array.1">
+ <para>
+ Technically this is classified as a typed query, but as you can see in handling the
+ results that is sort of misleading. Anyway, the expected result type here is an
+ array.
+ </para>
+ </callout>
+ <callout arearefs="ex.criteria.typedquery.array.2">
+ <para>
+ Here we see the use of the <methodname>array</methodname> method of the
+ <interfacename>javax.persistence.criteria.CriteriaBuilder</interfacename> which
+ explicitly combines individual selections into a
+ <interfacename>javax.persistence.criteria.CompoundSelection</interfacename>.
+ </para>
+ </callout>
+ </calloutlist>
+ </example>
+ <example id="ex-criteria-typedquery-array2">
+ <title>Selecting an array (2)</title>
+ <programlistingco role="JAVA">
+ <areaspec>
+ <areaset id="ex.criteria.typedquery.array2.1" coords="">
+ <area id="ex.criteria.typedquery.array2.1.c1" coords='1'/>
+ <area id="ex.criteria.typedquery.array2.1.c2" coords='7'/>
+ </areaset>
+ <area id="ex.criteria.typedquery.array2.2" coords="5" />
+ </areaspec>
+ <programlisting><![CDATA[CriteriaQuery<Object[]> criteria = builder.createQuery( Object[].class );
+Root<Person> personRoot = criteria.from( Person.class );
+Path<Long> idPath = personRoot.get( Person_.id );
+Path<Integer> agePath = personRoot.get( Person_.age );
+criteria.multiselect( idPath, agePath );
+criteria.where( builder.equal( personRoot.get( Person_.eyeColor ), "brown" ) );
+List<Object[]> valueArray = em.createQuery( criteria ).getResultList();
+for ( Object[] values : valueArray ) {
+ final Long id = (Long) values[0];
+ final Integer age = (Integer) values[1];
+ ...
+} ]]></programlisting>
+ </programlistingco>
+ <calloutlist>
+ <callout arearefs="ex.criteria.typedquery.array2.1">
+ <para>
+ Just as we saw in <xref linkend="ex-criteria-typedquery-array"/> we have
+ a "typed" criteria query returning an Object array.
+ </para>
+ </callout>
+ <callout arearefs="ex.criteria.typedquery.array2.2">
+ <para>
+ This actually functions exactly the same as what we saw in
+ <xref linkend="ex-criteria-typedquery-array"/>. The <methodname>multiselect</methodname>
+ method behaves slightly differently based on the type given when the criteria query
+ was first built, but in this case it says to select and return an
+ <emphasis>Object[]</emphasis>.
+ </para>
+ </callout>
+ </calloutlist>
+ </example>
</section>
- <section id="querycriteria-from">
- <title>FROM clause</title>
- <blockquote>
- <attribution>
- <citation>
- <citation>JPA 2 Specification</citation>
- </citation>
- </attribution>
- <para>
- A CriteriaQuery object defines a query over one or more entity, embeddable, or basic abstract
- schema types. The root objects of the query are entities, from which the other types are reached
- by navigation.
- </para>
- </blockquote>
- <para>All the individual parts of the FROM clause (roots, joins, paths) implement the
- <interfacename>javax.persistence.criteria.From</interfacename>
- interface.
+
+ <section id="querycriteria-typedquery-construct">
+ <title>Selecting a wrapper</title>
+ <para>
+ Another alternative to <xref linkend="querycriteria-typedquery-multiselect"/> is to instead select
+ an object that will "wrap" the multiple values. Going back to the example query there, rather than
+ returning an array of <emphasis>[Person#id, Person#age]</emphasis> instead declare a class
+ that holds these values and instead return that.
</para>
- <section id="querycriteria-from-root">
- <title>Roots</title>
- <para>Roots define the basis from which all joins, paths and attributes are available in the query. It
- is
- the root of the portion of your domain model you wish to query against. In a criteria query, a root
- is always an entity. Roots are defined and added to the criteria by the overloaded
- <methodname>from</methodname>
- methods on<interfacename>javax.persistence.criteria.CriteriaQuery</interfacename>:
- </para>
- <programlisting><![CDATA[<X> Root<X> from(Class<X>)]]></programlisting>
- <programlisting><![CDATA[<X> Root<X> from(EntityType<X>)]]></programlisting>
+ <example id="ex-criteria-typedquery-construct">
+ <title>Selecting an wrapper</title>
+ <programlistingco role="JAVA">
+ <areaspec>
+ <areaset id="ex.criteria.typedquery.construct.1" coords="" >
+ <area id="ex.criteria.typedquery.construct.1.c1" coords="1" />
+ <area id="ex.criteria.typedquery.construct.1.c2" coords="4" />
+ </areaset>
+ <areaset id="ex.criteria.typedquery.construct.2" coords="">
+ <area id="ex.criteria.typedquery.construct.2.c1" coords='11'/>
+ <area id="ex.criteria.typedquery.construct.2.c2" coords='21'/>
+ </areaset>
+ <areaset id="ex.criteria.typedquery.construct.3" coords="" >
+ <area id="ex.criteria.typedquery.construct.3.c1" coords="13" />
+ <area id="ex.criteria.typedquery.construct.3.c2" coords="14" />
+ </areaset>
+ </areaspec>
+ <programlisting><![CDATA[public class PersonWrapper {
+ private final Long id;
+ private final Integer age;
+ public PersonWrapper(Long id, Integer age) {
+ this.id = id;
+ this.age = age;
+ }
+ ...
+}
+...
+CriteriaQuery<PersonWrapper> criteria = builder.createQuery( PersonWrapper.class );
+Root<Person> personRoot = criteria.from( Person.class );
+criteria.select(
+ builder.construct(
+ PersonWrapper.class,
+ personRoot.get( Person_.id ),
+ personRoot.get( Person_.age )
+ )
+);
+criteria.where( builder.equal( personRoot.get( Person_.eyeColor ), "brown" ) );
+List<PersonWrapper> people = em.createQuery( criteria ).getResultList();
+for ( PersonWrapper person : people ) { ... }]]></programlisting>
+ </programlistingco>
+ <calloutlist>
+ <callout arearefs="ex.criteria.typedquery.construct.1">
+ <para>
+ First we see the simple definition of the wrapper object we will be using to
+ wrap our result values. Specifically notice the constructor and its argument types.
+ </para>
+ </callout>
+ <callout arearefs="ex.criteria.typedquery.construct.2">
+ <para>
+ Since we will be returning <emphasis>PersonWrapper</emphasis> objects, we
+ use <emphasis>PersonWrapper</emphasis> as the type of our criteria query.
+ </para>
+ </callout>
+ <callout arearefs="ex.criteria.typedquery.construct.3">
+ <para>
+ Here we see another new <interfacename>javax.persistence.criteria.CriteriaBuilder</interfacename>
+ method, <methodname>construct</methodname>, which is used to builder a wrapper
+ expression. Basically for every row in the result we are saying we would like
+ a <emphasis>PersonWrapper</emphasis> instantiated by the matching constructor. This
+ wrapper expression is then passed as the select.
+ </para>
+ </callout>
+ </calloutlist>
+ </example>
+ </section>
+
+ </section>
+
+ <section id="querycriteria-tuple">
+ <title>Tuple criteria queries</title>
+ <para>
+ A better approach to <xref linkend="querycriteria-typedquery-multiselect"/> is to either use
+ a wrapper (which we just saw in <xref linkend="querycriteria-typedquery-construct"/>) or using
+ the <interfacename>javax.persistence.Tuple</interfacename> contract.
+ </para>
+
+ <example id="ex-criteria-typedquery-tuple">
+ <title>Selecting a tuple</title>
+ <programlistingco role="JAVA">
+ <areaspec>
+ <areaset id="ex.criteria.typedquery.tuple.1" coords="">
+ <area id="ex.criteria.typedquery.tuple.1.c1" coords='1'/>
+ <area id="ex.criteria.typedquery.tuple.1.c2" coords='7'/>
+ </areaset>
+ <area id="ex.criteria.typedquery.tuple.2" coords="5" />
+ <areaset id="ex.criteria.typedquery.tuple.3" coords="">
+ <area id="ex.criteria.typedquery.tuple.3.c1" coords='9'/>
+ <area id="ex.criteria.typedquery.tuple.3.c2" coords='10'/>
+ </areaset>
+ </areaspec>
+ <programlisting><![CDATA[CriteriaQuery<Tuple> criteria = builder.createTupleQuery();
+Root<Person> personRoot = criteria.from( Person.class );
+Path<Long> idPath = personRoot.get( Person_.id );
+Path<Integer> agePath = personRoot.get( Person_.age );
+criteria.multiselect( idPath, agePath );
+criteria.where( builder.equal( personRoot.get( Person_.eyeColor ), "brown" ) );
+List<Tuple> tuples = em.createQuery( criteria ).getResultList();
+for ( Tuple tuple : valueArray ) {
+ assert tuple.get( 0 ) == tuple.get( idPath );
+ assert tuple.get( 1 ) == tuple.get( agePath );
+ ...
+} ]]></programlisting>
+ </programlistingco>
+ <calloutlist>
+ <callout arearefs="ex.criteria.typedquery.tuple.1">
+ <para>
+ Here we see the use of a new <interfacename>javax.persistence.criteria.CriteriaBuilder</interfacename>
+ <interfacename>javax.persistence.criteria.CriteriaQuery</interfacename> building method,
+ <methodname>createTupleQuery</methodname>. This is exactly equivalent to calling
+ <emphasis>builder.createQuery( Tuple.class )</emphasis>. It signifies that we want
+ to access the results through the <interfacename>javax.persistence.Tuple</interfacename> contract.
+ </para>
+ </callout>
+ <callout arearefs="ex.criteria.typedquery.tuple.2">
+ <para>
+ Again we see the use of the <methodname>multiselect</methodname> method, just like
+ in <xref linkend="ex-criteria-typedquery-array2"/>. The difference here is that the
+ type of the <interfacename>javax.persistence.criteria.CriteriaQuery</interfacename> was defined
+ as <interfacename>javax.persistence.Tuple</interfacename> so the compound selections in
+ this case are interpreted to be the tuple elements.
+ </para>
+ </callout>
+ <callout arearefs="ex.criteria.typedquery.tuple.3">
+ <para>
+ Here we see <interfacename>javax.persistence.Tuple</interfacename> allowing different types of
+ access to the results, which we will expand on next.
+ </para>
+ </callout>
+ </calloutlist>
+ </example>
+
+ <section id="querycriteria-tuple-access">
+ <title>Accessing tuple elements</title>
+ <para>
+ The <interfacename>javax.persistence.Tuple</interfacename> contract provides 3 basic forms of
+ access to the underlying elements:
+ </para>
+ <variablelist>
+ <varlistentry>
+ <term>typed</term>
+ <listitem>
+ <programlisting><![CDATA[<X> X get(TupleElement<X> tupleElement)]]></programlisting>
+ <para>
+ This allows typed access to the underlying tuple elements. We see this in
+ <xref linkend="ex-criteria-typedquery-tuple"/> in the <emphasis>tuple.get( idPath )</emphasis>
+ and <emphasis>tuple.get( agePath )</emphasis> calls. Just about everything is a
+ <interfacename>javax.persistence.TupleElement</interfacename>.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>positional</term>
+ <listitem>
+ <programlisting><![CDATA[Object get(int i)]]></programlisting>
+ <programlisting><![CDATA[<X> X get(int i, Class<X> type)]]></programlisting>
+ <para>
+ Very similar to what we saw in <xref linkend="ex-criteria-typedquery-array"/> and
+ <xref linkend="ex-criteria-typedquery-array2"/> in terms of positional access. Only the
+ second form here provides typing, because the user explicitly provides the typing
+ on access. We see this in <xref linkend="ex-criteria-typedquery-tuple"/> in
+ the <emphasis>tuple.get( 0 )</emphasis> and <emphasis>tuple.get( 1 )</emphasis> calls.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>aliased</term>
+ <listitem>
+ <programlisting><![CDATA[Object get(String alias)]]></programlisting>
+ <programlisting><![CDATA[<X> X get(String alias, Class<X> type)]]></programlisting>
+ <para>
+ Again, only the second form here provides typing, because the user explicitly provides
+ the typing on access. We have not seen an example of using this, but its trivial. We
+ would simply, for example, have applies an alias to either of the paths like
+ <emphasis>idPath.alias( "id" )</emphasis> and/or <emphasis>agePath.alias( "age" )</emphasis>
+ and we could have accessed the individual tuple elements by those specified aliases.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </section>
+
+ </section>
+
+
+
+ <section id="querycriteria-from">
+ <title>FROM clause</title>
+ <blockquote>
+ <attribution>
+ <citation><xref linkend="JPA2"/></citation>
+ </attribution>
+ <para>
+ A CriteriaQuery object defines a query over one or more entity, embeddable, or basic abstract
+ schema types. The root objects of the query are entities, from which the other types are reached
+ by navigation.
+ </para>
+ </blockquote>
+
+ <note>
+ <para>
+ All the individual parts of the FROM clause (roots, joins, paths) implement the
+ <interfacename>javax.persistence.criteria.From</interfacename> interface.
+ </para>
+ </note>
+
+ <section id="querycriteria-from-root">
+ <title>Roots</title>
+ <para>
+ Roots define the basis from which all joins, paths and attributes are available in the query. In
+ a criteria query, a root is always an entity. Roots are defined and added to the criteria by
+ the overloaded <methodname>from</methodname> methods on
+ <interfacename>javax.persistence.criteria.CriteriaQuery</interfacename>:
+ </para>
+ <programlisting><![CDATA[<X> Root<X> from(Class<X>)]]></programlisting>
+ <programlisting><![CDATA[<X> Root<X> from(EntityType<X>)]]></programlisting>
+ <example>
+ <title>Adding a root</title>
<programlisting><![CDATA[CriteriaQuery<Person> personCriteria = builder.createQuery( Person.class );
// create and add the root
person.from( Person.class );
...]]></programlisting>
- <para>Criteria queries may define multiple roots, the effect of which is to create a cartesean product
- between the newly added root and the others. Here is an example matching all single men and all
- single women:
- </para>
- <programlisting><![CDATA[CriteriaQuery query = builder.createQuery();
+ </example>
+
+ <para>
+ Criteria queries may define multiple roots, the effect of which is to create a
+ <ulink url="http://en.wikipedia.org/wiki/Cartesian_product">cartesian product</ulink>
+ between the newly added root and the others. Here is an example matching all single men and all
+ single women:
+ </para>
+ <programlisting><![CDATA[CriteriaQuery query = builder.createQuery();
Root<Person> men = query.from( Person.class );
Root<Person> women = query.from( Person.class );
Predicate menRestriction = builder.and(
- builder.equal(
- men.get( Person_.gender ),
- Gender.MALE
- ),
- builder.equal(
- men.get( Person_.relationshipStatus ),
- RelationshipStatus.SINGLE
- )
+ builder.equal( men.get( Person_.gender ), Gender.MALE ),
+ builder.equal( men.get( Person_.relationshipStatus ), RelationshipStatus.SINGLE )
);
Predicate womenRestriction = builder.and(
- builder.equal(
- women.get( Person_.gender ),
- Gender.FEMALE
- ),
- builder.equal(
- women.get( Person_.relationshipStatus ),
- RelationshipStatus.SINGLE
- )
+ builder.equal( women.get( Person_.gender ), Gender.FEMALE ),
+ builder.equal( women.get( Person_.relationshipStatus ), RelationshipStatus.SINGLE )
);
-query.where(
- builder.and( menRestriction, womenRestriction )
-);]]></programlisting>
- </section>
- <section id="querycriteria-from-join">
- <title>Joins</title>
- <para>Joins allow navigation from other
- <interfacename>javax.persistence.criteria.From</interfacename>
- to either association or embedded attributes. Joins are created by the numerous overloaded
- <methodname>join</methodname>
- methods of the
- <interfacename>javax.persistence.criteria.From</interfacename>
- interface:
- </para>
+query.where( builder.and( menRestriction, womenRestriction ) );]]></programlisting>
+ </section>
+
+ <section id="querycriteria-from-join">
+ <title>Joins</title>
+ <para>Joins allow navigation from other
+ <interfacename>javax.persistence.criteria.From</interfacename>
+ to either association or embedded attributes. Joins are created by the numerous overloaded
+ <methodname>join</methodname>
+ methods of the
+ <interfacename>javax.persistence.criteria.From</interfacename>
+ interface:
+ </para>
+ <example id="criteria-join-singular">
+ <title>Example with Embedded and ManyToOne</title>
<programlisting><![CDATA[CriteriaQuery<Person> personCriteria = builder.createQuery( Person.class );
Root<Person> personRoot = person.from( Person.class );
// Person.address is an embedded attribute
@@ -245,128 +559,105 @@
// Address.country is a ManyToOne
Join<Address,Country> addressCountry = personAddress.join( Address_.country );
...]]></programlisting>
- <para>An example with collection attributes:</para>
+ </example>
+ <example id="criteria-join-plural">
+ <title>Example with Collections</title>
<programlisting><![CDATA[CriteriaQuery<Person> personCriteria = builder.createQuery( Person.class );
Root<Person> personRoot = person.from( Person.class );
Join<Person,Order> orders = personRoot.join( Person_.orders );
Join<Order,LineItem> orderLines = orders.join( Order_.lineItems );
...]]></programlisting>
- </section>
- <section id="querycriteria-from-fetch">
- <title>Fetches</title>
- <para>todo</para>
- </section>
+ </example>
</section>
+
+ <section id="querycriteria-from-fetch">
+ <title>Fetches</title>
+ <para>
+ Just like in HQL and EJB-QL, we can specify that associated data be fetched along with the owner.
+ Fetches are created by the numerous overloaded <methodname>fetch</methodname>
+ methods of the <interfacename>javax.persistence.criteria.From</interfacename>
+ interface:
+ </para>
+ <example id="criteria-fetch-singular">
+ <title>Example with Embedded and ManyToOne</title>
+ <programlisting><![CDATA[CriteriaQuery<Person> personCriteria = builder.createQuery( Person.class );
+Root<Person> personRoot = person.from( Person.class );
+// Person.address is an embedded attribute
+Join<Person,Address> personAddress = personRoot.fetch( Person_.address );
+// Address.country is a ManyToOne
+Join<Address,Country> addressCountry = personAddress.fetch( Address_.country );
+...]]></programlisting>
+ </example>
+ <note>
+ <para>
+ Technically speaking, embedded attributes are always fetched with their owner. However
+ in order to define the fetching of <emphasis>Address#country</emphasis> we needed
+ a <interfacename>javax.persistence.criteria.Fetch</interfacename> for its parent path.
+ </para>
+ </note>
+ <example id="criteria-fetch-plural">
+ <title>Example with Collections</title>
+ <programlisting><![CDATA[CriteriaQuery<Person> personCriteria = builder.createQuery( Person.class );
+Root<Person> personRoot = person.from( Person.class );
+Join<Person,Order> orders = personRoot.fetch( Person_.orders );
+Join<Order,LineItem> orderLines = orders.fetch( Order_.lineItems );
+...]]></programlisting>
+ </example>
+ </section>
+
+ </section>
+
<section id="querycriteria-path">
<title>Path expressions</title>
<note>
<para>
- Roots, joins and fetches are themselves paths as well
+ Roots, joins and fetches are themselves paths as well.
</para>
</note>
- <para>todo</para>
</section>
- <section id="querycriteria-selection">
- <title>Selections</title>
- <para>todo</para>
- </section>
- </section>
- <section id="querycriteria-executing">
- <title>Criteria query execution</title>
- <para>todo</para>
- </section>
- <section id="querycriteria-common">
- <title>Common use cases</title>
- <section id="querycriteria-common-selectroot">
- <title>Selecting the root entity</title>
- <programlisting><![CDATA[// get all people with brown eyes
-CriteriaQuery<Person> personCriteria = build.createQuery( Person.class );
-Root<Person> personRoot = personCriteria.from( Person.class );
-// specifying select here is not strictly needed because 'personRoot'
-// will be the implied selection since we have only a single root;
-// but done here for explicitness
-personCriteria.select( personRoot );
-personCriteria.where( builder.equal( Person_.eyeColor, "brown" ) );
-List<Person> people = em.createQuery( personCriteria ).getResultList();]]></programlisting>
- </section>
- <section id="querycriteria-common-selectassociation">
- <title>Selecting an association</title>
- <programlisting><![CDATA[// get the gender of all people with brown eyes
-CriteriaQuery<Gender> personCriteria = build.createQuery( Gender.class );
-Root<Person> personRoot = personCriteria.from( Person.class );
-// specifying select here is not strictly needed because 'personRoot'
-// will be the implied selection since we have only a single root;
-// but done here for explicitness
-personCriteria.select( personRoot );
-personCriteria.where( builder.equal( Person_.eyeColor, "brown" ) );
-List<Person> people = em.createQuery( personCriteria ).getResultList();]]></programlisting>
- </section>
- <section id="querycriteria-common-selectvalue">
- <title>Selecting a value</title>
- <programlisting><![CDATA[// get the height of all people with brown eyes
-CriteriaQuery<Integer> personCriteria = build.createQuery( Integer.class );
-Root<Person> personRoot = personCriteria.from( Person.class );
-personCriteria.select( personRoot.get( Person.height ) );
-personCriteria.where( builder.equal( Person_.eyeColor, "brown" ) );
-List<Integer> heights = em.createQuery( personCriteria ).getResultList();]]></programlisting>
- </section>
- <section id="querycriteria-common-selectaggregation">
- <title>Selecting an aggregated value</title>
- <programlisting><![CDATA[// get the maximum height of all people with brown eyes
-CriteriaQuery<Integer> personCriteria = build.createQuery( Integer.class );
-Root<Person> personRoot = personCriteria.from( Person.class );
-personCriteria.select( builder.max( personRoot.get( Person.height ) ) );
-personCriteria.where( builder.equal( Person_.eyeColor, "brown" ) );
-Integer maxHeight = em.createQuery( personCriteria ).getSingleResult();]]></programlisting>
- </section>
- <section id="querycriteria-common-selecttuple">
- <title>Selecting a tuple</title>
- <programlisting><![CDATA[// get the id, height and gender of all people with brown eyes
-CriteriaQuery<Tuple> personCriteria = build.createTupleQuery();
-Root<Person> personRoot = personCriteria.from( Person.class );
-Path<Long> idPath = personRoot.get( Person_.id );
-idPath.setAlias( "id" );
-Path<Integer> heightPath = personRoot.get( Person_.height );
-Path<Gender> genderPath = personRoot.get( Person_.gender );
-personCriteria.multiselect( idPath, heightPath, genderPath );
-personCriteria.where( builder.equal( Person_.eyeColor, "brown" ) );
-List<Tuple> tuples = em.createQuery( personCriteria ).getResultList();
-for ( Tuple tuple : tuples ) {
- // the id value, for example, can be accessed by expression...
- handleId( tuple.get( idPath ) );
- // or by position...
- handleId( tuple.get( 0 ) );
- // or by the explicit alias we gave it...
- handleId( tuple.get( "id" ) );
-}]]></programlisting>
- </section>
- <section id="querycriteria-common-selectconstruct">
- <title>Selecting a constructed value</title>
- <programlisting><![CDATA[// get the id, height and gender of all people with brown eyes
-// like we did before, but this time wrap them in a "holder"
-CriteriaQuery<PersonHolder> personCriteria = build.createQuery( PersonHolder.class );
-Root<Person> personRoot = personCriteria.from( Person.class );
-personCriteria.select(
- builder.construct(
- PersonHolder.class,
- personRoot.get( Person_.id ),
- personRoot.get( Person_.height ),
- personRoot.get( Person_.gender )
- )
-);
-List<PersonHolder> people = em.createQuery( personCriteria ).getResultList();]]></programlisting>
- </section>
- <section id="querycriteria-common-param">
+
+
+ <section id="querycriteria-param">
+ <title>Using parameters</title>
+ <example id="ex-querycriteria-param" >
<title>Using parameters</title>
- <programlisting><![CDATA[// get all people with brown eyes
-CriteriaQuery<Person> personCriteria = build.createQuery( Person.class );
-Root<Person> personRoot = personCriteria.from( Person.class );
-personCriteria.select( personRoot );
+ <programlistingco>
+ <areaspec>
+ <area coords="4" id="ex.criteria.param.1"/>
+ <area coords="5" id="ex.criteria.param.2"/>
+ <area coords="7" id="ex.criteria.param.3"/>
+ </areaspec>
+ <programlisting><![CDATA[CriteriaQuery<Person> criteria = build.createQuery( Person.class );
+Root<Person> personRoot = criteria.from( Person.class );
+criteria.select( personRoot );
ParameterExpression<String> eyeColorParam = builder.parameter( String.class );
-personCriteria.where( builder.equal( Person_.eyeColor, eyeColorParam ) );
-TypedQuery<Person> query = em.createQuery( personCriteria );
+criteria.where( builder.equal( personRoot.get( Person_.eyeColor ), eyeColorParam ) );
+TypedQuery<Person> query = em.createQuery( criteria );
query.setParameter( eyeColorParam, "brown" );
List<Person> people = query.getResultList();]]></programlisting>
- </section>
+ <calloutlist>
+ <callout arearefs="ex.criteria.param.1">
+ <para>
+ Use the <methodname>parameter</methodname> method of
+ <interfacename>javax.persistence.criteria.CriteriaBuilder</interfacename>
+ to obtain a parameter reference.
+ </para>
+ </callout>
+ <callout arearefs="ex.criteria.param.2">
+ <para>
+ Use the parameter reference in the criteria query.
+ </para>
+ </callout>
+ <callout arearefs="ex.criteria.param.3">
+ <para>
+ Use the parameter reference to bind the parameter value to the
+ <interfacename>javax.persistence.TypedQuery</interfacename>
+ </para>
+ </callout>
+ </calloutlist>
+ </programlistingco>
+
+ </example>
</section>
+
</chapter>
14 years, 9 months
Hibernate SVN: r18866 - in core/trunk: testsuite/src/test/java/org/hibernate/test/immutable and 1 other directory.
by hibernate-commits@lists.jboss.org
Author: gbadner
Date: 2010-02-23 19:11:24 -0500 (Tue, 23 Feb 2010)
New Revision: 18866
Modified:
core/trunk/core/src/main/java/org/hibernate/event/def/DefaultAutoFlushEventListener.java
core/trunk/core/src/main/java/org/hibernate/event/def/DefaultFlushEventListener.java
core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/ImmutableTest.java
Log:
HHH-4948 : Session.flush() does not always cascade save or update to read-only or immutable entities
Modified: core/trunk/core/src/main/java/org/hibernate/event/def/DefaultAutoFlushEventListener.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/event/def/DefaultAutoFlushEventListener.java 2010-02-23 23:55:06 UTC (rev 18865)
+++ core/trunk/core/src/main/java/org/hibernate/event/def/DefaultAutoFlushEventListener.java 2010-02-24 00:11:24 UTC (rev 18866)
@@ -92,7 +92,8 @@
private boolean flushMightBeNeeded(final EventSource source) {
return !source.getFlushMode().lessThan(FlushMode.AUTO) &&
source.getDontFlushFromFind() == 0 &&
- source.getPersistenceContext().hasNonReadOnlyEntities();
+ ( source.getPersistenceContext().getEntityEntries().size() > 0 ||
+ source.getPersistenceContext().getCollectionEntries().size() > 0 );
}
}
Modified: core/trunk/core/src/main/java/org/hibernate/event/def/DefaultFlushEventListener.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/event/def/DefaultFlushEventListener.java 2010-02-23 23:55:06 UTC (rev 18865)
+++ core/trunk/core/src/main/java/org/hibernate/event/def/DefaultFlushEventListener.java 2010-02-24 00:11:24 UTC (rev 18866)
@@ -44,8 +44,9 @@
*/
public void onFlush(FlushEvent event) throws HibernateException {
final EventSource source = event.getSession();
- if ( source.getPersistenceContext().hasNonReadOnlyEntities() ) {
-
+ if ( source.getPersistenceContext().getEntityEntries().size() > 0 ||
+ source.getPersistenceContext().getCollectionEntries().size() > 0 ) {
+
flushEverythingToExecutions(event);
performExecutions(source);
postFlush(source);
@@ -53,7 +54,7 @@
if ( source.getFactory().getStatistics().isStatisticsEnabled() ) {
source.getFactory().getStatisticsImplementor().flush();
}
-
+
}
}
}
Modified: core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/ImmutableTest.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/ImmutableTest.java 2010-02-23 23:55:06 UTC (rev 18865)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/immutable/ImmutableTest.java 2010-02-24 00:11:24 UTC (rev 18866)
@@ -280,7 +280,6 @@
// c was loaded into s, so it should be read-only
assertTrue( s.isReadOnly( c ) );
c.setCustomerName("foo bar");
- c.getVariations().add( new ContractVariation(3, c) );
cv1 = (ContractVariation) c.getVariations().iterator().next();
cv1.setText("blah blah");
// cv1 and cv2 were loaded into s by hibernate, so they should be read-only
@@ -350,7 +349,6 @@
// c was loaded into s, so it should be read-only
assertTrue( s.isReadOnly( c ) );
c.setCustomerName("foo bar");
- c.getVariations().add( new ContractVariation(3, c) );
cv1 = (ContractVariation) c.getVariations().iterator().next();
cv1.setText("blah blah");
// cv1 and cv2 were loaded into s by hibernate, so they should be read-only
14 years, 9 months