merge master

This commit is contained in:
Strong Liu 2013-06-17 22:47:03 +08:00
commit cda5d8e959
250 changed files with 9198 additions and 2316 deletions

View File

@ -35,6 +35,7 @@ Do yo thing!
up the related commits and display them on the Jira issue.
* Make sure you have added the necessary tests for your changes.
* Run _all_ the tests to assure nothing else was accidentally broken.
* Make sure your source does not violate the checkstyles.
_Prior to commiting, if you want to pull in the latest upstream changes (highly
appreciated btw), please use rebasing rather than merging. Merging creates

View File

@ -71,6 +71,9 @@ subprojects { subProject ->
group = 'org.hibernate'
version = rootProject.hibernateTargetVersion
// The OSGi manifest exported package versions need to be only the numerical release -- no "SNAPSHOT" or "Final"
exportPackageVersion = version.replaceAll("-SNAPSHOT", "");
exportPackageVersion = exportPackageVersion.replaceAll(".Final", "");
// minimize changes, at least for now (gradle uses 'build' by default)..
buildDir = "target"
@ -229,7 +232,7 @@ subprojects { subProject ->
privatePackages.add( packageName );
}
else {
exportPackages.add( packageName );
exportPackages.add( packageName + ";version=\"" + exportPackageVersion + "\"" );
}
}
}

View File

@ -5,6 +5,53 @@ match the actual issue resolution (i.e. a bug might not be a bug). Please
refer to the particular case on JIRA using the issue tracking number to learn
more about each case.
Changes in version 4.3.0.Beta3 (2013.05.29)
------------------------------------------------------------------------------------------------------------------------
https://hibernate.atlassian.net/browse/HHH/fixforversion/13451
** Sub-task
* [HHH-8144] - Create a 'release' task that performs all tasks needed for doing a release
** Bug
* [HHH-2664] - full join not working
* [HHH-5465] - HQL left join fetch of an element collection following a left join fetch of a one-to-one relationship causes NullPointerException
* [HHH-6813] - @Id @OneToOne cause NullPointerException during query
* [HHH-8083] - @OrderColumn not updated on @OneToMany cascade
* [HHH-8219] - Protect against JDK 7 API usage
* [HHH-8220] - pom dependencies scope changed from compile to runtime
* [HHH-8225] - EMF cannot be created, closed, then re-created in OSGi
* [HHH-8233] - exclude-unlisted-classes is not excluding unlisted classes in root
* [HHH-8236] - Update to hibernate-commons-annotations 4.0.2.Final
* [HHH-8241] - Reusing of scanner instance is impossible with Apache Aries JPA
* [HHH-8250] - DefaultInitializeCollectionEventListener not finding collections in cache
* [HHH-8254] - throw HibernateException when transaction is rolledback by a reaper thread
* [HHH-8266] - Binding of named-stored-procedure XML element tries to create duplicate
* [HHH-8269] - DenormalizedTable FK constraint names can be too long
* [HHH-8270] - Support for accessing JPA schema export script files specified by URL
* [HHH-8271] - Handling of javax.persistence.sql-load-script-source
* [HHH-8273] - Incorrect "unique-key" naming comment in docs
** Improvement
* [HHH-6875] - @OrderBy on @ElementCollection of basic type should "order by value"
* [HHH-7214] - DiscriminatorValue
* [HHH-7582] - TableGenerator does not distinguish between different tenants (MultiTenant Schema based)
* [HHH-8211] - Checkstyle and FindBugs fix-ups
* [HHH-8217] - Make generated constraint names short and non-random
* [HHH-8226] - table synonyms cannot find columns on Oracle
* [HHH-8231] - Pass along IOException as cause when trying to open script outputs
* [HHH-8238] - OsgiJtaPlatform null pointer exception
* [HHH-8257] - More concisely obtaining a JBoss logger
** Task
* [HHH-8218] - Update to final versions of BV 1.1 and HV 5
* [HHH-8222] - Implement @NamedStoredProcedureQuery binding
* [HHH-8223] - Implement @NamedEntityGraph binding
* [HHH-8232] - Upgrade to Gradle 1.6
* [HHH-8235] - Drop database profiles upstream
* [HHH-8246] - Implement XML binding of NamedStoredProcedureQuery
* [HHH-8247] - Implement XML binding of NamedEntityGraph
Changes in version 4.3.0.Beta2 (2013.05.02)
------------------------------------------------------------------------------------------------------------------------
https://hibernate.atlassian.net/browse/HHH/fixforversion/13052

View File

@ -50,6 +50,12 @@
<surname>Badner</surname>
</personname>
</author>
<author>
<personname>
<firstname>Brett</firstname>
<surname>Meyer</surname>
</personname>
</author>
<othercredit>
<personname>

View File

@ -522,9 +522,8 @@
The <option>not-null</option> and <option>UNIQUE</option> attributes generate constraints on table columns.
</para>
<para>
The unique-key attribute groups columns in a single, unique key constraint. Currently, the specified value
of the unique-key attribute does not name the constraint in the generated DDL. It only groups the columns in
the mapping file.
The unique-key attribute groups columns in a single, unique key constraint. The attribute overrides
the name of any generated unique key constraint.
</para>
<programlisting language="XML" role="XML"><xi:include href="extras/notnull-unique.xml" xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" /></programlisting>
</step>

View File

@ -380,8 +380,12 @@
<para>
If you want to audit a relation, where the target entity is not audited (that is the case for example with
dictionary-like entities, which don't change and don't have to be audited), just annotate it with
<literal>@Audited(targetAuditMode = RelationTargetAuditMode.NOT_AUDITED)</literal>. Then, when reading historic
versions of your entity, the relation will always point to the "current" related entity.
<literal>@Audited(targetAuditMode = RelationTargetAuditMode.NOT_AUDITED)</literal>. Then, while reading historic
versions of your entity, the relation will always point to the "current" related entity. By default Envers
throws <classname>javax.persistence.EntityNotFoundException</classname> when "current" entity does not
exist in the database. Apply <literal>@NotFound(action = NotFoundAction.IGNORE)</literal> annotation
to silence the exception and assign null value instead. Hereby solution causes implicit eager loading
of to-one relations.
</para>
<para>

View File

@ -52,6 +52,7 @@
<xi:include href="JMX.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
<xi:include href="Envers.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
<xi:include href="chapters/multitenancy/Multi_Tenancy.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
<xi:include href="chapters/osgi/OSGi.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
<xi:include href="appendix-Configuration_Properties.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
<xi:include href="appendices/legacy_criteria/Legacy_Criteria.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
</book>

View File

@ -0,0 +1,422 @@
<?xml version='1.0' encoding='utf-8'?>
<chapter xmlns="http://docbook.org/ns/docbook"
xmlns:xl="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude">
<info>
<title>OSGi</title>
<abstract>
<para>
The Open Services Gateway initiative (OSGi) specification describes a dynamic, modularized system. "Bundles"
(components) can be installed, activated, deactivated, and uninstalled during runtime, without requiring
a system restart. OSGi frameworks manage bundles' dependencies, packages, and classes. The framework
is also in charge of ClassLoading, managing visibility of packages between bundles. Further, service
registry and discovery is provided through a "whiteboard" pattern.
</para>
<para>
OSGi environments present numerous, unique challenges. Most notably, the dynamic nature of available
bundles during runtime can require significant architectural considerations. Also,
architectures must allow the OSGi-specific ClassLoading and service registration/discovery.
</para>
</abstract>
</info>
<section>
<title>OSGi Specification and Environment</title>
<para>
Hibernate targets the OSGi 4.3 spec or later. It was necessary to start with 4.3, over 4.2, due to our
dependency on OSGi's <literal>BundleWiring</literal> for entity/mapping scanning.
</para>
<para>
Hibernate supports three types of configurations within OSGi.
<orderedlist>
<listitem>
<firstterm>Container-Managed JPA</firstterm>: <xref linkend="osgi-managed-jpa"/>
</listitem>
<listitem>
<firstterm>Unmanaged JPA</firstterm>: <xref linkend="osgi-unmanaged-jpa"/>
</listitem>
<listitem>
<firstterm>Unmanaged Native</firstterm>: <xref linkend="osgi-unmanaged-native"/>
</listitem>
</orderedlist>
</para>
</section>
<section>
<title>hibernate-osgi</title>
<para>
Rather than embed OSGi capabilities into hibernate-core, hibernate-entitymanager, and sub-modules,
hibernate-osgi was created. It's purposefully separated, isolating all OSGi dependencies. It provides an
OSGi-specific ClassLoader (aggregates the container's CL with core and entitymanager CLs), JPA persistence
provider, SF/EMF bootstrapping, entities/mappings scanner, and service management.
</para>
</section>
<section xml:id="osgi-managed-jpa">
<title>Container-Managed JPA</title>
<para>
The Enterprise OSGi specification includes container-managed JPA. The container is responsible for
discovering persistence units and creating the <literal>EntityManagerFactory</literal> (one EMF per PU).
It uses the JPA provider (hibernate-osgi) that has registered itself with the OSGi
<literal>PersistenceProvider</literal> service.
</para>
<para>
Quickstart tutorial project, demonstrating a container-managed JPA client bundle:
<link xl:href="https://github.com/hibernate/hibernate-orm/tree/master/documentation/src/main/docbook/quickstart/tutorials/osgi/managed-jpa">managed-jpa</link>
</para>
<section>
<title>Client bundle imports</title>
<para>
Your client bundle's manifest will need to import, at a minimum,
<itemizedlist>
<listitem>
<literal>javax.persistence</literal>
</listitem>
<listitem>
<para>
<literal>org.hibernate.proxy</literal> and <literal>javassist.util.proxy</literal>, due to
Hibernate's ability to return proxies for lazy initialization (Javassist enhancement
occurs on the entity's ClassLoader during runtime).
</para>
</listitem>
</itemizedlist>
</para>
</section>
<section>
<title>JPA 2.1</title>
<para>
No Enterprise OSGi JPA container currently supports JPA 2.1 (the spec is not yet released). For
testing, the managed-jpa example makes use of
<link xl:href="https://github.com/brmeyer/aries/tree/jpa21">Brett's fork of Aries</link>. To work
with Hibernate 4.3, clone the fork and build Aries JPA.
</para>
</section>
<section>
<title>DataSource</title>
<para>
Typical Enterprise OSGi JPA usage includes a DataSource installed in the container. The client
bundle's <literal>persistence.xml</literal> uses the DataSource through JNDI. For an example,
see the QuickStart's DataSource:
<link xl:href="https://github.com/hibernate/hibernate-orm/blob/master/documentation/src/main/docbook/quickstart/tutorials/osgi/datasource-h2.xml">datasource-h2.xml</link>
The DataSource is then called out in
<link xl:href="https://github.com/hibernate/hibernate-orm/blob/master/documentation/src/main/docbook/quickstart/tutorials/osgi/managed-jpa/src/main/resources/META-INF/persistence.xml">
persistence.xml's</link> <literal>jta-data-source</literal>.
</para>
</section>
<section>
<title>Bundle Ordering</title>
<para>
Hibernate currently requires fairly specific bundle activation ordering. See the managed-jpa
QuickStart's
<link xl:href="https://github.com/hibernate/hibernate-orm/blob/master/documentation/src/main/docbook/quickstart/tutorials/osgi/managed-jpa/features.xml">features.xml</link>
for the best supported sequence.
</para>
</section>
<section>
<title>Obtaining an EntityManger</title>
<para>
The easiest, and most supported, method of obtaining an <literal>EntityManager</literal> utilizes OSGi's
<literal>blueprint.xml</literal>. The container takes the name of your persistence unit, then injects
an <literal>EntityManager</literal> instance into your given bean attribute. See the
<literal>dpService</literal> bean in the managed-jpa QuickStart's
<link xl:href="https://github.com/hibernate/hibernate-orm/blob/master/documentation/src/main/docbook/quickstart/tutorials/osgi/managed-jpa/src/main/resources/OSGI-INF/blueprint/blueprint.xml">blueprint.xml</link>
for an example.
</para>
</section>
</section>
<section xml:id="osgi-unmanaged-jpa">
<title>Unmanaged JPA</title>
<para>
Hibernate also supports the use of JPA through hibernate-entitymanager, unmanaged by the OSGi
container. The client bundle is responsible for managing the EntityManagerFactory and EntityManagers.
</para>
<para>
Quickstart tutorial project, demonstrating an unmanaged JPA client bundle:
<link xl:href="https://github.com/hibernate/hibernate-orm/tree/master/documentation/src/main/docbook/quickstart/tutorials/osgi/unmanaged-jpa">unmanaged-jpa</link>
</para>
<section>
<title>Client bundle imports</title>
<para>
Your client bundle's manifest will need to import, at a minimum,
<itemizedlist>
<listitem>
<literal>javax.persistence</literal>
</listitem>
<listitem>
<para>
<literal>org.hibernate.proxy</literal> and <literal>javassist.util.proxy</literal>, due to
Hibernate's ability to return proxies for lazy initialization (Javassist enhancement
occurs on the entity's ClassLoader during runtime)
</para>
</listitem>
<listitem>
<para>
JDBC driver package (example: <literal>org.h2</literal>)
</para>
</listitem>
<listitem>
<para>
<literal>org.osgi.framework</literal>, necessary to discover the EMF (described below)
</para>
</listitem>
</itemizedlist>
</para>
</section>
<section>
<title>Bundle Ordering</title>
<para>
Hibernate currently requires fairly specific bundle activation ordering. See the unmanaged-jpa
QuickStart's
<link xl:href="https://github.com/hibernate/hibernate-orm/blob/master/documentation/src/main/docbook/quickstart/tutorials/osgi/unmanaged-jpa/features.xml">features.xml</link>
for the best supported sequence.
</para>
</section>
<section>
<title>Obtaining an EntityMangerFactory</title>
<para>
hibernate-osgi registers an OSGi service, using the JPA <literal>PersistenceProvider</literal> interface
name, that bootstraps and creates an <literal>EntityManagerFactory</literal> specific for OSGi
environments. It is VITAL that your EMF be obtained through the service, rather than creating it
manually. The service handles the OSGi ClassLoader, discovered extension points, scanning, etc. Manually
creating an <literal>EntityManagerFactory</literal> is guaranteed to NOT work during runtime!
</para>
<para>
For an example on how to discover and use the service, see the unmanaged-jpa
QuickStart's
<link xl:href="https://github.com/hibernate/hibernate-orm/blob/master/documentation/src/main/docbook/quickstart/tutorials/osgi/unmanaged-jpa/src/main/java/org/hibernate/osgitest/HibernateUtil.java">HibernateUtil.java</link>.
</para>
</section>
</section>
<section xml:id="osgi-unmanaged-native">
<title>Unmanaged Native</title>
<para>
Native Hibernate use is also supported. The client bundle is responsible for managing the
SessionFactory and Sessions.
</para>
<para>
Quickstart tutorial project, demonstrating an unmanaged native client bundle:
<link xl:href="https://github.com/hibernate/hibernate-orm/tree/master/documentation/src/main/docbook/quickstart/tutorials/osgi/unmanaged-native">unmanaged-native</link>
</para>
<section>
<title>Client bundle imports</title>
<para>
Your client bundle's manifest will need to import, at a minimum,
<itemizedlist>
<listitem>
<literal>javax.persistence</literal>
</listitem>
<listitem>
<para>
<literal>org.hibernate.proxy</literal> and <literal>javassist.util.proxy</literal>, due to
Hibernate's ability to return proxies for lazy initialization (Javassist enhancement
occurs on the entity's ClassLoader during runtime)
</para>
</listitem>
<listitem>
<para>
JDBC driver package (example: <literal>org.h2</literal>)
</para>
</listitem>
<listitem>
<para>
<literal>org.osgi.framework</literal>, necessary to discover the SF (described below)
</para>
</listitem>
<listitem>
<para>
<literal>org.hibernate.*</literal> packages, as necessary (ex: cfg, criterion, service, etc.)
</para>
</listitem>
</itemizedlist>
</para>
</section>
<section>
<title>Bundle Ordering</title>
<para>
Hibernate currently requires fairly specific bundle activation ordering. See the unmanaged-native
QuickStart's
<link xl:href="https://github.com/hibernate/hibernate-orm/blob/master/documentation/src/main/docbook/quickstart/tutorials/osgi/unmanaged-native/features.xml">features.xml</link>
for the best supported sequence.
</para>
</section>
<section>
<title>Obtaining an SessionFactory</title>
<para>
hibernate-osgi registers an OSGi service, using the <literal>SessionFactory</literal> interface
name, that bootstraps and creates an <literal>SessionFactory</literal> specific for OSGi
environments. It is VITAL that your SF be obtained through the service, rather than creating it
manually. The service handles the OSGi ClassLoader, discovered extension points, scanning, etc. Manually
creating an <literal>SessionFactory</literal> is guaranteed to NOT work during runtime!
</para>
<para>
For an example on how to discover and use the service, see the unmanaged-native
QuickStart's
<link xl:href="https://github.com/hibernate/hibernate-orm/blob/master/documentation/src/main/docbook/quickstart/tutorials/osgi/unmanaged-native/src/main/java/org/hibernate/osgitest/HibernateUtil.java">HibernateUtil.java</link>.
</para>
</section>
</section>
<section>
<title>Optional Modules</title>
<para>
The <link xl:href="https://github.com/hibernate/hibernate-orm/blob/master/documentation/src/main/docbook/quickstart/tutorials/osgi/unmanaged-native">unmanaged-native</link>
QuickStart project demonstrates the use of optional Hibernate modules. Each module adds additional
dependency bundles that must first be activated
(see <link xl:href="https://github.com/hibernate/hibernate-orm/blob/master/documentation/src/main/docbook/quickstart/tutorials/osgi/unmanaged-native/features.xml">features.xml</link>).
As of ORM 4.2, Envers is fully supported. Support for C3P0, Proxool, EhCache, and Infinispan were added in
4.3, however none of their 3rd party libraries currently work in OSGi (lots of ClassLoader problems, etc.).
We're tracking the issues in JIRA.
</para>
</section>
<section>
<title>Extension Points</title>
<para>
Multiple contracts exist to allow applications to integrate with and extend Hibernate capabilities. Most
apps utilize JDK services to provide their implementations. hibernate-osgi supports the same
extensions through OSGi services. Implement and register them in any of the three configurations.
hibernate-osgi will discover and integrate them during EMF/SF bootstrapping. Supported extension points
are as follows. The specified interface should be used during service registration.
<itemizedlist>
<listitem>
<literal>org.hibernate.integrator.spi.Integrator</literal> (as of 4.2)
</listitem>
<listitem>
<literal>org.hibernate.boot.registry.selector.StrategyRegistrationProvider</literal> (as of 4.3)
</listitem>
<listitem>
<literal>org.hibernate.metamodel.spi.TypeContributor</literal> (as of 4.3)
</listitem>
<listitem>
JTA's <literal>javax.transaction.TransactionManager</literal> and
<literal>javax.transaction.UserTransaction</literal> (as of 4.2), however these are typically
provided by the OSGi container.
</listitem>
</itemizedlist>
</para>
<para>
The easiest way to register extension point implementations is through a <literal>blueprint.xml</literal>
file. Add <literal>OSGI-INF/blueprint/blueprint.xml</literal> to your classpath. Envers' blueprint
is a great example:
</para>
<example>
<title>Example extension point registrations in blueprint.xml</title>
<programlisting role="XML"><xi:include href="extras/extension_point_blueprint.xml" parse="text"/></programlisting>
</example>
<para>
Extension points can also be registered programmatically with
<literal>BundleContext#registerService</literal>, typically within your
<literal>BundleActivator#start</literal>.
</para>
</section>
<section>
<title>Caveats</title>
<itemizedlist>
<listitem>
<para>
Technically, multiple persistence units are supported by Enterprise OSGi JPA and unmanaged
Hibernate JPA use. However, we cannot currently support this in OSGi. In Hibernate 4, only one
instance of the OSGi-specific ClassLoader is used per Hibernate bundle, mainly due to heavy use of
static TCCL utilities. We hope to support one OSGi ClassLoader per persistence unit in
Hibernate 5.
</para>
</listitem>
<listitem>
<para>
Scanning is supported to find non-explicitly listed entities and mappings. However, they MUST be
in the same bundle as your persistence unit (fairly typical anyway). Our OSGi ClassLoader only
considers the "requesting bundle" (hence the requirement on using services to create EMF/SF),
rather than attempting to scan all available bundles. This is primarily for versioning
considerations, collision protections, etc.
</para>
</listitem>
<listitem>
<para>
Some containers (ex: Aries) always return true for
<literal>PersistenceUnitInfo#excludeUnlistedClasses</literal>,
even if your persistence.xml explicitly has <literal>exclude-unlisted-classes</literal> set
to <literal>false</literal>. They claim it's to protect JPA providers from having to implement
scanning ("we handle it for you"), even though we still want to support it in many cases. The work
around is to set <literal>hibernate.archive.autodetection</literal> to, for example,
<literal>hbm,class</literal>. This tells hibernate to ignore the excludeUnlistedClasses value and
scan for <literal>*.hbm.xml</literal> and entities regardless.
</para>
</listitem>
<listitem>
<para>
Scanning does not currently support annotated packages on <literal>package-info.java</literal>.
</para>
</listitem>
<listitem>
<para>
Currently, Hibernate OSGi is primarily tested using Apache Karaf and Apache Aries JPA. Additional
testing is needed with Equinox, Gemini, and other container providers.
</para>
</listitem>
<listitem>
<para>
Hibernate ORM has many dependencies that do not currently provide OSGi manifests.
The QuickStart tutorials make heavy use of 3rd party bundles (SpringSource, ServiceMix) or the
<literal>wrap:...</literal> operator.
</para>
</listitem>
<listitem>
<para>
As previously mentioned, bundle activation is currently order specific. See the QuickStart
tutorials' <literal>features.xml</literal> for example sequences.
</para>
</listitem>
<listitem>
<para>
The environment should be considered STATIC. Hibernate currently does not support the ability
to dynamically add and remove client bundles during runtime. Doing so is typically
catastrophic. We hope to better support at least partially-dynamic environments in
Hibernate 5.
</para>
</listitem>
<listitem>
<para>
No Enterprise OSGi JPA container currently supports JPA 2.1 (the spec is not yet released). For
testing, the managed-jpa example makes use of
<link xl:href="https://github.com/brmeyer/aries/tree/jpa21">Brett's fork of Aries</link>. To work
with Hibernate 4.3, clone the fork and build Aries JPA.
</para>
</listitem>
</itemizedlist>
</section>
</chapter>

View File

@ -0,0 +1,11 @@
<blueprint default-activation="eager"
xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<bean id="integrator" class="org.hibernate.envers.event.spi.EnversIntegrator" />
<service ref="integrator" interface="org.hibernate.integrator.spi.Integrator" />
<bean id="typeContributor"
class="org.hibernate.envers.internal.entities.TypeContributorImpl" />
<service ref="typeContributor" interface="org.hibernate.metamodel.spi.TypeContributor" />
</blueprint>

View File

@ -95,10 +95,8 @@
<para>
A <literal>unique-key</literal> attribute can be used to group columns in
a single, unique key constraint. Currently, the specified value of the
<literal>unique-key</literal> attribute is <emphasis>not</emphasis> used
to name the constraint in the generated DDL. It is only used to group the columns in
the mapping file.
a single, unique key constraint. The attribute overrides
the name of any generated unique key constraint.
</para>
<programlisting role="XML"><![CDATA[<many-to-one name="org" column="orgId" unique-key="OrgEmployeeId"/>

View File

@ -31,6 +31,12 @@
<surname>Warski</surname>
</personname>
</author>
<author>
<personname>
<firstname>Brett</firstname>
<surname>Meyer</surname>
</personname>
</author>
<othercredit>
<personname>

View File

@ -43,5 +43,6 @@
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="content/tutorial_annotations.xml" />
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="content/tutorial_jpa.xml" />
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="content/tutorial_envers.xml" />
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="content/tutorial_osgi.xml" />
</book>

View File

@ -0,0 +1,104 @@
<?xml version='1.0' encoding='UTF-8' ?>
<chapter xmlns="http://docbook.org/ns/docbook"
xmlns:xl="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude">
<title>OSGi Tutorial</title>
<para>
Hibernate targets the OSGi 4.3 spec or later and supports three types
of configurations.
<orderedlist>
<listitem>
<link xl:href="https://github.com/hibernate/hibernate-orm/tree/master/documentation/src/main/docbook/quickstart/tutorials/osgi/managed-jpa">Container-Managed JPA</link>
</listitem>
<listitem>
<link xl:href="https://github.com/hibernate/hibernate-orm/tree/master/documentation/src/main/docbook/quickstart/tutorials/osgi/unmanaged-jpa">Unmanaged JPA</link>
</listitem>
<listitem>
<link xl:href="https://github.com/hibernate/hibernate-orm/tree/master/documentation/src/main/docbook/quickstart/tutorials/osgi/unmanaged-native">Unmanaged Native</link>
</listitem>
</orderedlist>
</para>
<para>
For more details about OSGi, the three configurations, hibernate-osgi, extensions points, and caveats, please
see the OSGi chapter of the Developer's Guide!
</para>
<section>
<title>
Project Overview
</title>
<para>
Each configuration has a QuickStart project located within the download bundle (under <filename>osgi</filename>).
The bundles can be used as-is within Apache Karaf. Feel free to use them as literal
"quick start" bundle templates.
</para>
</section>
<section>
<title>
Project Structure
</title>
<itemizedlist>
<listitem>
<filename>osgi/datasource-h2.xml</filename>: Enterprise OSGi JPA usage can include a DataSource installed in the container.
The client bundle's <literal>persistence.xml</literal> references the DataSource through JNDI. For an
example, see how managed-jpa's <literal>persistence.xml</literal> calls out the
<literal>jta-data-source</literal>.
</listitem>
<listitem>
<filename>osgi/[project]/features.xml</filename>: This is arguably the most important "quick start" material. It defines
a single Karaf feature ("hibernate-test") that demonstrates the necessary 3rd party libraries and
bundle activation ordering.
</listitem>
<listitem>
<filename>osgi/[project]/pom.xml</filename>: The POM includes typical compile-time dependencies (JPA, OSGi Core,
OSGi Enterprise), as well as OSGi manifest data.
</listitem>
<listitem>
<filename>osgi/[project]/src/main/resources/OSGI-INF/blueprint/blueprint.xml</filename>:
The Blueprint includes container-managed EntityManager
injection (for managed-jpa), as well as demonstrations showing how to register
your custom implementations of Hibernate extension points.
</listitem>
<listitem>
<filename>osgi/[project]/src/main/resources/META-INF/persistence.xml</filename> or
<filename>osgi/[project]/src/main/resources/hibernate.cfg.xml</filename>: Note that the configurations
are no different than typical uses of Hibernate!
</listitem>
<listitem>
<filename>osgi/[project]/src/main/java/org/hibernate/osgitest/HibernateUtil.java</filename>: Demonstrates how to create an
EntityManagerFactory (JPA) or SessionFactory (Native) using hibernate-osgi's services. Note that in
managed-jpa, this is replaced by <literal>DataPointServiceImpl#entityManager</literal>, injected by
<filename>blueprint.xml</filename> (described above).
</listitem>
</itemizedlist>
</section>
<section xml:id="hibernate-gsg-tutorial-envers-config">
<title>
TODOs
</title>
<itemizedlist>
<listitem>
If using managed-jpa, <filename>features.xml</filename> will need the path to
<filename>datasource-h2.xml</filename> updated.
</listitem>
</itemizedlist>
</section>
<section xml:id="hibernate-gsg-tutorial-envers-config">
<title>
Karaf Commands
</title>
<para>
All three bundles include Karaf Commands that can be used directly on the Karaf command line to test
basic persistence operations ("dp:add [name]", "dp:getall", "dp:deleteall", etc.). I leave them in the
QuickStarts as a useful sanity check.
</para>
</section>
</chapter>

View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
First install the H2 driver using:
> install -s mvn:com.h2database/h2/1.3.163
Then copy this file to the deploy folder
-->
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
<bean id="dataSource" class="org.h2.jdbcx.JdbcDataSource">
<property name="URL" value="jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1;MVCC=TRUE"/>
<property name="user" value="sa"/>
<property name="password" value=""/>
</bean>
<service interface="javax.sql.DataSource" ref="dataSource">
<service-properties>
<entry key="osgi.jndi.service.name" value="jdbc/h2ds"/>
</service-properties>
</service>
</blueprint>

View File

@ -0,0 +1 @@
/target

View File

@ -0,0 +1,74 @@
<?xml version="1.0" encoding="UTF-8"?>
<features>
<feature name="hibernate-test">
<feature>karaf-framework</feature>
<!-- JTA -->
<config name="org.apache.aries.transaction">
aries.transaction.recoverable = true
aries.transaction.timeout = 600
aries.transaction.howl.maxLogFiles = 2
aries.transaction.howl.maxBlocksPerFile = 512
aries.transaction.howl.bufferSizeKBytes = 4
</config>
<bundle start-level="30">mvn:org.apache.geronimo.specs/geronimo-jta_1.1_spec/1.1.1</bundle>
<bundle start-level="30">mvn:org.apache.aries.transaction/org.apache.aries.transaction.blueprint/1.0.0</bundle>
<bundle start-level="30">mvn:org.apache.aries.transaction/org.apache.aries.transaction.manager/1.0.1</bundle>
<!-- JPA -->
<bundle start-level="30">mvn:org.hibernate.javax.persistence/hibernate-jpa-2.1-api/1.0.0-SNAPSHOT</bundle>
<!-- No container currently supports JPA 2.1. Clone and build Aries JPA from the following fork (upgrades to
JPA 2.1). Aries should be upgrading as soon as the spec is out.
https://github.com/brmeyer/aries/tree/jpa21 -->
<bundle start-level="30">mvn:org.apache.aries/org.apache.aries.util/1.0.0</bundle>
<bundle start-level="30">mvn:org.apache.aries.jpa/org.apache.aries.jpa.api/1.0.1-SNAPSHOT</bundle>
<bundle start-level="30">mvn:org.apache.aries.jpa/org.apache.aries.jpa.blueprint.aries/1.0.2-SNAPSHOT</bundle>
<bundle start-level="30">mvn:org.apache.aries.jpa/org.apache.aries.jpa.container/1.0.1-SNAPSHOT</bundle>
<bundle start-level="30">mvn:org.apache.aries.jpa/org.apache.aries.jpa.container.context/1.0.2-SNAPSHOT</bundle>
<!-- JNDI -->
<bundle start-level="30">mvn:org.apache.aries.jndi/org.apache.aries.jndi.api/1.0.0</bundle>
<bundle start-level="30">mvn:org.apache.aries.jndi/org.apache.aries.jndi.core/1.0.0</bundle>
<bundle start-level="30">mvn:org.apache.aries.jndi/org.apache.aries.jndi.rmi/1.0.0</bundle>
<bundle start-level="30">mvn:org.apache.aries.jndi/org.apache.aries.jndi.url/1.0.0</bundle>
<bundle start-level="30">mvn:org.apache.aries.jndi/org.apache.aries.jndi.legacy.support/1.0.0</bundle>
<!-- Taken from Karaf-Tutorial -->
<bundle>mvn:commons-collections/commons-collections/3.2.1</bundle>
<bundle>mvn:commons-pool/commons-pool/1.5.4</bundle>
<bundle>mvn:commons-dbcp/commons-dbcp/1.4</bundle>
<bundle>mvn:commons-lang/commons-lang/2.6</bundle>
<bundle>wrap:mvn:net.sourceforge.serp/serp/1.13.1</bundle>
<bundle>mvn:com.h2database/h2/1.3.170</bundle>
<bundle>blueprint:file:/[PATH]/datasource-h2.xml</bundle>
<!-- These do not natively support OSGi, so using 3rd party bundles. -->
<bundle>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.antlr/2.7.7_5</bundle>
<bundle>mvn:org.jboss.javassist/com.springsource.javassist/3.15.0.GA</bundle>
<bundle>mvn:org.apache.servicemix.specs/org.apache.servicemix.specs.jsr303-api-1.0.0/2.2.0</bundle>
<bundle>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.ant/1.8.2_2</bundle>
<bundle>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.dom4j/1.6.1_5</bundle>
<!-- These do not natively support OSGi, so wrap with BND. -->
<bundle>wrap:mvn:org.jboss/jandex/1.1.0.Alpha1</bundle>
<bundle>wrap:mvn:org.hibernate.common/hibernate-commons-annotations/4.0.2.Final</bundle>
<bundle>mvn:com.fasterxml/classmate/0.5.4</bundle>
<bundle>mvn:org.jboss.logging/jboss-logging/3.1.0.GA</bundle>
<bundle>mvn:org.hibernate/hibernate-core/4.3.0-SNAPSHOT</bundle>
<bundle>mvn:org.hibernate/hibernate-entitymanager/4.3.0-SNAPSHOT</bundle>
<!-- TODO: It seems that the persistence unit bundle needs to be started
before hibernate-osgi. When the BundleActivator is started,
the persistence unit is provided even though managed-jpa
hasn't completely started yet. If that happens, you'll get an "illegal
bundle state" exception. Is there a way for the activator to
watch for bundles with PUs before registering the persistence provider? -->
<bundle>mvn:org.hibernate.osgi/managed-jpa/1.0.0</bundle>
<bundle>mvn:org.hibernate/hibernate-osgi/4.3.0-SNAPSHOT</bundle>
</feature>
</features>

View File

@ -0,0 +1,64 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.hibernate.osgi</groupId>
<artifactId>managed-jpa</artifactId>
<version>1.0.0</version>
<packaging>bundle</packaging>
<dependencies>
<dependency>
<groupId>org.hibernate.javax.persistence</groupId>
<artifactId>hibernate-jpa-2.1-api</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.core</artifactId>
<version>4.3.1</version>
</dependency>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.enterprise</artifactId>
<version>4.2.0</version>
</dependency>
<dependency>
<groupId>org.apache.karaf.shell</groupId>
<artifactId>org.apache.karaf.shell.console</artifactId>
<version>2.3.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-SymbolicName>org.hibernate.osgi.managed-jpa</Bundle-SymbolicName>
<Bundle-Name>managed-jpa</Bundle-Name>
<Bundle-Version>1.0.0</Bundle-Version>
<Export-Package>
org.hibernate.osgitest,
org.hibernate.osgitest.entity
</Export-Package>
<Import-Package>
org.apache.felix.service.command,
org.apache.felix.gogo.commands,
org.apache.karaf.shell.console,
org.apache.karaf.shell.commands,
javax.persistence;version="[1.0.0,2.1.0]",
<!-- Needed for proxying's Javassist enhancement during runtime -->
org.hibernate.proxy,
javassist.util.proxy,
*
</Import-Package>
<Meta-Persistence>META-INF/persistence.xml</Meta-Persistence>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,37 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* JBoss, Home of Professional Open Source
* Copyright 2013 Red Hat Inc. and/or its affiliates and other contributors
* as indicated by the @authors tag. All rights reserved.
* See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* 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, v. 2.1.
* This program is distributed in the hope that it will be useful, but WITHOUT A
* 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,
* v.2.1 along with this distribution; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
package org.hibernate.osgitest;
import java.util.List;
import org.hibernate.osgitest.entity.DataPoint;
/**
* @author Brett Meyer
*/
public interface DataPointService {
public void add(DataPoint dp);
public List<DataPoint> getAll();
public void deleteAll();
}

View File

@ -0,0 +1,58 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* JBoss, Home of Professional Open Source
* Copyright 2013 Red Hat Inc. and/or its affiliates and other contributors
* as indicated by the @authors tag. All rights reserved.
* See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* 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, v. 2.1.
* This program is distributed in the hope that it will be useful, but WITHOUT A
* 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,
* v.2.1 along with this distribution; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
package org.hibernate.osgitest;
import java.util.List;
import javax.persistence.EntityManager;
import org.hibernate.osgitest.entity.DataPoint;
/**
* @author Brett Meyer
*/
public class DataPointServiceImpl implements DataPointService {
private EntityManager entityManager;
public void add(DataPoint dp) {
entityManager.persist( dp );
entityManager.flush();
}
public List<DataPoint> getAll() {
return entityManager.createQuery( "select d from DataPoint d", DataPoint.class ).getResultList();
}
public void deleteAll() {
entityManager.createQuery( "delete from DataPoint" ).executeUpdate();
entityManager.flush();
}
public EntityManager getEntityManager() {
return entityManager;
}
public void setEntityManager(EntityManager entityManager) {
this.entityManager = entityManager;
}
}

View File

@ -0,0 +1,44 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.hibernate.osgitest.command;
import org.apache.felix.gogo.commands.Action;
import org.apache.felix.gogo.commands.Argument;
import org.apache.felix.gogo.commands.Command;
import org.apache.felix.service.command.CommandSession;
import org.hibernate.osgitest.DataPointService;
import org.hibernate.osgitest.entity.DataPoint;
@Command(scope = "dp", name = "add")
public class AddCommand implements Action {
@Argument(index=0, name="Name", required=true, description="Name", multiValued=false)
String name;
private DataPointService dpService;
public void setDpService(DataPointService dpService) {
this.dpService = dpService;
}
public Object execute(CommandSession session) throws Exception {
DataPoint dp = new DataPoint();
dp.setName( name );
dpService.add( dp );
return null;
}
}

View File

@ -0,0 +1,37 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.hibernate.osgitest.command;
import org.apache.felix.gogo.commands.Action;
import org.apache.felix.gogo.commands.Command;
import org.apache.felix.service.command.CommandSession;
import org.hibernate.osgitest.DataPointService;
@Command(scope = "dp", name = "deleteAll")
public class DeleteAllCommand implements Action {
private DataPointService dpService;
public void setDpService(DataPointService dpService) {
this.dpService = dpService;
}
public Object execute(CommandSession session) throws Exception {
dpService.deleteAll();
return null;
}
}

View File

@ -0,0 +1,43 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.hibernate.osgitest.command;
import java.util.List;
import org.apache.felix.gogo.commands.Action;
import org.apache.felix.gogo.commands.Command;
import org.apache.felix.service.command.CommandSession;
import org.hibernate.osgitest.DataPointService;
import org.hibernate.osgitest.entity.DataPoint;
@Command(scope = "dp", name = "getAll")
public class GetAllCommand implements Action {
private DataPointService dpService;
public void setDpService(DataPointService dpService) {
this.dpService = dpService;
}
public Object execute(CommandSession session) throws Exception {
List<DataPoint> dps = dpService.getAll();
for (DataPoint dp : dps) {
System.out.println(dp.getId() + ", " + dp.getName());
}
return null;
}
}

View File

@ -18,30 +18,36 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
package org.hibernate.test.annotations.join;
package org.hibernate.osgitest.entity;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Test;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
/**
* @author Brett Meyer
*/
@TestForIssue( jiraKey = "HHH-2872" )
public class JoinOrderingTest extends BaseCoreFunctionalTestCase {
@Entity
public class DataPoint {
@Id
@GeneratedValue
private long id;
@Override
protected Class<?>[] getAnnotatedClasses() {
// This is the important piece. ProductDetails must be first to
// reproduce the issue.
// return new Class<?>[] { ProductDetails.class, Product.class, ProductVersion.class };
// TODO: commented out -- @FailureExpected wasn't working on builds
// if it's a MappingException.
return new Class<?>[] { };
private String name;
public long getId() {
return id;
}
@Test
public void testEntityOrderingWithJoins() {
// nothing to do
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
version="1.0">
<persistence-unit name="managed-jpa" transaction-type="JTA">
<jta-data-source>osgi:service/javax.sql.DataSource/(osgi.jndi.service.name=jdbc/h2ds)</jta-data-source>
<properties>
<property name="hibernate.connection.driver_class" value="org.h2.Driver"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>
<property name="hibernate.hbm2ddl.auto" value="create-drop"/>
<property name="hibernate.archive.autodetection" value="class"/>
</properties>
</persistence-unit>
</persistence>

View File

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<blueprint default-activation="eager"
xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jpa="http://aries.apache.org/xmlns/jpa/v1.0.0"
xmlns:tx="http://aries.apache.org/xmlns/transactions/v1.0.0">
<!-- This gets the container-managed EntityManager and injects it into the DataPointServiceImpl bean. -->
<bean id="dpService" class="org.hibernate.osgitest.DataPointServiceImpl">
<jpa:context unitname="managed-jpa" property="entityManager"/>
<tx:transaction method="*" value="Required"/>
</bean>
<service ref="dpService" interface="org.hibernate.osgitest.DataPointService" />
<!-- This demonstrates how to register your custom implementations of Hibernate extension points, such as
Integrator and TypeContributor. -->
<!-- <bean id="integrator" class="your.package.IntegratorImpl"/>
<service ref="integrator" interface="org.hibernate.integrator.spi.Integrator"/>
<bean id="typeContributor" class="your.package.TypeContributorImpl"/>
<service ref="typeContributor" interface="org.hibernate.metamodel.spi.TypeContributor"/> -->
<!-- This bundle makes use of Karaf commands to demonstrate core persistence operations. Feel free to remove it. -->
<command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.1.0">
<command name="dp/add">
<action class="org.hibernate.osgitest.command.AddCommand">
<property name="dpService" ref="dpService"/>
</action>
</command>
<command name="dp/getAll">
<action class="org.hibernate.osgitest.command.GetAllCommand">
<property name="dpService" ref="dpService"/>
</action>
</command>
<command name="dp/deleteAll">
<action class="org.hibernate.osgitest.command.DeleteAllCommand">
<property name="dpService" ref="dpService"/>
</action>
</command>
</command-bundle>
</blueprint>

View File

@ -0,0 +1 @@
/target

View File

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8"?>
<features>
<feature name="hibernate-test">
<feature>karaf-framework</feature>
<!-- JTA -->
<bundle start-level="30">mvn:org.apache.geronimo.specs/geronimo-jta_1.1_spec/1.1.1</bundle>
<!-- JPA -->
<bundle start-level="30">mvn:org.hibernate.javax.persistence/hibernate-jpa-2.1-api/1.0.0-SNAPSHOT</bundle>
<!-- Taken from Karaf-Tutorial -->
<bundle>mvn:commons-collections/commons-collections/3.2.1</bundle>
<bundle>mvn:commons-pool/commons-pool/1.5.4</bundle>
<bundle>mvn:commons-dbcp/commons-dbcp/1.4</bundle>
<bundle>mvn:commons-lang/commons-lang/2.6</bundle>
<bundle>wrap:mvn:net.sourceforge.serp/serp/1.13.1</bundle>
<bundle>mvn:com.h2database/h2/1.3.170</bundle>
<!-- These do not natively support OSGi, so using 3rd party bundles. -->
<bundle>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.antlr/2.7.7_5</bundle>
<bundle>mvn:org.jboss.javassist/com.springsource.javassist/3.15.0.GA</bundle>
<bundle>mvn:org.apache.servicemix.specs/org.apache.servicemix.specs.jsr303-api-1.0.0/2.2.0</bundle>
<bundle>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.ant/1.8.2_2</bundle>
<bundle>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.dom4j/1.6.1_5</bundle>
<!-- These do not natively support OSGi, so wrap with BND. -->
<bundle>wrap:mvn:org.hibernate.common/hibernate-commons-annotations/4.0.2.Final</bundle>
<bundle>wrap:mvn:org.jboss/jandex/1.1.0.Alpha1</bundle>
<bundle>mvn:com.fasterxml/classmate/0.5.4</bundle>
<bundle>mvn:org.jboss.logging/jboss-logging/3.1.0.GA</bundle>
<bundle>mvn:org.hibernate/hibernate-core/4.3.0-SNAPSHOT</bundle>
<bundle>mvn:org.hibernate/hibernate-entitymanager/4.3.0-SNAPSHOT</bundle>
<bundle>mvn:org.hibernate/hibernate-osgi/4.3.0-SNAPSHOT</bundle>
<bundle>mvn:org.hibernate.osgi/unmanaged-jpa/1.0.0</bundle>
</feature>
</features>

View File

@ -0,0 +1,75 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.hibernate.osgi</groupId>
<artifactId>unmanaged-jpa</artifactId>
<version>1.0.0</version>
<packaging>bundle</packaging>
<dependencies>
<dependency>
<groupId>org.hibernate.javax.persistence</groupId>
<artifactId>hibernate-jpa-2.1-api</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.core</artifactId>
<version>4.3.1</version>
</dependency>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.enterprise</artifactId>
<version>4.2.0</version>
</dependency>
<dependency>
<groupId>org.apache.karaf.shell</groupId>
<artifactId>org.apache.karaf.shell.console</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>4.3.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.3.170</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-SymbolicName>org.hibernate.osgi.unmanaged-jpa</Bundle-SymbolicName>
<Bundle-Name>unmanaged-jpa</Bundle-Name>
<Bundle-Version>1.0.0</Bundle-Version>
<Export-Package>
org.hibernate.osgitest,
org.hibernate.osgitest.entity
</Export-Package>
<Import-Package>
org.apache.felix.service.command,
org.apache.felix.gogo.commands,
org.apache.karaf.shell.console,
org.apache.karaf.shell.commands,
org.h2,
javax.persistence;version="[1.0.0,2.1.0]",
<!-- Needed for proxying's Javassist enhancement during runtime -->
org.hibernate.proxy,
javassist.util.proxy,
*
</Import-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,41 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* JBoss, Home of Professional Open Source
* Copyright 2013 Red Hat Inc. and/or its affiliates and other contributors
* as indicated by the @authors tag. All rights reserved.
* See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* 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, v. 2.1.
* This program is distributed in the hope that it will be useful, but WITHOUT A
* 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,
* v.2.1 along with this distribution; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
package org.hibernate.osgitest;
import java.util.List;
import org.hibernate.osgitest.entity.DataPoint;
/**
* @author Brett Meyer
*/
public interface DataPointService {
public void add(DataPoint dp);
public void update(DataPoint dp);
public DataPoint get(long id);
public List<DataPoint> getAll();
public void deleteAll();
}

View File

@ -0,0 +1,76 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* JBoss, Home of Professional Open Source
* Copyright 2013 Red Hat Inc. and/or its affiliates and other contributors
* as indicated by the @authors tag. All rights reserved.
* See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* 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, v. 2.1.
* This program is distributed in the hope that it will be useful, but WITHOUT A
* 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,
* v.2.1 along with this distribution; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
package org.hibernate.osgitest;
import java.util.List;
import javax.persistence.EntityManager;
import org.hibernate.osgitest.entity.DataPoint;
/**
* @author Brett Meyer
*/
public class DataPointServiceImpl implements DataPointService {
public void add(DataPoint dp) {
EntityManager em = HibernateUtil.getEntityManager();
em.getTransaction().begin();
em.persist( dp );
em.getTransaction().commit();
em.close();
}
public void update(DataPoint dp) {
EntityManager em = HibernateUtil.getEntityManager();
em.getTransaction().begin();
em.merge( dp );
em.getTransaction().commit();
em.close();
}
public DataPoint get(long id) {
EntityManager em = HibernateUtil.getEntityManager();
em.getTransaction().begin();
DataPoint dp = (DataPoint) em.createQuery( "from DataPoint dp where dp.id=" + id ).getSingleResult();
em.getTransaction().commit();
em.close();
return dp;
}
public List<DataPoint> getAll() {
EntityManager em = HibernateUtil.getEntityManager();
em.getTransaction().begin();
List list = em.createQuery( "from DataPoint" ).getResultList();
em.getTransaction().commit();
em.close();
return list;
}
public void deleteAll() {
EntityManager em = HibernateUtil.getEntityManager();
em.getTransaction().begin();
em.createQuery( "delete from DataPoint" ).executeUpdate();
em.getTransaction().commit();
em.close();
}
}

View File

@ -0,0 +1,57 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* JBoss, Home of Professional Open Source
* Copyright 2013 Red Hat Inc. and/or its affiliates and other contributors
* as indicated by the @authors tag. All rights reserved.
* See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* 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, v. 2.1.
* This program is distributed in the hope that it will be useful, but WITHOUT A
* 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,
* v.2.1 along with this distribution; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
package org.hibernate.osgitest;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.spi.PersistenceProvider;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.ServiceReference;
/**
* @author Brett Meyer
*/
public class HibernateUtil {
private static EntityManagerFactory emf;
public static EntityManager getEntityManager() {
return getEntityManagerFactory().createEntityManager();
}
private static EntityManagerFactory getEntityManagerFactory() {
if ( emf == null ) {
Bundle thisBundle = FrameworkUtil.getBundle( HibernateUtil.class );
// Could get this by wiring up OsgiTestBundleActivator as well.
BundleContext context = thisBundle.getBundleContext();
ServiceReference serviceReference = context.getServiceReference( PersistenceProvider.class.getName() );
PersistenceProvider persistenceProvider = (PersistenceProvider) context.getService( serviceReference );
emf = persistenceProvider.createEntityManagerFactory( "unmanaged-jpa", null );
}
return emf;
}
}

View File

@ -0,0 +1,44 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.hibernate.osgitest.command;
import org.apache.felix.gogo.commands.Action;
import org.apache.felix.gogo.commands.Argument;
import org.apache.felix.gogo.commands.Command;
import org.apache.felix.service.command.CommandSession;
import org.hibernate.osgitest.DataPointService;
import org.hibernate.osgitest.entity.DataPoint;
@Command(scope = "dp", name = "addJPA")
public class AddCommand implements Action {
@Argument(index=0, name="Name", required=true, description="Name", multiValued=false)
String name;
private DataPointService dpService;
public void setDpService(DataPointService dpService) {
this.dpService = dpService;
}
public Object execute(CommandSession session) throws Exception {
DataPoint dp = new DataPoint();
dp.setName( name );
dpService.add( dp );
return null;
}
}

View File

@ -0,0 +1,37 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.hibernate.osgitest.command;
import org.apache.felix.gogo.commands.Action;
import org.apache.felix.gogo.commands.Command;
import org.apache.felix.service.command.CommandSession;
import org.hibernate.osgitest.DataPointService;
@Command(scope = "dp", name = "deleteAllJPA")
public class DeleteAllCommand implements Action {
private DataPointService dpService;
public void setDpService(DataPointService dpService) {
this.dpService = dpService;
}
public Object execute(CommandSession session) throws Exception {
dpService.deleteAll();
return null;
}
}

View File

@ -0,0 +1,43 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.hibernate.osgitest.command;
import java.util.List;
import org.apache.felix.gogo.commands.Action;
import org.apache.felix.gogo.commands.Command;
import org.apache.felix.service.command.CommandSession;
import org.hibernate.osgitest.DataPointService;
import org.hibernate.osgitest.entity.DataPoint;
@Command(scope = "dp", name = "getAllJPA")
public class GetAllCommand implements Action {
private DataPointService dpService;
public void setDpService(DataPointService dpService) {
this.dpService = dpService;
}
public Object execute(CommandSession session) throws Exception {
List<DataPoint> dps = dpService.getAll();
for (DataPoint dp : dps) {
System.out.println(dp.getId() + ", " + dp.getName());
}
return null;
}
}

View File

@ -0,0 +1,47 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.hibernate.osgitest.command;
import org.apache.felix.gogo.commands.Action;
import org.apache.felix.gogo.commands.Argument;
import org.apache.felix.gogo.commands.Command;
import org.apache.felix.service.command.CommandSession;
import org.hibernate.osgitest.DataPointService;
import org.hibernate.osgitest.entity.DataPoint;
@Command(scope = "dp", name = "updateJPA")
public class UpdateCommand implements Action {
@Argument(index=0, name="Id", required=true, description="Id", multiValued=false)
String id;
@Argument(index=1, name="Name", required=true, description="Name", multiValued=false)
String name;
private DataPointService dpService;
public void setDpService(DataPointService dpService) {
this.dpService = dpService;
}
public Object execute(CommandSession session) throws Exception {
DataPoint dp = dpService.get( Long.valueOf( id ) );
dp.setName( name );
dpService.update( dp );
return null;
}
}

View File

@ -0,0 +1,53 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* JBoss, Home of Professional Open Source
* Copyright 2013 Red Hat Inc. and/or its affiliates and other contributors
* as indicated by the @authors tag. All rights reserved.
* See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* 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, v. 2.1.
* This program is distributed in the hope that it will be useful, but WITHOUT A
* 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,
* v.2.1 along with this distribution; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
package org.hibernate.osgitest.entity;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
/**
* @author Brett Meyer
*/
@Entity
public class DataPoint {
@Id
@GeneratedValue
private long id;
private String name;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
version="1.0">
<persistence-unit name="unmanaged-jpa">
<class>org.hibernate.osgitest.entity.DataPoint</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<property name="hibernate.connection.driver_class" value="org.h2.Driver"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>
<property name="hibernate.connection.url" value="jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1;MVCC=TRUE"/>
<property name="hibernate.connection.username" value="sa"/>
<property name="hibernate.connection.password" value=""/>
<property name="hibernate.hbm2ddl.auto" value="create-drop"/>
</properties>
</persistence-unit>
</persistence>

View File

@ -0,0 +1,57 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<blueprint default-activation="eager"
xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<bean id="dpService" class="org.hibernate.osgitest.DataPointServiceImpl"/>
<service ref="dpService" interface="org.hibernate.osgitest.DataPointService" />
<!-- This demonstrates how to register your custom implementations of Hibernate extension points, such as
Integrator and TypeContributor. -->
<!-- <bean id="integrator" class="your.package.IntegratorImpl"/>
<service ref="integrator" interface="org.hibernate.integrator.spi.Integrator"/>
<bean id="typeContributor" class="your.package.TypeContributorImpl"/>
<service ref="typeContributor" interface="org.hibernate.metamodel.spi.TypeContributor"/> -->
<!-- This bundle makes use of Karaf commands to demonstrate core persistence operations. Feel free to remove it. -->
<command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.1.0">
<command name="dp:add">
<action class="org.hibernate.osgitest.command.AddCommand">
<property name="dpService" ref="dpService"/>
</action>
</command>
<command name="dp:update">
<action class="org.hibernate.osgitest.command.UpdateCommand">
<property name="dpService" ref="dpService"/>
</action>
</command>
<command name="dp:getAll">
<action class="org.hibernate.osgitest.command.GetAllCommand">
<property name="dpService" ref="dpService"/>
</action>
</command>
<command name="dp:deleteAll">
<action class="org.hibernate.osgitest.command.DeleteAllCommand">
<property name="dpService" ref="dpService"/>
</action>
</command>
</command-bundle>
</blueprint>

View File

@ -0,0 +1 @@
/target

View File

@ -0,0 +1,72 @@
<?xml version="1.0" encoding="UTF-8"?>
<features>
<feature name="hibernate-test">
<feature>karaf-framework</feature>
<!-- JTA -->
<bundle start-level="30">mvn:org.apache.geronimo.specs/geronimo-jta_1.1_spec/1.1.1</bundle>
<!-- JPA -->
<bundle start-level="30">mvn:org.hibernate.javax.persistence/hibernate-jpa-2.1-api/1.0.0-SNAPSHOT</bundle>
<!-- Taken from Karaf-Tutorial -->
<bundle>mvn:commons-collections/commons-collections/3.2.1</bundle>
<bundle>mvn:commons-pool/commons-pool/1.5.4</bundle>
<bundle>mvn:commons-dbcp/commons-dbcp/1.4</bundle>
<bundle>mvn:commons-lang/commons-lang/2.6</bundle>
<bundle>wrap:mvn:net.sourceforge.serp/serp/1.13.1</bundle>
<bundle>mvn:com.h2database/h2/1.3.170</bundle>
<!-- These do not natively support OSGi, so using 3rd party bundles. -->
<bundle>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.antlr/2.7.7_5</bundle>
<bundle>mvn:org.jboss.javassist/com.springsource.javassist/3.15.0.GA</bundle>
<bundle>mvn:org.apache.servicemix.specs/org.apache.servicemix.specs.jsr303-api-1.0.0/2.2.0</bundle>
<bundle>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.ant/1.8.2_2</bundle>
<bundle>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.dom4j/1.6.1_5</bundle>
<!-- These do not natively support OSGi, so wrap with BND. -->
<bundle>wrap:mvn:org.hibernate.common/hibernate-commons-annotations/4.0.2.Final</bundle>
<bundle>wrap:mvn:org.jboss/jandex/1.1.0.Alpha1</bundle>
<!-- Optional. Needed to test C3P0 connection pools. -->
<!-- <bundle>wrap:mvn:c3p0/c3p0/0.9.1</bundle> -->
<!-- Optional. Needed to test Proxool connection pools. -->
<!-- <bundle>wrap:mvn:proxool/proxool/0.8.3</bundle> -->
<!-- Optional. Needed to test ehcache 2lc. -->
<!-- <bundle>wrap:mvn:net.sf.ehcache/ehcache-core/2.4.3</bundle> -->
<bundle>mvn:com.fasterxml/classmate/0.5.4</bundle>
<bundle>mvn:org.jboss.logging/jboss-logging/3.1.0.GA</bundle>
<!-- JACC is optional. -->
<!--<bundle>mvn:javax.servlet/javax.servlet-api/3.0.1</bundle>
<bundle>mvn:org.jboss.spec.javax.security.jacc/jboss-jacc-api_1.4_spec/1.0.2.Final</bundle>-->
<!-- hibernate-validator is optional. -->
<!--<bundle>wrap:mvn:javax.validation/validation-api/1.0.0.GA</bundle>
<bundle>mvn:org.hibernate/hibernate-validator/4.2.0.Final</bundle>-->
<!-- Optional. Needed to test infinispan 2lc. -->
<!-- IMPORTANT: Infinispan requires the JRE sun.misc package. You
MUST enable this in your OSGi container. For Karaf, add
"org.osgi.framework.system.packages.extra=sun.misc" to etc/config.properties -->
<!-- <bundle>wrap:mvn:org.jboss.marshalling/jboss-marshalling/1.3.17.GA</bundle>
<bundle>wrap:mvn:org.jboss.marshalling/jboss-marshalling-river/1.3.17.GA</bundle>
<bundle>wrap:mvn:org.jboss/staxmapper/1.1.0.Final</bundle>
<bundle>mvn:org.jgroups/jgroups/3.2.8.Final</bundle>
<bundle>mvn:org.infinispan/infinispan-core/5.2.0.Beta3</bundle> -->
<bundle>mvn:org.hibernate/hibernate-core/4.3.0-SNAPSHOT</bundle>
<!-- TODO: Shouldn't need this, but hibernate-osgi's activator is a catch-all for SF and EMF. -->
<bundle>mvn:org.hibernate/hibernate-entitymanager/4.3.0-SNAPSHOT</bundle>
<bundle>mvn:org.hibernate/hibernate-envers/4.3.0-SNAPSHOT</bundle>
<!-- <bundle>mvn:org.hibernate/hibernate-c3p0/4.3.0-SNAPSHOT</bundle> -->
<!-- <bundle>mvn:org.hibernate/hibernate-proxool/4.3.0-SNAPSHOT</bundle> -->
<!-- <bundle>mvn:org.hibernate/hibernate-ehcache/4.3.0-SNAPSHOT</bundle> -->
<!-- <bundle>mvn:org.hibernate/hibernate-infinispan/4.3.0-SNAPSHOT</bundle> -->
<bundle>mvn:org.hibernate/hibernate-osgi/4.3.0-SNAPSHOT</bundle>
<bundle>mvn:org.hibernate.osgi/unmanaged-native/1.0.0</bundle>
</feature>
</features>

View File

@ -0,0 +1,83 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.hibernate.osgi</groupId>
<artifactId>unmanaged-native</artifactId>
<version>1.0.0</version>
<packaging>bundle</packaging>
<dependencies>
<dependency>
<groupId>org.hibernate.javax.persistence</groupId>
<artifactId>hibernate-jpa-2.1-api</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.core</artifactId>
<version>4.3.1</version>
</dependency>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.enterprise</artifactId>
<version>4.2.0</version>
</dependency>
<dependency>
<groupId>org.apache.karaf.shell</groupId>
<artifactId>org.apache.karaf.shell.console</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>4.3.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-envers</artifactId>
<version>4.3.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.3.170</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-SymbolicName>org.hibernate.osgi.unmanaged-native</Bundle-SymbolicName>
<Bundle-Name>unmanaged-native</Bundle-Name>
<Bundle-Version>1.0.0</Bundle-Version>
<Export-Package>
org.hibernate.osgitest,
org.hibernate.osgitest.entity
</Export-Package>
<Import-Package>
org.apache.felix.service.command,
org.apache.felix.gogo.commands,
org.apache.karaf.shell.console,
org.apache.karaf.shell.commands,
org.h2,
org.hibernate,
org.hibernate.cfg,
org.hibernate.service,
javax.persistence;version="[1.0.0,2.1.0]",
<!-- Needed for proxying's Javassist enhancement during runtime -->
org.hibernate.proxy,
javassist.util.proxy,
*
</Import-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,47 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* JBoss, Home of Professional Open Source
* Copyright 2013 Red Hat Inc. and/or its affiliates and other contributors
* as indicated by the @authors tag. All rights reserved.
* See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* 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, v. 2.1.
* This program is distributed in the hope that it will be useful, but WITHOUT A
* 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,
* v.2.1 along with this distribution; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
package org.hibernate.osgitest;
import java.util.List;
import java.util.Map;
import org.hibernate.envers.DefaultRevisionEntity;
import org.hibernate.osgitest.entity.DataPoint;
/**
* @author Brett Meyer
*/
public interface DataPointService {
public void add(DataPoint dp);
public void update(DataPoint dp);
public DataPoint get(long id);
public DataPoint load(long id);
public List<DataPoint> getAll();
public Map<Number, DefaultRevisionEntity> getRevisions(long id);
public void deleteAll();
}

View File

@ -0,0 +1,102 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* JBoss, Home of Professional Open Source
* Copyright 2013 Red Hat Inc. and/or its affiliates and other contributors
* as indicated by the @authors tag. All rights reserved.
* See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* 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, v. 2.1.
* This program is distributed in the hope that it will be useful, but WITHOUT A
* 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,
* v.2.1 along with this distribution; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
package org.hibernate.osgitest;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import org.hibernate.Hibernate;
import org.hibernate.Session;
import org.hibernate.criterion.Restrictions;
import org.hibernate.envers.AuditReader;
import org.hibernate.envers.AuditReaderFactory;
import org.hibernate.envers.DefaultRevisionEntity;
import org.hibernate.osgitest.entity.DataPoint;
/**
* @author Brett Meyer
*/
public class DataPointServiceImpl implements DataPointService {
public void add(DataPoint dp) {
Session s = HibernateUtil.getSession();
s.getTransaction().begin();
s.persist( dp );
s.getTransaction().commit();
s.close();
}
public void update(DataPoint dp) {
Session s = HibernateUtil.getSession();
s.getTransaction().begin();
s.update( dp );
s.getTransaction().commit();
s.close();
}
public DataPoint get(long id) {
Session s = HibernateUtil.getSession();
s.getTransaction().begin();
DataPoint dp = (DataPoint) s.createCriteria( DataPoint.class ).add(
Restrictions.eq( "id", id ) ).uniqueResult();
s.getTransaction().commit();
s.close();
return dp;
}
// Test lazy loading (mainly to make sure the proxy classes work in OSGi)
public DataPoint load(long id) {
Session s = HibernateUtil.getSession();
s.getTransaction().begin();
DataPoint dp = (DataPoint) s.load( DataPoint.class, new Long(id) );
// initialize
dp.getName();
s.getTransaction().commit();
s.close();
return dp;
}
public List<DataPoint> getAll() {
Session s = HibernateUtil.getSession();
s.getTransaction().begin();
List list = s.createQuery( "from DataPoint" ).list();
s.getTransaction().commit();
s.close();
return list;
}
public Map<Number, DefaultRevisionEntity> getRevisions(long id) {
Session s = HibernateUtil.getSession();
AuditReader reader = AuditReaderFactory.get(s);
List<Number> revisionNums = reader.getRevisions( DataPoint.class, id );
return reader.findRevisions( DefaultRevisionEntity.class, new HashSet<Number>(revisionNums) );
}
public void deleteAll() {
Session s = HibernateUtil.getSession();
s.getTransaction().begin();
s.createQuery( "delete from DataPoint" ).executeUpdate();
s.getTransaction().commit();
s.close();
}
}

View File

@ -0,0 +1,53 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* JBoss, Home of Professional Open Source
* Copyright 2013 Red Hat Inc. and/or its affiliates and other contributors
* as indicated by the @authors tag. All rights reserved.
* See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* 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, v. 2.1.
* This program is distributed in the hope that it will be useful, but WITHOUT A
* 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,
* v.2.1 along with this distribution; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
package org.hibernate.osgitest;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.ServiceReference;
/**
* @author Brett Meyer
*/
public class HibernateUtil {
private static SessionFactory sf;
public static Session getSession() {
return getSessionFactory().openSession();
}
private static SessionFactory getSessionFactory() {
if ( sf == null ) {
Bundle thisBundle = FrameworkUtil.getBundle( HibernateUtil.class );
// Could get this by wiring up OsgiTestBundleActivator as well.
BundleContext context = thisBundle.getBundleContext();
ServiceReference sr = context.getServiceReference( SessionFactory.class.getName() );
sf = (SessionFactory) context.getService( sr );
}
return sf;
}
}

View File

@ -0,0 +1,44 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.hibernate.osgitest.command;
import org.apache.felix.gogo.commands.Action;
import org.apache.felix.gogo.commands.Argument;
import org.apache.felix.gogo.commands.Command;
import org.apache.felix.service.command.CommandSession;
import org.hibernate.osgitest.DataPointService;
import org.hibernate.osgitest.entity.DataPoint;
@Command(scope = "dp", name = "add")
public class AddCommand implements Action {
@Argument(index=0, name="Name", required=true, description="Name", multiValued=false)
String name;
private DataPointService dpService;
public void setDpService(DataPointService dpService) {
this.dpService = dpService;
}
public Object execute(CommandSession session) throws Exception {
DataPoint dp = new DataPoint();
dp.setName( name );
dpService.add( dp );
return null;
}
}

View File

@ -0,0 +1,37 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.hibernate.osgitest.command;
import org.apache.felix.gogo.commands.Action;
import org.apache.felix.gogo.commands.Command;
import org.apache.felix.service.command.CommandSession;
import org.hibernate.osgitest.DataPointService;
@Command(scope = "dp", name = "deleteAll")
public class DeleteAllCommand implements Action {
private DataPointService dpService;
public void setDpService(DataPointService dpService) {
this.dpService = dpService;
}
public Object execute(CommandSession session) throws Exception {
dpService.deleteAll();
return null;
}
}

View File

@ -0,0 +1,43 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.hibernate.osgitest.command;
import java.util.List;
import org.apache.felix.gogo.commands.Action;
import org.apache.felix.gogo.commands.Command;
import org.apache.felix.service.command.CommandSession;
import org.hibernate.osgitest.DataPointService;
import org.hibernate.osgitest.entity.DataPoint;
@Command(scope = "dp", name = "getAll")
public class GetAllCommand implements Action {
private DataPointService dpService;
public void setDpService(DataPointService dpService) {
this.dpService = dpService;
}
public Object execute(CommandSession session) throws Exception {
List<DataPoint> dps = dpService.getAll();
for (DataPoint dp : dps) {
System.out.println(dp.getId() + ", " + dp.getName());
}
return null;
}
}

View File

@ -0,0 +1,43 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.hibernate.osgitest.command;
import org.apache.felix.gogo.commands.Action;
import org.apache.felix.gogo.commands.Argument;
import org.apache.felix.gogo.commands.Command;
import org.apache.felix.service.command.CommandSession;
import org.hibernate.osgitest.DataPointService;
import org.hibernate.osgitest.entity.DataPoint;
@Command(scope = "dp", name = "get")
public class GetCommand implements Action {
@Argument(index = 0, name = "Id", required = true, description = "Id", multiValued = false)
String id;
private DataPointService dpService;
public void setDpService(DataPointService dpService) {
this.dpService = dpService;
}
public Object execute(CommandSession session) throws Exception {
DataPoint dp = dpService.get( Long.valueOf( id ) );
System.out.println( dp.getId() + ", " + dp.getName() );
return null;
}
}

View File

@ -0,0 +1,48 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.hibernate.osgitest.command;
import java.util.Map;
import org.apache.felix.gogo.commands.Action;
import org.apache.felix.gogo.commands.Argument;
import org.apache.felix.gogo.commands.Command;
import org.apache.felix.service.command.CommandSession;
import org.hibernate.envers.DefaultRevisionEntity;
import org.hibernate.osgitest.DataPointService;
@Command(scope = "dp", name = "getRevisions")
public class GetRevisionsCommand implements Action {
@Argument(index=0, name="Id", required=true, description="Id", multiValued=false)
String id;
private DataPointService dpService;
public void setDpService(DataPointService dpService) {
this.dpService = dpService;
}
public Object execute(CommandSession session) throws Exception {
Map<Number, DefaultRevisionEntity> revisions = dpService.getRevisions(Long.valueOf( id ));
for (Number revisionNum : revisions.keySet()) {
DefaultRevisionEntity dre = revisions.get( revisionNum );
System.out.println(revisionNum + ": " + dre.getId() + ", " + dre.getTimestamp());
}
return null;
}
}

View File

@ -0,0 +1,43 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.hibernate.osgitest.command;
import org.apache.felix.gogo.commands.Action;
import org.apache.felix.gogo.commands.Argument;
import org.apache.felix.gogo.commands.Command;
import org.apache.felix.service.command.CommandSession;
import org.hibernate.osgitest.DataPointService;
import org.hibernate.osgitest.entity.DataPoint;
@Command(scope = "dp", name = "load")
public class LoadCommand implements Action {
@Argument(index = 0, name = "Id", required = true, description = "Id", multiValued = false)
String id;
private DataPointService dpService;
public void setDpService(DataPointService dpService) {
this.dpService = dpService;
}
public Object execute(CommandSession session) throws Exception {
DataPoint dp = dpService.load( Long.valueOf( id ) );
System.out.println( dp.getId() + ", " + dp.getName() );
return null;
}
}

View File

@ -0,0 +1,47 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.hibernate.osgitest.command;
import org.apache.felix.gogo.commands.Action;
import org.apache.felix.gogo.commands.Argument;
import org.apache.felix.gogo.commands.Command;
import org.apache.felix.service.command.CommandSession;
import org.hibernate.osgitest.DataPointService;
import org.hibernate.osgitest.entity.DataPoint;
@Command(scope = "dp", name = "update")
public class UpdateCommand implements Action {
@Argument(index=0, name="Id", required=true, description="Id", multiValued=false)
String id;
@Argument(index=1, name="Name", required=true, description="Name", multiValued=false)
String name;
private DataPointService dpService;
public void setDpService(DataPointService dpService) {
this.dpService = dpService;
}
public Object execute(CommandSession session) throws Exception {
DataPoint dp = dpService.get( Long.valueOf( id ) );
dp.setName( name );
dpService.update( dp );
return null;
}
}

View File

@ -0,0 +1,58 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* JBoss, Home of Professional Open Source
* Copyright 2013 Red Hat Inc. and/or its affiliates and other contributors
* as indicated by the @authors tag. All rights reserved.
* See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* 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, v. 2.1.
* This program is distributed in the hope that it will be useful, but WITHOUT A
* 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,
* v.2.1 along with this distribution; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
package org.hibernate.osgitest.entity;
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import org.hibernate.envers.Audited;
/**
* @author Brett Meyer
*/
@Entity
@Audited
public class DataPoint implements Serializable {
@Id
@GeneratedValue
private long id;
private String name;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

View File

@ -0,0 +1,72 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<blueprint default-activation="eager"
xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<bean id="dpService" class="org.hibernate.osgitest.DataPointServiceImpl"/>
<service ref="dpService" interface="org.hibernate.osgitest.DataPointService" />
<!-- This demonstrates how to register your custom implementations of Hibernate extension points, such as
Integrator and TypeContributor. -->
<!-- <bean id="integrator" class="your.package.IntegratorImpl"/>
<service ref="integrator" interface="org.hibernate.integrator.spi.Integrator"/>
<bean id="typeContributor" class="your.package.TypeContributorImpl"/>
<service ref="typeContributor" interface="org.hibernate.metamodel.spi.TypeContributor"/> -->
<!-- This bundle makes use of Karaf commands to demonstrate core persistence operations. Feel free to remove it. -->
<command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.1.0">
<command name="dp:add">
<action class="org.hibernate.osgitest.command.AddCommand">
<property name="dpService" ref="dpService"/>
</action>
</command>
<command name="dp:update">
<action class="org.hibernate.osgitest.command.UpdateCommand">
<property name="dpService" ref="dpService"/>
</action>
</command>
<command name="dp:get">
<action class="org.hibernate.osgitest.command.GetCommand">
<property name="dpService" ref="dpService"/>
</action>
</command>
<command name="dp:load">
<action class="org.hibernate.osgitest.command.LoadCommand">
<property name="dpService" ref="dpService"/>
</action>
</command>
<command name="dp:getAll">
<action class="org.hibernate.osgitest.command.GetAllCommand">
<property name="dpService" ref="dpService"/>
</action>
</command>
<command name="dp:getRevisions">
<action class="org.hibernate.osgitest.command.GetRevisionsCommand">
<property name="dpService" ref="dpService"/>
</action>
</command>
<command name="dp:deleteAll">
<action class="org.hibernate.osgitest.command.DeleteAllCommand">
<property name="dpService" ref="dpService"/>
</action>
</command>
</command-bundle>
</blueprint>

View File

@ -0,0 +1,111 @@
<!--
~ Hibernate, Relational Persistence for Idiomatic Java
~
~ Copyright (c) 2007, 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
-->
<ehcache>
<!-- Sets the path to the directory where cache .data files are created.
If the path is a Java System Property it is replaced by
its value in the running VM.
The following properties are translated:
user.home - User's home directory
user.dir - User's current working directory
java.io.tmpdir - Default temp file path -->
<diskStore path="./target/tmp"/>
<!--Default Cache configuration. These will applied to caches programmatically created through
the CacheManager.
The following attributes are required for defaultCache:
maxInMemory - Sets the maximum number of objects that will be created in memory
eternal - Sets whether elements are eternal. If eternal, timeouts are ignored and the element
is never expired.
timeToIdleSeconds - Sets the time to idle for an element before it expires. Is only used
if the element is not eternal. Idle time is now - last accessed time
timeToLiveSeconds - Sets the time to live for an element before it expires. Is only used
if the element is not eternal. TTL is now - creation time
overflowToDisk - Sets whether elements can overflow to disk when the in-memory cache
has reached the maxInMemory limit.
-->
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"
/>
<!--Predefined caches. Add your cache configuration settings here.
If you do not have a configuration for your cache a WARNING will be issued when the
CacheManager starts
The following attributes are required for defaultCache:
name - Sets the name of the cache. This is used to identify the cache. It must be unique.
maxInMemory - Sets the maximum number of objects that will be created in memory
eternal - Sets whether elements are eternal. If eternal, timeouts are ignored and the element
is never expired.
timeToIdleSeconds - Sets the time to idle for an element before it expires. Is only used
if the element is not eternal. Idle time is now - last accessed time
timeToLiveSeconds - Sets the time to live for an element before it expires. Is only used
if the element is not eternal. TTL is now - creation time
overflowToDisk - Sets whether elements can overflow to disk when the in-memory cache
has reached the maxInMemory limit.
-->
<!-- Sample cache named sampleCache1
This cache contains a maximum in memory of 10000 elements, and will expire
an element if it is idle for more than 5 minutes and lives for more than
10 minutes.
If there are more than 10000 elements it will overflow to the
disk cache, which in this configuration will go to wherever java.io.tmp is
defined on your system. On a standard Linux system this will be /tmp"
-->
<cache name="sampleCache1"
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
overflowToDisk="true"
/>
<!-- Sample cache named sampleCache2
This cache contains 1000 elements. Elements will always be held in memory.
They are not expired. -->
<cache name="sampleCache2"
maxElementsInMemory="1000"
eternal="true"
timeToIdleSeconds="0"
timeToLiveSeconds="0"
overflowToDisk="false"
/> -->
<!-- Place configuration for your caches following -->
</ehcache>

View File

@ -0,0 +1,46 @@
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">org.h2.Driver</property>
<property name="hibernate.connection.url">jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1;MVCC=TRUE</property>
<property name="hibernate.connection.username">sa</property>
<property name="hibernate.connection.password"></property>
<property name="hibernate.dialect">org.hibernate.dialect.H2Dialect</property>
<property name="hibernate.hbm2ddl.auto">create-drop</property>
<!-- <property name="hibernate.connection.pool_size">5</property>
<property name="hibernate.c3p0.min_size">50</property>
<property name="hibernate.c3p0.max_size">800</property>
<property name="hibernate.c3p0.max_statements">50</property>
<property name="hibernate.jdbc.batch_size">10</property>
<property name="hibernate.c3p0.timeout">300</property>
<property name="hibernate.c3p0.idle_test_period">3000</property>
<property name="hibernate.c3p0.testConnectionOnCheckout">true</property> -->
<!-- <property name="hibernate.connection.pool_size">5</property>
<property name="hibernate.jdbc.batch_size">10</property>
<property name="hibernate.connection.provider_class">proxool</property>
<property name="hibernate.proxool.properties">pool-one.properties</property>
<property name="hibernate.proxool.pool_alias">pool-one</property> -->
<!-- <property name="hibernate.cache.region_prefix">hibernate.test</property>
<property name="cache.use_query_cache">true</property>
<property name="cache.use_second_level_cache">true</property>
<property name="cache.use_structured_entries">true</property>
<property name="cache.region.factory_class">org.hibernate.cache.EhCacheRegionFactory</property>
<property name="net.sf.ehcache.configurationResourceName">file:///[PATH]/unmanaged-jpa/src/main/resources/ehcache.xml</property> -->
<!-- <property name="hibernate.cache.region_prefix">hibernate.test</property>
<property name="cache.use_query_cache">true</property>
<property name="cache.use_second_level_cache">true</property>
<property name="cache.use_structured_entries">true</property>
<property name="cache.region.factory_class">org.hibernate.cache.infinispan.InfinispanRegionFactory</property> -->
<mapping class="org.hibernate.osgitest.entity.DataPoint"/>
</session-factory>
</hibernate-configuration>

View File

@ -0,0 +1,7 @@
jdbc-0.proxool.alias=pool-one
jdbc-0.proxool.driver-url=jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1;MVCC=TRUE
jdbc-0.proxool.driver-class=org.h2.Driver
jdbc-0.user=sa
jdbc-0.password=
jdbc-0.proxool.maximum-connection-count=2
jdbc-0.proxool.house-keeping-test-sql=select CURRENT_DATE

View File

@ -44,6 +44,7 @@
<module>annotations</module>
<module>entitymanager</module>
<module>envers</module>
<module>osgi</module>
</modules>
<dependencies>

View File

@ -64,7 +64,14 @@ jar {
// Temporarily support JTA 1.1 -- Karaf and other frameworks still
// use it. Without this, the plugin generates [1.2,2).
// build.gradle adds javax.transaction for all modules
'javax.transaction.xa;version="[1.1,2)"'
'javax.transaction.xa;version="[1.1,2)"',
// optionals
'javax.management;resolution:=optional',
'javax.naming.event;resolution:=optional',
'javax.naming.spi;resolution:=optional',
'org.apache.tools.ant;resolution:=optional',
'org.apache.tools.ant.taskdefs;resolution:=optional',
'org.apache.tools.ant.types;resolution:=optional'
// TODO: Uncomment once EntityManagerFactoryBuilderImpl no longer
// uses ClassLoaderServiceImpl.

View File

@ -0,0 +1,74 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008-2011, 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
*/
package org.hibernate.action.internal;
import java.io.Serializable;
import org.hibernate.HibernateException;
import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.persister.collection.CollectionPersister;
/**
* If a collection is extra lazy and has queued ops, we still need to
* process them. Ex: OneToManyPersister needs to insert indexes for List
* collections. See HHH-8083.
*
* @author Brett Meyer
*/
public final class QueuedOperationCollectionAction extends CollectionAction {
/**
* Constructs a CollectionUpdateAction
*
* @param collection The collection to update
* @param persister The collection persister
* @param id The collection key
* @param session The session
*/
public QueuedOperationCollectionAction(
final PersistentCollection collection,
final CollectionPersister persister,
final Serializable id,
final SessionImplementor session) {
super( persister, collection, id, session );
}
@Override
public void execute() throws HibernateException {
final Serializable id = getKey();
final SessionImplementor session = getSession();
final CollectionPersister persister = getPersister();
final PersistentCollection collection = getCollection();
persister.processQueuedOps( collection, id, session );
}
}

View File

@ -272,7 +272,7 @@ public final class AnnotationBinder {
(List<NamedStoredProcedureQuery>) defaults.get( NamedStoredProcedureQuery.class );
if ( annotations != null ) {
for ( NamedStoredProcedureQuery annotation : annotations ) {
QueryBinder.bindNamedStoredProcedureQuery( annotation, mappings );
bindNamedStoredProcedureQuery( mappings, annotation, true );
}
}
}
@ -281,9 +281,7 @@ public final class AnnotationBinder {
(List<NamedStoredProcedureQueries>) defaults.get( NamedStoredProcedureQueries.class );
if ( annotations != null ) {
for ( NamedStoredProcedureQueries annotation : annotations ) {
for ( NamedStoredProcedureQuery queryAnnotation : annotation.value() ) {
QueryBinder.bindNamedStoredProcedureQuery( queryAnnotation, mappings );
}
bindNamedStoredProcedureQueries( mappings, annotation, true );
}
}
}
@ -394,24 +392,30 @@ public final class AnnotationBinder {
}
// NamedStoredProcedureQuery handling ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
{
final NamedStoredProcedureQuery annotation = annotatedElement.getAnnotation( NamedStoredProcedureQuery.class );
if ( annotation != null ) {
QueryBinder.bindNamedStoredProcedureQuery( annotation, mappings );
}
}
bindNamedStoredProcedureQuery( mappings, annotatedElement.getAnnotation( NamedStoredProcedureQuery.class ), false );
// NamedStoredProcedureQueries handling ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
{
final NamedStoredProcedureQueries annotation = annotatedElement.getAnnotation( NamedStoredProcedureQueries.class );
if ( annotation != null ) {
for ( NamedStoredProcedureQuery queryAnnotation : annotation.value() ) {
QueryBinder.bindNamedStoredProcedureQuery( queryAnnotation, mappings );
}
bindNamedStoredProcedureQueries(
mappings,
annotatedElement.getAnnotation( NamedStoredProcedureQueries.class ),
false
);
}
private static void bindNamedStoredProcedureQueries(Mappings mappings, NamedStoredProcedureQueries annotation, boolean isDefault) {
if ( annotation != null ) {
for ( NamedStoredProcedureQuery queryAnnotation : annotation.value() ) {
bindNamedStoredProcedureQuery( mappings, queryAnnotation, isDefault );
}
}
}
private static void bindNamedStoredProcedureQuery(Mappings mappings, NamedStoredProcedureQuery annotation, boolean isDefault) {
if ( annotation != null ) {
QueryBinder.bindNamedStoredProcedureQuery( annotation, mappings, isDefault );
}
}
private static IdGenerator buildIdGenerator(java.lang.annotation.Annotation ann, Mappings mappings) {
IdGenerator idGen = new IdGenerator();
if ( mappings.getSchemaName() != null ) {

View File

@ -263,6 +263,8 @@ public class Configuration implements Serializable {
private Set<String> defaultNamedQueryNames;
private Set<String> defaultNamedNativeQueryNames;
private Set<String> defaultSqlResultSetMappingNames;
private Set<String> defaultNamedProcedure;
private Set<String> defaultNamedGenerators;
private Map<String, Properties> generatorTables;
private Map<Table, List<UniqueConstraintHolder>> uniqueConstraintHoldersByTable;
@ -303,7 +305,7 @@ public class Configuration implements Serializable {
namedSqlQueries = new HashMap<String,NamedSQLQueryDefinition>();
sqlResultSetMappings = new HashMap<String, ResultSetMappingDefinition>();
namedEntityGraphMap = new HashMap<String, NamedEntityGraphDefinition>();
namedProcedureCallMap = new HashMap<String, NamedProcedureCallDefinition>( );
typeDefs = new HashMap<String,TypeDef>();
filterDefinitions = new HashMap<String, FilterDefinition>();
fetchProfiles = new HashMap<String, FetchProfile>();
@ -339,6 +341,7 @@ public class Configuration implements Serializable {
defaultNamedQueryNames = new HashSet<String>();
defaultNamedNativeQueryNames = new HashSet<String>();
defaultSqlResultSetMappingNames = new HashSet<String>();
defaultNamedProcedure = new HashSet<String>( );
defaultNamedGenerators = new HashSet<String>();
uniqueConstraintHoldersByTable = new HashMap<Table, List<UniqueConstraintHolder>>();
jpaIndexHoldersByTable = new HashMap<Table,List<JPAIndexHolder>>( );
@ -2890,16 +2893,25 @@ public class Configuration implements Serializable {
public void addNamedProcedureCallDefinition(NamedProcedureCallDefinition definition)
throws DuplicateMappingException {
final String name = definition.getRegisteredName();
final NamedProcedureCallDefinition previous = namedProcedureCallMap.put( name, definition );
if ( previous != null ) {
throw new DuplicateMappingException( "named stored procedure query", name );
if ( !defaultNamedProcedure.contains( name ) ) {
final NamedProcedureCallDefinition previous = namedProcedureCallMap.put( name, definition );
if ( previous != null ) {
throw new DuplicateMappingException( "named stored procedure query", name );
}
}
}
@Override
public void addDefaultNamedProcedureCallDefinition(NamedProcedureCallDefinition definition)
throws DuplicateMappingException {
addNamedProcedureCallDefinition( definition );
defaultNamedProcedure.add( definition.getRegisteredName() );
}
@Override
public void addNamedEntityGraphDefintion(NamedEntityGraphDefinition definition)
throws DuplicateMappingException {
final String name = definition.getRegisteredName();
final NamedEntityGraphDefinition previous = namedEntityGraphMap.put( name, definition );
if ( previous != null ) {
throw new DuplicateMappingException( "NamedEntityGraph", name );

View File

@ -348,6 +348,17 @@ public interface Mappings {
*/
public void addNamedProcedureCallDefinition(NamedProcedureCallDefinition definition) throws DuplicateMappingException;
/**
* Adds metadata for a named stored procedure call to this repository.
*
* @param definition The procedure call information
*
* @throws DuplicateMappingException If a query already exists with that name.
*/
public void addDefaultNamedProcedureCallDefinition(NamedProcedureCallDefinition definition) throws DuplicateMappingException;
/**
* Adds metadata for a named entity graph to this repository
*

View File

@ -25,6 +25,8 @@ package org.hibernate.cfg.annotations;
import javax.persistence.NamedEntityGraph;
import org.hibernate.internal.util.StringHelper;
/**
* Models the definition of a {@link NamedEntityGraph} annotation
*
@ -34,15 +36,17 @@ public class NamedEntityGraphDefinition {
private final NamedEntityGraph annotation;
private final String jpaEntityName;
private final String entityName;
private final String name;
public NamedEntityGraphDefinition(NamedEntityGraph annotation, String jpaEntityName, String entityName) {
this.annotation = annotation;
this.jpaEntityName = jpaEntityName;
this.entityName = entityName;
this.name = StringHelper.isEmpty( annotation.name() ) ? jpaEntityName : annotation.name();
}
public String getRegisteredName() {
return jpaEntityName;
return name;
}
public String getJpaEntityName() {

View File

@ -25,25 +25,20 @@ package org.hibernate.cfg.annotations;
import javax.persistence.NamedStoredProcedureQuery;
import javax.persistence.ParameterMode;
import javax.persistence.QueryHint;
import javax.persistence.StoredProcedureParameter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.hibernate.LockMode;
import org.hibernate.MappingException;
import org.hibernate.engine.ResultSetMappingDefinition;
import org.hibernate.engine.query.spi.sql.NativeSQLQueryReturn;
import org.hibernate.engine.query.spi.sql.NativeSQLQueryRootReturn;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.internal.SessionFactoryImpl;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.procedure.ProcedureCallMemento;
import org.hibernate.procedure.internal.ParameterStrategy;
import org.hibernate.procedure.internal.ProcedureCallMementoImpl;
@ -65,7 +60,7 @@ public class NamedProcedureCallDefinition {
private final Class[] resultClasses;
private final String[] resultSetMappings;
private final ParameterDefinitions parameterDefinitions;
private final Map<String,Object> hints;
private final Map<String, Object> hints;
NamedProcedureCallDefinition(NamedStoredProcedureQuery annotation) {
this.registeredName = annotation.name();
@ -73,7 +68,7 @@ public class NamedProcedureCallDefinition {
this.resultClasses = annotation.resultClasses();
this.resultSetMappings = annotation.resultSetMappings();
this.parameterDefinitions = new ParameterDefinitions( annotation.parameters() );
this.hints = extract( annotation.hints() );
this.hints = new QueryHintDefinition( annotation.hints() ).getHintsMap();
final boolean specifiesResultClasses = resultClasses != null && resultClasses.length > 0;
final boolean specifiesResultSetMappings = resultSetMappings != null && resultSetMappings.length > 0;
@ -88,17 +83,6 @@ public class NamedProcedureCallDefinition {
}
}
private Map<String, Object> extract(QueryHint[] hints) {
if ( hints == null || hints.length == 0 ) {
return Collections.emptyMap();
}
final Map<String,Object> hintsMap = new HashMap<String, Object>();
for ( QueryHint hint : hints ) {
hintsMap.put( hint.name(), hint.value() );
}
return hintsMap;
}
public String getRegisteredName() {
return registeredName;
}
@ -201,7 +185,7 @@ public class NamedProcedureCallDefinition {
public List<ParameterMemento> toMementos(SessionFactoryImpl sessionFactory) {
final List<ParameterMemento> mementos = new ArrayList<ParameterMemento>();
for ( ParameterDefinition definition : parameterDefinitions ) {
definition.toMemento( sessionFactory );
mementos.add(definition.toMemento( sessionFactory ));
}
return mementos;
}

View File

@ -24,13 +24,11 @@
package org.hibernate.cfg.annotations;
import java.util.HashMap;
import javax.persistence.LockModeType;
import javax.persistence.NamedNativeQueries;
import javax.persistence.NamedNativeQuery;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.NamedStoredProcedureQuery;
import javax.persistence.QueryHint;
import javax.persistence.SqlResultSetMapping;
import javax.persistence.SqlResultSetMappings;
@ -41,9 +39,9 @@ import org.hibernate.AssertionFailure;
import org.hibernate.CacheMode;
import org.hibernate.FlushMode;
import org.hibernate.LockMode;
import org.hibernate.LockOptions;
import org.hibernate.annotations.CacheModeType;
import org.hibernate.annotations.FlushModeType;
import org.hibernate.annotations.QueryHints;
import org.hibernate.cfg.BinderHelper;
import org.hibernate.cfg.Mappings;
import org.hibernate.cfg.NotYetImplementedException;
@ -54,7 +52,6 @@ import org.hibernate.engine.spi.NamedQueryDefinitionBuilder;
import org.hibernate.engine.spi.NamedSQLQueryDefinition;
import org.hibernate.engine.spi.NamedSQLQueryDefinitionBuilder;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.LockModeConverter;
/**
* Query binder
@ -70,19 +67,19 @@ public abstract class QueryBinder {
throw new AnnotationException( "A named query must have a name when used in class or package level" );
}
//EJBQL Query
QueryHint[] hints = queryAnn.hints();
QueryHintDefinition hints = new QueryHintDefinition( queryAnn.hints() );
String queryName = queryAnn.query();
NamedQueryDefinition queryDefinition = new NamedQueryDefinitionBuilder( queryAnn.name() )
.setLockOptions( determineLockOptions( queryAnn, hints ) )
.setLockOptions( hints.determineLockOptions( queryAnn ) )
.setQuery( queryName )
.setCacheable( getBoolean( queryName, "org.hibernate.cacheable", hints ) )
.setCacheRegion( getString( queryName, "org.hibernate.cacheRegion", hints ) )
.setTimeout( getTimeout( queryName, hints ) )
.setFetchSize( getInteger( queryName, "org.hibernate.fetchSize", hints ) )
.setFlushMode( getFlushMode( queryName, hints ) )
.setCacheMode( getCacheMode( queryName, hints ) )
.setReadOnly( getBoolean( queryName, "org.hibernate.readOnly", hints ) )
.setComment( getString( queryName, "org.hibernate.comment", hints ) )
.setCacheable( hints.getBoolean( queryName, QueryHints.CACHEABLE ) )
.setCacheRegion( hints.getString( queryName, QueryHints.CACHE_REGION ) )
.setTimeout( hints.getTimeout( queryName ) )
.setFetchSize( hints.getInteger( queryName, QueryHints.FETCH_SIZE ) )
.setFlushMode( hints.getFlushMode( queryName ) )
.setCacheMode( hints.getCacheMode( queryName ) )
.setReadOnly( hints.getBoolean( queryName, QueryHints.READ_ONLY ) )
.setComment( hints.getString( queryName, QueryHints.COMMENT ) )
.setParameterTypes( null )
.createNamedQueryDefinition();
@ -97,17 +94,7 @@ public abstract class QueryBinder {
}
}
private static LockOptions determineLockOptions(NamedQuery namedQueryAnnotation, QueryHint[] hints) {
LockModeType lockModeType = namedQueryAnnotation.lockMode();
Integer lockTimeoutHint = getInteger( namedQueryAnnotation.name(), "javax.persistence.lock.timeout", hints );
LockOptions lockOptions = new LockOptions( LockModeConverter.convertToLockMode( lockModeType ) );
if ( lockTimeoutHint != null ) {
lockOptions.setTimeOut( lockTimeoutHint );
}
return lockOptions;
}
public static void bindNativeQuery(NamedNativeQuery queryAnn, Mappings mappings, boolean isDefault) {
if ( queryAnn == null ) return;
@ -116,22 +103,22 @@ public abstract class QueryBinder {
throw new AnnotationException( "A named query must have a name when used in class or package level" );
}
String resultSetMapping = queryAnn.resultSetMapping();
QueryHint[] hints = queryAnn.hints();
QueryHintDefinition hints = new QueryHintDefinition( queryAnn.hints() );
String queryName = queryAnn.query();
NamedSQLQueryDefinitionBuilder builder = new NamedSQLQueryDefinitionBuilder( queryAnn.name() )
.setQuery( queryName )
.setQuerySpaces( null )
.setCacheable( getBoolean( queryName, "org.hibernate.cacheable", hints ) )
.setCacheRegion( getString( queryName, "org.hibernate.cacheRegion", hints ) )
.setTimeout( getTimeout( queryName, hints ) )
.setFetchSize( getInteger( queryName, "org.hibernate.fetchSize", hints ) )
.setFlushMode( getFlushMode( queryName, hints ) )
.setCacheMode( getCacheMode( queryName, hints ) )
.setReadOnly( getBoolean( queryName, "org.hibernate.readOnly", hints ) )
.setComment( getString( queryName, "org.hibernate.comment", hints ) )
.setCacheable( hints.getBoolean( queryName, QueryHints.CACHEABLE ) )
.setCacheRegion( hints.getString( queryName, QueryHints.CACHE_REGION ) )
.setTimeout( hints.getTimeout( queryName ) )
.setFetchSize( hints.getInteger( queryName, QueryHints.FETCH_SIZE ) )
.setFlushMode( hints.getFlushMode( queryName ) )
.setCacheMode( hints.getCacheMode( queryName ) )
.setReadOnly( hints.getBoolean( queryName, QueryHints.READ_ONLY ) )
.setComment( hints.getString( queryName, QueryHints.COMMENT ) )
.setParameterTypes( null )
.setCallable( getBoolean( queryName, "org.hibernate.callable", hints ) );
.setCallable( hints.getBoolean( queryName, QueryHints.CALLABLE ) );
if ( !BinderHelper.isEmptyAnnotationValue( resultSetMapping ) ) {
//sql result set usage
@ -332,7 +319,7 @@ public abstract class QueryBinder {
}
}
public static void bindNamedStoredProcedureQuery(NamedStoredProcedureQuery annotation, Mappings mappings) {
public static void bindNamedStoredProcedureQuery(NamedStoredProcedureQuery annotation, Mappings mappings, boolean isDefault) {
if ( annotation == null ) {
return;
}
@ -342,7 +329,12 @@ public abstract class QueryBinder {
}
final NamedProcedureCallDefinition def = new NamedProcedureCallDefinition( annotation );
mappings.addNamedProcedureCallDefinition( def );
if(isDefault){
mappings.addDefaultNamedProcedureCallDefinition( def );
} else{
mappings.addNamedProcedureCallDefinition( def );
}
LOG.debugf( "Bound named stored procedure query : %s => %s", def.getRegisteredName(), def.getProcedureName() );
}
@ -359,109 +351,5 @@ public abstract class QueryBinder {
mappings.addSecondPass( new ResultsetMappingSecondPass( ann, mappings, isDefault ) );
}
private static CacheMode getCacheMode(String query, QueryHint[] hints) {
for (QueryHint hint : hints) {
if ( "org.hibernate.cacheMode".equals( hint.name() ) ) {
if ( hint.value().equalsIgnoreCase( CacheMode.GET.toString() ) ) {
return CacheMode.GET;
}
else if ( hint.value().equalsIgnoreCase( CacheMode.IGNORE.toString() ) ) {
return CacheMode.IGNORE;
}
else if ( hint.value().equalsIgnoreCase( CacheMode.NORMAL.toString() ) ) {
return CacheMode.NORMAL;
}
else if ( hint.value().equalsIgnoreCase( CacheMode.PUT.toString() ) ) {
return CacheMode.PUT;
}
else if ( hint.value().equalsIgnoreCase( CacheMode.REFRESH.toString() ) ) {
return CacheMode.REFRESH;
}
else {
throw new AnnotationException( "Unknown CacheMode in hint: " + query + ":" + hint.name() );
}
}
}
return null;
}
private static FlushMode getFlushMode(String query, QueryHint[] hints) {
for (QueryHint hint : hints) {
if ( "org.hibernate.flushMode".equals( hint.name() ) ) {
if ( hint.value().equalsIgnoreCase( FlushMode.ALWAYS.toString() ) ) {
return FlushMode.ALWAYS;
}
else if ( hint.value().equalsIgnoreCase( FlushMode.AUTO.toString() ) ) {
return FlushMode.AUTO;
}
else if ( hint.value().equalsIgnoreCase( FlushMode.COMMIT.toString() ) ) {
return FlushMode.COMMIT;
}
else if ( hint.value().equalsIgnoreCase( FlushMode.NEVER.toString() ) ) {
return FlushMode.MANUAL;
}
else if ( hint.value().equalsIgnoreCase( FlushMode.MANUAL.toString() ) ) {
return FlushMode.MANUAL;
}
else {
throw new AnnotationException( "Unknown FlushMode in hint: " + query + ":" + hint.name() );
}
}
}
return null;
}
private static boolean getBoolean(String query, String hintName, QueryHint[] hints) {
for (QueryHint hint : hints) {
if ( hintName.equals( hint.name() ) ) {
if ( hint.value().equalsIgnoreCase( "true" ) ) {
return true;
}
else if ( hint.value().equalsIgnoreCase( "false" ) ) {
return false;
}
else {
throw new AnnotationException( "Not a boolean in hint: " + query + ":" + hint.name() );
}
}
}
return false;
}
private static String getString(String query, String hintName, QueryHint[] hints) {
for (QueryHint hint : hints) {
if ( hintName.equals( hint.name() ) ) {
return hint.value();
}
}
return null;
}
private static Integer getInteger(String query, String hintName, QueryHint[] hints) {
for (QueryHint hint : hints) {
if ( hintName.equals( hint.name() ) ) {
try {
return Integer.decode( hint.value() );
}
catch (NumberFormatException nfe) {
throw new AnnotationException( "Not an integer in hint: " + query + ":" + hint.name(), nfe );
}
}
}
return null;
}
private static Integer getTimeout(String queryName, QueryHint[] hints) {
Integer timeout = getInteger( queryName, "javax.persistence.query.timeout", hints );
if ( timeout != null ) {
// convert milliseconds to seconds
timeout = (int)Math.round(timeout.doubleValue() / 1000.0 );
}
else {
// timeout is already in seconds
timeout = getInteger( queryName, "org.hibernate.timeout", hints );
}
return timeout;
}
}

View File

@ -0,0 +1,152 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2013, 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
*/
package org.hibernate.cfg.annotations;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import javax.persistence.LockModeType;
import javax.persistence.NamedQuery;
import javax.persistence.QueryHint;
import org.hibernate.AnnotationException;
import org.hibernate.CacheMode;
import org.hibernate.FlushMode;
import org.hibernate.LockOptions;
import org.hibernate.MappingException;
import org.hibernate.annotations.QueryHints;
import org.hibernate.internal.util.LockModeConverter;
/**
* @author Strong Liu <stliu@hibernate.org>
*/
public class QueryHintDefinition {
private final Map<String, Object> hintsMap;
public QueryHintDefinition(final QueryHint[] hints) {
if ( hints == null || hints.length == 0 ) {
hintsMap = Collections.emptyMap();
}
else {
final Map<String, Object> hintsMap = new HashMap<String, Object>();
for ( QueryHint hint : hints ) {
hintsMap.put( hint.name(), hint.value() );
}
this.hintsMap = hintsMap;
}
}
public CacheMode getCacheMode(String query) {
String hitName = QueryHints.CACHE_MODE;
String value =(String) hintsMap.get( hitName );
if ( value == null ) {
return null;
}
try {
return CacheMode.interpretExternalSetting( value );
}
catch ( MappingException e ) {
throw new AnnotationException( "Unknown CacheMode in hint: " + query + ":" + hitName, e );
}
}
public FlushMode getFlushMode(String query) {
String hitName = QueryHints.FLUSH_MODE;
String value =(String) hintsMap.get( hitName );
if ( value == null ) {
return null;
}
try {
return FlushMode.interpretExternalSetting( value );
}
catch ( MappingException e ) {
throw new AnnotationException( "Unknown FlushMode in hint: " + query + ":" + hitName, e );
}
}
public boolean getBoolean(String query, String hintName) {
String value =(String) hintsMap.get( hintName );
if ( value == null ) {
return false;
}
if ( value.equalsIgnoreCase( "true" ) ) {
return true;
}
else if ( value.equalsIgnoreCase( "false" ) ) {
return false;
}
else {
throw new AnnotationException( "Not a boolean in hint: " + query + ":" + hintName );
}
}
public String getString(String query, String hintName) {
return (String) hintsMap.get( hintName );
}
public Integer getInteger(String query, String hintName) {
String value = (String) hintsMap.get( hintName );
if ( value == null ) {
return null;
}
try {
return Integer.decode( value );
}
catch ( NumberFormatException nfe ) {
throw new AnnotationException( "Not an integer in hint: " + query + ":" + hintName, nfe );
}
}
public Integer getTimeout(String queryName) {
Integer timeout = getInteger( queryName, QueryHints.TIMEOUT_JPA );
if ( timeout != null ) {
// convert milliseconds to seconds
timeout = (int) Math.round( timeout.doubleValue() / 1000.0 );
}
else {
// timeout is already in seconds
timeout = getInteger( queryName, QueryHints.TIMEOUT_HIBERNATE );
}
return timeout;
}
public LockOptions determineLockOptions(NamedQuery namedQueryAnnotation) {
LockModeType lockModeType = namedQueryAnnotation.lockMode();
Integer lockTimeoutHint = getInteger( namedQueryAnnotation.name(), "javax.persistence.lock.timeout" );
LockOptions lockOptions = new LockOptions( LockModeConverter.convertToLockMode( lockModeType ) );
if ( lockTimeoutHint != null ) {
lockOptions.setTimeOut( lockTimeoutHint );
}
return lockOptions;
}
public Map<String, Object> getHintsMap() {
return hintsMap;
}
}

View File

@ -33,6 +33,7 @@ import java.util.Map;
import javax.persistence.EntityListeners;
import javax.persistence.NamedNativeQuery;
import javax.persistence.NamedQuery;
import javax.persistence.NamedStoredProcedureQuery;
import javax.persistence.SequenceGenerator;
import javax.persistence.SqlResultSetMapping;
import javax.persistence.TableGenerator;
@ -49,6 +50,7 @@ import org.hibernate.internal.util.ReflectHelper;
*
* @author Emmanuel Bernard
*/
@SuppressWarnings("unchecked")
public class JPAMetadataProvider implements MetadataProvider, Serializable {
private transient MetadataProvider delegate = new JavaMetadataProvider();
private transient Map<Object, Object> defaults;
@ -152,6 +154,16 @@ public class JPAMetadataProvider implements MetadataProvider, Serializable {
element, xmlDefaults
);
sqlResultSetMappings.addAll( currentSqlResultSetMappings );
List<NamedStoredProcedureQuery> namedStoredProcedureQueries = (List<NamedStoredProcedureQuery>)defaults.get( NamedStoredProcedureQuery.class );
if(namedStoredProcedureQueries==null){
namedStoredProcedureQueries = new ArrayList<NamedStoredProcedureQuery>( );
defaults.put( NamedStoredProcedureQuery.class, namedStoredProcedureQueries );
}
List<NamedStoredProcedureQuery> currentNamedStoredProcedureQueries = JPAOverriddenAnnotationReader.buildNamedStoreProcedureQueries(
element, xmlDefaults
);
namedStoredProcedureQueries.addAll( currentNamedStoredProcedureQueries );
}
}
return defaults;

View File

@ -88,14 +88,21 @@ import javax.persistence.MapKeyJoinColumns;
import javax.persistence.MapKeyTemporal;
import javax.persistence.MappedSuperclass;
import javax.persistence.MapsId;
import javax.persistence.NamedAttributeNode;
import javax.persistence.NamedEntityGraph;
import javax.persistence.NamedEntityGraphs;
import javax.persistence.NamedNativeQueries;
import javax.persistence.NamedNativeQuery;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.NamedStoredProcedureQueries;
import javax.persistence.NamedStoredProcedureQuery;
import javax.persistence.NamedSubgraph;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.OrderBy;
import javax.persistence.OrderColumn;
import javax.persistence.ParameterMode;
import javax.persistence.PostLoad;
import javax.persistence.PostPersist;
import javax.persistence.PostRemove;
@ -111,6 +118,7 @@ import javax.persistence.SecondaryTables;
import javax.persistence.SequenceGenerator;
import javax.persistence.SqlResultSetMapping;
import javax.persistence.SqlResultSetMappings;
import javax.persistence.StoredProcedureParameter;
import javax.persistence.Table;
import javax.persistence.TableGenerator;
import javax.persistence.Temporal;
@ -176,10 +184,14 @@ public class JPAOverriddenAnnotationReader implements AnnotationReader {
annotationToXml.put( DiscriminatorColumn.class, "discriminator-column" );
annotationToXml.put( SequenceGenerator.class, "sequence-generator" );
annotationToXml.put( TableGenerator.class, "table-generator" );
annotationToXml.put( NamedEntityGraph.class, "named-entity-graph" );
annotationToXml.put( NamedEntityGraphs.class, "named-entity-graph" );
annotationToXml.put( NamedQuery.class, "named-query" );
annotationToXml.put( NamedQueries.class, "named-query" );
annotationToXml.put( NamedNativeQuery.class, "named-native-query" );
annotationToXml.put( NamedNativeQueries.class, "named-native-query" );
annotationToXml.put( NamedStoredProcedureQuery.class, "named-stored-procedure-query" );
annotationToXml.put( NamedStoredProcedureQueries.class, "named-stored-procedure-query" );
annotationToXml.put( SqlResultSetMapping.class, "sql-result-set-mapping" );
annotationToXml.put( SqlResultSetMappings.class, "sql-result-set-mapping" );
annotationToXml.put( ExcludeDefaultListeners.class, "exclude-default-listeners" );
@ -357,6 +369,8 @@ public class JPAOverriddenAnnotationReader implements AnnotationReader {
addIfNotNull( annotationList, getTableGenerator( tree, defaults ) );
addIfNotNull( annotationList, getNamedQueries( tree, defaults ) );
addIfNotNull( annotationList, getNamedNativeQueries( tree, defaults ) );
addIfNotNull( annotationList, getNamedStoredProcedureQueries( tree, defaults ) );
addIfNotNull( annotationList, getNamedEntityGraphs( tree, defaults ) );
addIfNotNull( annotationList, getSqlResultSetMappings( tree, defaults ) );
addIfNotNull( annotationList, getExcludeDefaultListeners( tree, defaults ) );
addIfNotNull( annotationList, getExcludeSuperclassListeners( tree, defaults ) );
@ -1743,6 +1757,142 @@ public class JPAOverriddenAnnotationReader implements AnnotationReader {
}
}
public static List<NamedEntityGraph> buildNamedEntityGraph(Element element, XMLContext.Default defaults) {
if ( element == null ) {
return new ArrayList<NamedEntityGraph>();
}
List<NamedEntityGraph> namedEntityGraphList = new ArrayList<NamedEntityGraph>();
List<Element> namedEntityGraphElements = element.elements( "named-entity-graph" );
for ( Element subElement : namedEntityGraphElements ) {
AnnotationDescriptor ann = new AnnotationDescriptor( NamedEntityGraph.class );
copyStringAttribute( ann, subElement, "name", false );
copyBooleanAttribute( ann, subElement, "include-all-attributes" );
bindNamedAttributeNodes( subElement, ann );
List<Element> subgraphNodes = subElement.elements( "subgraph" );
bindNamedSubgraph( defaults, ann, subgraphNodes );
List<Element> subclassSubgraphNodes = subElement.elements( "subclass-subgraph" );
bindNamedSubgraph( defaults, ann, subclassSubgraphNodes );
namedEntityGraphList.add( (NamedEntityGraph) AnnotationFactory.create( ann ) );
}
//TODO
return namedEntityGraphList;
}
private static void bindNamedSubgraph(XMLContext.Default defaults, AnnotationDescriptor ann, List<Element> subgraphNodes) {
List<NamedSubgraph> annSubgraphNodes = new ArrayList<NamedSubgraph>( );
for(Element subgraphNode : subgraphNodes){
AnnotationDescriptor annSubgraphNode = new AnnotationDescriptor( NamedSubgraph.class );
copyStringAttribute( annSubgraphNode, subgraphNode, "name", true );
String clazzName = subgraphNode.attributeValue( "class" );
Class clazz;
try {
clazz = ReflectHelper.classForName(
XMLContext.buildSafeClassName( clazzName, defaults ),
JPAOverriddenAnnotationReader.class
);
}
catch ( ClassNotFoundException e ) {
throw new AnnotationException( "Unable to find entity-class: " + clazzName, e );
}
annSubgraphNode.setValue( "type", clazz );
bindNamedAttributeNodes(subgraphNode, annSubgraphNode);
annSubgraphNodes.add( (NamedSubgraph) AnnotationFactory.create( annSubgraphNode ) );
}
ann.setValue( "subgraphs", annSubgraphNodes.toArray( new NamedSubgraph[annSubgraphNodes.size()] ) );
}
private static void bindNamedAttributeNodes(Element subElement, AnnotationDescriptor ann) {
List<Element> namedAttributeNodes = subElement.elements("named-attribute-node");
List<NamedAttributeNode> annNamedAttributeNodes = new ArrayList<NamedAttributeNode>( );
for(Element namedAttributeNode : namedAttributeNodes){
AnnotationDescriptor annNamedAttributeNode = new AnnotationDescriptor( NamedAttributeNode.class );
copyStringAttribute( annNamedAttributeNode, namedAttributeNode, "value", true );
copyStringAttribute( annNamedAttributeNode, namedAttributeNode, "subgraph", false );
copyStringAttribute( annNamedAttributeNode, namedAttributeNode, "key-subgraph", false );
annNamedAttributeNodes.add( (NamedAttributeNode) AnnotationFactory.create( annNamedAttributeNode ) );
}
ann.setValue( "attributeNodes", annNamedAttributeNodes.toArray( new NamedAttributeNode[annNamedAttributeNodes.size()] ) );
}
public static List<NamedStoredProcedureQuery> buildNamedStoreProcedureQueries(Element element, XMLContext.Default defaults) {
if ( element == null ) {
return new ArrayList<NamedStoredProcedureQuery>();
}
List namedStoredProcedureElements = element.elements( "named-stored-procedure-query" );
List<NamedStoredProcedureQuery> namedStoredProcedureQueries = new ArrayList<NamedStoredProcedureQuery>();
for ( Object obj : namedStoredProcedureElements ) {
Element subElement = (Element) obj;
AnnotationDescriptor ann = new AnnotationDescriptor( NamedStoredProcedureQuery.class );
copyStringAttribute( ann, subElement, "name", true );
copyStringAttribute( ann, subElement, "procedure-name", true );
List<Element> elements = subElement.elements( "parameter" );
List<StoredProcedureParameter> storedProcedureParameters = new ArrayList<StoredProcedureParameter>();
for ( Element parameterElement : elements ) {
AnnotationDescriptor parameterDescriptor = new AnnotationDescriptor( StoredProcedureParameter.class );
copyStringAttribute( parameterDescriptor, parameterElement, "name", false );
String modeValue = parameterElement.attributeValue( "mode" );
if ( modeValue == null ) {
parameterDescriptor.setValue( "mode", ParameterMode.IN );
}
else {
parameterDescriptor.setValue( "mode", ParameterMode.valueOf( modeValue.toUpperCase() ) );
}
String clazzName = parameterElement.attributeValue( "class" );
Class clazz;
try {
clazz = ReflectHelper.classForName(
XMLContext.buildSafeClassName( clazzName, defaults ),
JPAOverriddenAnnotationReader.class
);
}
catch ( ClassNotFoundException e ) {
throw new AnnotationException( "Unable to find entity-class: " + clazzName, e );
}
parameterDescriptor.setValue( "type", clazz );
storedProcedureParameters.add( (StoredProcedureParameter) AnnotationFactory.create( parameterDescriptor ) );
}
ann.setValue(
"parameters",
storedProcedureParameters.toArray( new StoredProcedureParameter[storedProcedureParameters.size()] )
);
elements = subElement.elements( "result-class" );
List<Class> returnClasses = new ArrayList<Class>();
for ( Element classElement : elements ) {
String clazzName = classElement.getTextTrim();
Class clazz;
try {
clazz = ReflectHelper.classForName(
XMLContext.buildSafeClassName( clazzName, defaults ),
JPAOverriddenAnnotationReader.class
);
}
catch ( ClassNotFoundException e ) {
throw new AnnotationException( "Unable to find entity-class: " + clazzName, e );
}
returnClasses.add( clazz );
}
ann.setValue( "resultClasses", returnClasses.toArray( new Class[returnClasses.size()] ) );
elements = subElement.elements( "result-set-mapping" );
List<String> resultSetMappings = new ArrayList<String>();
for ( Element resultSetMappingElement : elements ) {
resultSetMappings.add( resultSetMappingElement.getTextTrim() );
}
ann.setValue( "resultSetMappings", resultSetMappings.toArray( new String[resultSetMappings.size()] ) );
elements = subElement.elements( "hint" );
buildQueryHints( elements, ann );
namedStoredProcedureQueries.add( (NamedStoredProcedureQuery) AnnotationFactory.create( ann ) );
}
return namedStoredProcedureQueries;
}
public static List<SqlResultSetMapping> buildSqlResultsetMappings(Element element, XMLContext.Default defaults) {
if ( element == null ) {
return new ArrayList<SqlResultSetMapping>();
@ -1872,6 +2022,84 @@ public class JPAOverriddenAnnotationReader implements AnnotationReader {
}
}
private NamedEntityGraphs getNamedEntityGraphs(Element tree, XMLContext.Default defaults) {
List<NamedEntityGraph> queries = buildNamedEntityGraph( tree, defaults );
if ( defaults.canUseJavaAnnotations() ) {
NamedEntityGraph annotation = getJavaAnnotation( NamedEntityGraph.class );
addNamedEntityGraphIfNeeded( annotation, queries );
NamedEntityGraphs annotations = getJavaAnnotation( NamedEntityGraphs.class );
if ( annotations != null ) {
for ( NamedEntityGraph current : annotations.value() ) {
addNamedEntityGraphIfNeeded( current, queries );
}
}
}
if ( queries.size() > 0 ) {
AnnotationDescriptor ad = new AnnotationDescriptor( NamedEntityGraphs.class );
ad.setValue( "value", queries.toArray( new NamedEntityGraph[queries.size()] ) );
return AnnotationFactory.create( ad );
}
else {
return null;
}
}
private void addNamedEntityGraphIfNeeded(NamedEntityGraph annotation, List<NamedEntityGraph> queries) {
if ( annotation != null ) {
String queryName = annotation.name();
boolean present = false;
for ( NamedEntityGraph current : queries ) {
if ( current.name().equals( queryName ) ) {
present = true;
break;
}
}
if ( !present ) {
queries.add( annotation );
}
}
}
private NamedStoredProcedureQueries getNamedStoredProcedureQueries(Element tree, XMLContext.Default defaults) {
List<NamedStoredProcedureQuery> queries = buildNamedStoreProcedureQueries( tree, defaults );
if ( defaults.canUseJavaAnnotations() ) {
NamedStoredProcedureQuery annotation = getJavaAnnotation( NamedStoredProcedureQuery.class );
addNamedStoredProcedureQueryIfNeeded( annotation, queries );
NamedStoredProcedureQueries annotations = getJavaAnnotation( NamedStoredProcedureQueries.class );
if ( annotations != null ) {
for ( NamedStoredProcedureQuery current : annotations.value() ) {
addNamedStoredProcedureQueryIfNeeded( current, queries );
}
}
}
if ( queries.size() > 0 ) {
AnnotationDescriptor ad = new AnnotationDescriptor( NamedStoredProcedureQueries.class );
ad.setValue( "value", queries.toArray( new NamedStoredProcedureQuery[queries.size()] ) );
return AnnotationFactory.create( ad );
}
else {
return null;
}
}
private void addNamedStoredProcedureQueryIfNeeded(NamedStoredProcedureQuery annotation, List<NamedStoredProcedureQuery> queries) {
if ( annotation != null ) {
String queryName = annotation.name();
boolean present = false;
for ( NamedStoredProcedureQuery current : queries ) {
if ( current.name().equals( queryName ) ) {
present = true;
break;
}
}
if ( !present ) {
queries.add( annotation );
}
}
}
private NamedNativeQueries getNamedNativeQueries(Element tree, XMLContext.Default defaults) {
List<NamedNativeQuery> queries = (List<NamedNativeQuery>) buildNamedQueries( tree, true, defaults );
if ( defaults.canUseJavaAnnotations() ) {
@ -1910,6 +2138,25 @@ public class JPAOverriddenAnnotationReader implements AnnotationReader {
}
}
private static void buildQueryHints(List<Element> elements, AnnotationDescriptor ann){
List<QueryHint> queryHints = new ArrayList<QueryHint>( elements.size() );
for ( Element hint : elements ) {
AnnotationDescriptor hintDescriptor = new AnnotationDescriptor( QueryHint.class );
String value = hint.attributeValue( "name" );
if ( value == null ) {
throw new AnnotationException( "<hint> without name. " + SCHEMA_VALIDATION );
}
hintDescriptor.setValue( "name", value );
value = hint.attributeValue( "value" );
if ( value == null ) {
throw new AnnotationException( "<hint> without value. " + SCHEMA_VALIDATION );
}
hintDescriptor.setValue( "value", value );
queryHints.add( (QueryHint) AnnotationFactory.create( hintDescriptor ) );
}
ann.setValue( "hints", queryHints.toArray( new QueryHint[queryHints.size()] ) );
}
public static List buildNamedQueries(Element element, boolean isNative, XMLContext.Default defaults) {
if ( element == null ) {
return new ArrayList();
@ -1931,22 +2178,7 @@ public class JPAOverriddenAnnotationReader implements AnnotationReader {
}
copyStringElement( queryElt, ann, "query" );
List<Element> elements = subelement.elements( "hint" );
List<QueryHint> queryHints = new ArrayList<QueryHint>( elements.size() );
for ( Element hint : elements ) {
AnnotationDescriptor hintDescriptor = new AnnotationDescriptor( QueryHint.class );
String value = hint.attributeValue( "name" );
if ( value == null ) {
throw new AnnotationException( "<hint> without name. " + SCHEMA_VALIDATION );
}
hintDescriptor.setValue( "name", value );
value = hint.attributeValue( "value" );
if ( value == null ) {
throw new AnnotationException( "<hint> without value. " + SCHEMA_VALIDATION );
}
hintDescriptor.setValue( "value", value );
queryHints.add( (QueryHint) AnnotationFactory.create( hintDescriptor ) );
}
ann.setValue( "hints", queryHints.toArray( new QueryHint[queryHints.size()] ) );
buildQueryHints( elements, ann );
String clazzName = subelement.attributeValue( "result-class" );
if ( StringHelper.isNotEmpty( clazzName ) ) {
Class clazz;

View File

@ -178,7 +178,7 @@ abstract class AbstractTransactSQLDialect extends Dialect {
}
@Override
public String applyLocksToSql(String sql, LockOptions aliasedLockOptions, Map keyColumnNames) {
public String applyLocksToSql(String sql, LockOptions aliasedLockOptions, Map<String, String[]> keyColumnNames) {
// TODO: merge additional lockoptions support in Dialect.applyLocksToSql
final Iterator itr = aliasedLockOptions.getAliasLockIterator();
final StringBuilder buffer = new StringBuilder( sql );

View File

@ -1468,7 +1468,7 @@ public abstract class Dialect implements ConversionContext {
* @param keyColumnNames a map of key columns indexed by aliased table names.
* @return the modified SQL string.
*/
public String applyLocksToSql(String sql, LockOptions aliasedLockOptions, Map keyColumnNames) {
public String applyLocksToSql(String sql, LockOptions aliasedLockOptions, Map<String, String[]> keyColumnNames) {
return sql + new ForUpdateFragment( this, aliasedLockOptions, keyColumnNames ).toFragmentString();
}

View File

@ -96,7 +96,7 @@ public class SybaseASE157Dialect extends SybaseASE15Dialect {
}
@Override
public String applyLocksToSql(String sql, LockOptions aliasedLockOptions, Map keyColumnNames) {
public String applyLocksToSql(String sql, LockOptions aliasedLockOptions, Map<String, String[]> keyColumnNames) {
return sql + new ForUpdateFragment( this, aliasedLockOptions, keyColumnNames ).toFragmentString();
}

View File

@ -186,8 +186,10 @@ public class SQLServer2005LimitHandler extends AbstractLimitHandler {
// Inserting alias. It is unlikely that we would have to add alias, but just in case.
alias = StringHelper.generateAlias( "page", unique );
sb.insert( nextComa, " as " + alias );
int aliasExprLength = ( " as " + alias ).length();
++unique;
nextComa += ( " as " + alias ).length();
nextComa += aliasExprLength;
endPos += aliasExprLength;
}
aliases.add( alias );
}

View File

@ -36,7 +36,7 @@ import java.util.concurrent.ConcurrentHashMap;
public class ColumnNameCache {
private static final float LOAD_FACTOR = .75f;
private final Map<String, Integer> columnNameToIndexCache;
private final ConcurrentHashMap<String, Integer> columnNameToIndexCache;
/**
* Constructs a ColumnNameCache

View File

@ -45,6 +45,7 @@ import org.hibernate.engine.spi.CollectionKey;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.engine.spi.Status;
import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.pretty.MessageHelper;
@ -60,12 +61,11 @@ import org.hibernate.pretty.MessageHelper;
* @author Steve Ebersole
*/
public class CollectionLoadContext {
private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, CollectionLoadContext.class.getName());
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( CollectionLoadContext.class );
private final LoadContexts loadContexts;
private final ResultSet resultSet;
private Set localLoadingCollectionKeys = new HashSet();
private Set<CollectionKey> localLoadingCollectionKeys = new HashSet<CollectionKey>();
/**
* Creates a collection load context for the given result set.
@ -122,12 +122,13 @@ public class CollectionLoadContext {
if ( collection != null ) {
if ( collection.wasInitialized() ) {
LOG.trace( "Collection already initialized; ignoring" );
return null; // ignore this row of results! Note the early exit
// ignore this row of results! Note the early exit
return null;
}
LOG.trace( "Collection not yet initialized; initializing" );
}
else {
Object owner = loadContexts.getPersistenceContext().getCollectionOwner( key, persister );
final Object owner = loadContexts.getPersistenceContext().getCollectionOwner( key, persister );
final boolean newlySavedEntity = owner != null
&& loadContexts.getPersistenceContext().getEntry( owner ).getStatus() != Status.LOADING;
if ( newlySavedEntity ) {
@ -165,7 +166,7 @@ public class CollectionLoadContext {
* @param persister The persister for which to complete loading.
*/
public void endLoadingCollections(CollectionPersister persister) {
SessionImplementor session = getLoadContext().getPersistenceContext().getSession();
final SessionImplementor session = getLoadContext().getPersistenceContext().getSession();
if ( !loadContexts.hasLoadingCollectionEntries()
&& localLoadingCollectionKeys.isEmpty() ) {
return;
@ -177,17 +178,17 @@ public class CollectionLoadContext {
// internal loadingCollections map for matches and store those matches
// in a temp collection. the temp collection is then used to "drive"
// the #endRead processing.
List matches = null;
Iterator iter = localLoadingCollectionKeys.iterator();
while ( iter.hasNext() ) {
final CollectionKey collectionKey = (CollectionKey) iter.next();
List<LoadingCollectionEntry> matches = null;
final Iterator itr = localLoadingCollectionKeys.iterator();
while ( itr.hasNext() ) {
final CollectionKey collectionKey = (CollectionKey) itr.next();
final LoadingCollectionEntry lce = loadContexts.locateLoadingCollectionEntry( collectionKey );
if ( lce == null ) {
LOG.loadingCollectionKeyNotFound( collectionKey );
}
else if ( lce.getResultSet() == resultSet && lce.getPersister() == persister ) {
if ( matches == null ) {
matches = new ArrayList();
matches = new ArrayList<LoadingCollectionEntry>();
}
matches.add( lce );
if ( lce.getCollection().getOwner() == null ) {
@ -204,7 +205,7 @@ public class CollectionLoadContext {
// todo : i'd much rather have this done from #endLoadingCollection(CollectionPersister,LoadingCollectionEntry)...
loadContexts.unregisterLoadingCollectionXRef( collectionKey );
iter.remove();
itr.remove();
}
}
@ -220,29 +221,35 @@ public class CollectionLoadContext {
}
}
private void endLoadingCollections(CollectionPersister persister, List matchedCollectionEntries) {
private void endLoadingCollections(CollectionPersister persister, List<LoadingCollectionEntry> matchedCollectionEntries) {
final boolean debugEnabled = LOG.isDebugEnabled();
if ( matchedCollectionEntries == null ) {
if ( debugEnabled ) LOG.debugf( "No collections were found in result set for role: %s", persister.getRole() );
if ( debugEnabled ) {
LOG.debugf( "No collections were found in result set for role: %s", persister.getRole() );
}
return;
}
final int count = matchedCollectionEntries.size();
if ( debugEnabled ) LOG.debugf("%s collections were found in result set for role: %s", count, persister.getRole());
for ( int i = 0; i < count; i++ ) {
LoadingCollectionEntry lce = ( LoadingCollectionEntry ) matchedCollectionEntries.get( i );
endLoadingCollection( lce, persister );
if ( debugEnabled ) {
LOG.debugf( "%s collections were found in result set for role: %s", count, persister.getRole() );
}
if ( debugEnabled ) LOG.debugf( "%s collections initialized for role: %s", count, persister.getRole() );
for ( LoadingCollectionEntry matchedCollectionEntry : matchedCollectionEntries ) {
endLoadingCollection( matchedCollectionEntry, persister );
}
if ( debugEnabled ) {
LOG.debugf( "%s collections initialized for role: %s", count, persister.getRole() );
}
}
private void endLoadingCollection(LoadingCollectionEntry lce, CollectionPersister persister) {
LOG.tracev( "Ending loading collection [{0}]", lce );
final SessionImplementor session = getLoadContext().getPersistenceContext().getSession();
boolean hasNoQueuedAdds = lce.getCollection().endRead(); // warning: can cause a recursive calls! (proxy initialization)
// warning: can cause a recursive calls! (proxy initialization)
final boolean hasNoQueuedAdds = lce.getCollection().endRead();
if ( persister.getCollectionType().hasHolder() ) {
getLoadContext().getPersistenceContext().addCollectionHolder( lce.getCollection() );
@ -260,11 +267,14 @@ public class CollectionLoadContext {
}
boolean addToCache = hasNoQueuedAdds && // there were no queued additions
persister.hasCache() && // and the role has a cache
session.getCacheMode().isPutEnabled() &&
!ce.isDoremove(); // and this is not a forced initialization during flush
// add to cache if:
boolean addToCache =
// there were no queued additions
hasNoQueuedAdds
// and the role has a cache
&& persister.hasCache()
// and this is not a forced initialization during flush
&& session.getCacheMode().isPutEnabled() && !ce.isDoremove();
if ( addToCache ) {
addCollectionToCache( lce, persister );
}
@ -272,11 +282,11 @@ public class CollectionLoadContext {
if ( LOG.isDebugEnabled() ) {
LOG.debugf(
"Collection fully initialized: %s",
MessageHelper.collectionInfoString(persister, lce.getCollection(), lce.getKey(), session)
MessageHelper.collectionInfoString( persister, lce.getCollection(), lce.getKey(), session )
);
}
if ( session.getFactory().getStatistics().isStatisticsEnabled() ) {
session.getFactory().getStatisticsImplementor().loadCollection(persister.getRole());
session.getFactory().getStatisticsImplementor().loadCollection( persister.getRole() );
}
}
@ -305,7 +315,8 @@ public class CollectionLoadContext {
// currently this works in conjuction with the check on
// DefaultInitializeCollectionEventHandler.initializeCollectionFromCache() (which makes sure to not read from
// cache with enabled filters).
return; // EARLY EXIT!!!!!
// EARLY EXIT!!!!!
return;
}
final Object version;
@ -318,7 +329,7 @@ public class CollectionLoadContext {
// about its owner, that owner should be the same instance as associated with the PC, but we do the
// resolution against the PC anyway just to be safe since the lookup should not be costly.
if ( lce.getCollection() != null ) {
Object linkedOwner = lce.getCollection().getOwner();
final Object linkedOwner = lce.getCollection().getOwner();
if ( linkedOwner != null ) {
final Serializable ownerKey = persister.getOwnerEntityPersister().getIdentifier( linkedOwner, session );
collectionOwner = getLoadContext().getPersistenceContext().getCollectionOwner( ownerKey, persister );
@ -338,11 +349,11 @@ public class CollectionLoadContext {
version = null;
}
CollectionCacheEntry entry = new CollectionCacheEntry( lce.getCollection(), persister );
CacheKey cacheKey = session.generateCacheKey( lce.getKey(), persister.getKeyType(), persister.getRole() );
boolean put = persister.getCacheAccessStrategy().putFromLoad(
final CollectionCacheEntry entry = new CollectionCacheEntry( lce.getCollection(), persister );
final CacheKey cacheKey = session.generateCacheKey( lce.getKey(), persister.getKeyType(), persister.getRole() );
final boolean put = persister.getCacheAccessStrategy().putFromLoad(
cacheKey,
persister.getCacheEntryStructure().structure(entry),
persister.getCacheEntryStructure().structure( entry ),
session.getTimestamp(),
version,
factory.getServiceRegistry().getService( RegionFactory.class ).isMinimalPutsEnabled() && session.getCacheMode()!= CacheMode.REFRESH
@ -363,7 +374,7 @@ public class CollectionLoadContext {
@Override
public String toString() {
public String toString() {
return super.toString() + "<rs=" + resultSet + ">";
}
}

View File

@ -41,7 +41,8 @@ public class EntityLoadContext {
private final LoadContexts loadContexts;
private final ResultSet resultSet;
private final List hydratingEntities = new ArrayList( 20 ); // todo : need map? the prob is a proper key, right?
// todo : need map? the prob is a proper key, right?
private final List hydratingEntities = new ArrayList( 20 );
public EntityLoadContext(LoadContexts loadContexts, ResultSet resultSet) {
this.loadContexts = loadContexts;

View File

@ -30,24 +30,18 @@ import java.util.IdentityHashMap;
import java.util.Map;
import java.util.Set;
import org.jboss.logging.Logger;
import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.engine.spi.CollectionKey;
import org.hibernate.engine.spi.PersistenceContext;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.collections.IdentityMap;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.pretty.MessageHelper;
/**
* Maps {@link ResultSet result-sets} to specific contextual data related to processing that result set
* <p/>
* Implementation note: internally an {@link IdentityMap} is used to maintain the mappings mainly because I'd
* rather not be dependent upon potentially bad {@link Object#equals} and {@link Object#hashCode} implementations on
* the JDBC result sets
* <p/>
* Considering the JDBC-redesign work, would further like this contextual info not mapped separately, but available
* based on the result set being processed. This would also allow maintaining a single mapping as we could reliably
* get notification of the result-set closing...
@ -55,8 +49,7 @@ import org.hibernate.pretty.MessageHelper;
* @author Steve Ebersole
*/
public class LoadContexts {
private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, LoadContexts.class.getName());
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( LoadContexts.class );
private final PersistenceContext persistenceContext;
private Map<ResultSet,CollectionLoadContext> collectionLoadContexts;
@ -101,11 +94,11 @@ public class LoadContexts {
*/
public void cleanup(ResultSet resultSet) {
if ( collectionLoadContexts != null ) {
CollectionLoadContext collectionLoadContext = collectionLoadContexts.remove( resultSet );
final CollectionLoadContext collectionLoadContext = collectionLoadContexts.remove( resultSet );
collectionLoadContext.cleanup();
}
if ( entityLoadContexts != null ) {
EntityLoadContext entityLoadContext = entityLoadContexts.remove( resultSet );
final EntityLoadContext entityLoadContext = entityLoadContexts.remove( resultSet );
entityLoadContext.cleanup();
}
}
@ -191,7 +184,7 @@ public class LoadContexts {
* @return The loading collection, or null if not found.
*/
public PersistentCollection locateLoadingCollection(CollectionPersister persister, Serializable ownerKey) {
LoadingCollectionEntry lce = locateLoadingCollectionEntry( new CollectionKey( persister, ownerKey ) );
final LoadingCollectionEntry lce = locateLoadingCollectionEntry( new CollectionKey( persister, ownerKey ) );
if ( lce != null ) {
if ( LOG.isTraceEnabled() ) {
LOG.tracef(
@ -246,13 +239,13 @@ public class LoadContexts {
if ( !hasRegisteredLoadingCollectionEntries() ) {
return;
}
xrefLoadingCollectionEntries.remove(key);
}
xrefLoadingCollectionEntries.remove( key );
}
@SuppressWarnings( {"UnusedDeclaration"})
Map getLoadingCollectionXRefs() {
return xrefLoadingCollectionEntries;
}
return xrefLoadingCollectionEntries;
}
/**
@ -271,7 +264,7 @@ public class LoadContexts {
return null;
}
LOG.tracev( "Attempting to locate loading collection entry [{0}] in any result-set context", key );
LoadingCollectionEntry rtn = xrefLoadingCollectionEntries.get( key );
final LoadingCollectionEntry rtn = xrefLoadingCollectionEntries.get( key );
if ( rtn == null ) {
LOG.tracev( "Collection [{0}] not located in load context", key );
}
@ -291,6 +284,13 @@ public class LoadContexts {
// Entity load contexts ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// * currently, not yet used...
/**
* Currently unused
*
* @param resultSet The result set
*
* @return The entity load context
*/
@SuppressWarnings( {"UnusedDeclaration"})
public EntityLoadContext getEntityLoadContext(ResultSet resultSet) {
EntityLoadContext context = null;

View File

@ -41,7 +41,7 @@ public class LoadingCollectionEntry {
private final Serializable key;
private final PersistentCollection collection;
public LoadingCollectionEntry(
LoadingCollectionEntry(
ResultSet resultSet,
CollectionPersister persister,
Serializable key,
@ -68,6 +68,7 @@ public class LoadingCollectionEntry {
return collection;
}
@Override
public String toString() {
return getClass().getName() + "<rs=" + resultSet + ", coll=" + MessageHelper.collectionInfoString( persister.getRole(), key ) + ">@" + Integer.toHexString( hashCode() );
}

View File

@ -21,11 +21,8 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.persister.walking.spi;
/**
* @author Gail Badner
* Internal classes used to track loading of data, potentially across multiple ResultSets
*/
public interface CompositionElementDefinition extends CompositionDefinition{
public CollectionDefinition getCollectionDefinition();
}
package org.hibernate.engine.loading.internal;

View File

@ -34,6 +34,12 @@ public class Association {
private final String associationPath;
private final String role;
/**
* Constructs a association defining what is to be fetched.
*
* @param owner The entity owning the association
* @param associationPath The path of the association, from the entity
*/
public Association(EntityPersister owner, String associationPath) {
this.owner = owner;
this.associationPath = associationPath;

View File

@ -23,7 +23,6 @@
*/
package org.hibernate.engine.profile;
/**
* Models an individual fetch within a profile.
*
@ -33,6 +32,12 @@ public class Fetch {
private final Association association;
private final Style style;
/**
* Constructs a Fetch
*
* @param association The association to be fetched
* @param style How to fetch it
*/
public Fetch(Association association, Style style) {
this.association = association;
this.style = style;
@ -54,7 +59,13 @@ public class Fetch {
* needed for other things as well anyway).
*/
public enum Style {
/**
* Fetch via a join
*/
JOIN( "join" ),
/**
* Fetch via a subsequent select
*/
SELECT( "select" );
private final String name;
@ -63,10 +74,18 @@ public class Fetch {
this.name = name;
}
@Override
public String toString() {
return name;
}
/**
* Parses a style given an externalized string representation
*
* @param name The externalized representation
*
* @return The style; {@link #JOIN} is returned if not recognized
*/
public static Style parse(String name) {
if ( SELECT.name.equals( name ) ) {
return SELECT;
@ -78,6 +97,7 @@ public class Fetch {
}
}
@Override
public String toString() {
return "Fetch[" + style + "{" + association.getRole() + "}]";
}

View File

@ -22,12 +22,11 @@
* Boston, MA 02110-1301 USA
*/
package org.hibernate.engine.profile;
import java.util.HashMap;
import java.util.Map;
import org.jboss.logging.Logger;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.type.BagType;
import org.hibernate.type.Type;
@ -41,21 +40,17 @@ import org.hibernate.type.Type;
* @author Steve Ebersole
*/
public class FetchProfile {
private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, FetchProfile.class.getName());
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( FetchProfile.class );
private final String name;
private Map<String,Fetch> fetches = new HashMap<String,Fetch>();
private boolean containsJoinFetchedCollection = false;
private boolean containsJoinFetchedBag = false;
private boolean containsJoinFetchedCollection;
private boolean containsJoinFetchedBag;
private Fetch bagJoinFetch;
/**
* A 'fetch profile' is uniquely named within a
* {@link SessionFactoryImplementor SessionFactory}, thus it is also
* uniquely and easily identifiable within that
* {@link SessionFactoryImplementor SessionFactory}.
* Constructs a FetchProfile, supplying its unique name (unique within the SessionFactory).
*
* @param name The name under which we are bound in the sessionFactory
*/
@ -91,7 +86,7 @@ public class FetchProfile {
*/
public void addFetch(final Fetch fetch) {
final String fetchAssociactionRole = fetch.getAssociation().getRole();
Type associationType = fetch.getAssociation().getOwner().getPropertyType( fetch.getAssociation().getAssociationPath() );
final Type associationType = fetch.getAssociation().getOwner().getPropertyType( fetch.getAssociation().getAssociationPath() );
if ( associationType.isCollectionType() ) {
LOG.tracev( "Handling request to add collection fetch [{0}]", fetchAssociactionRole );
@ -103,7 +98,8 @@ public class FetchProfile {
if ( BagType.class.isInstance( associationType ) ) {
if ( containsJoinFetchedCollection ) {
LOG.containsJoinFetchedCollection( fetchAssociactionRole );
return; // EARLY EXIT!!!
// EARLY EXIT!!!
return;
}
}
@ -144,6 +140,13 @@ public class FetchProfile {
return fetches;
}
/**
* Obtain the fetch associated with the given role.
*
* @param role The role identifying the fetch
*
* @return The fetch, or {@code null} if a matching one was not found
*/
public Fetch getFetchByRole(String role) {
return fetches.get( role );
}

View File

@ -0,0 +1,4 @@
/**
* Models the fetch profiles defined by the application
*/
package org.hibernate.engine.profile;

View File

@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
* Copyright (c) 2008, 2013, 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 Middleware LLC.
* 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
@ -20,9 +20,9 @@
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*
*/
package org.hibernate.engine.query.spi;
import java.io.Serializable;
import java.util.Map;
@ -38,12 +38,21 @@ public class FilterQueryPlan extends HQLQueryPlan implements Serializable {
private final String collectionRole;
/**
* Constructs a query plan for an HQL filter
*
* @param hql The HQL fragment
* @param collectionRole The collection role being filtered
* @param shallow Is the query shallow?
* @param enabledFilters All enabled filters from the Session
* @param factory The factory
*/
public FilterQueryPlan(
String hql,
String collectionRole,
boolean shallow,
Map enabledFilters,
SessionFactoryImplementor factory) {
String collectionRole,
boolean shallow,
Map enabledFilters,
SessionFactoryImplementor factory) {
super( hql, collectionRole, shallow, enabledFilters, factory );
this.collectionRole = collectionRole;
}

View File

@ -32,8 +32,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import org.jboss.logging.Logger;
import org.hibernate.Filter;
import org.hibernate.HibernateException;
import org.hibernate.QueryException;
import org.hibernate.ScrollableResults;
@ -47,6 +46,7 @@ import org.hibernate.hql.spi.FilterTranslator;
import org.hibernate.hql.spi.ParameterTranslations;
import org.hibernate.hql.spi.QueryTranslator;
import org.hibernate.hql.spi.QueryTranslatorFactory;
import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.collections.ArrayHelper;
import org.hibernate.internal.util.collections.EmptyIterator;
@ -60,11 +60,10 @@ import org.hibernate.type.Type;
* @author Steve Ebersole
*/
public class HQLQueryPlan implements Serializable {
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( HQLQueryPlan.class );
// TODO : keep separate notions of QT[] here for shallow/non-shallow queries...
private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, HQLQueryPlan.class.getName());
private final String sourceQuery;
private final QueryTranslator[] translators;
private final String[] sqlStrings;
@ -73,17 +72,32 @@ public class HQLQueryPlan implements Serializable {
private final ReturnMetadata returnMetadata;
private final Set querySpaces;
private final Set enabledFilterNames;
private final Set<String> enabledFilterNames;
private final boolean shallow;
public HQLQueryPlan(String hql, boolean shallow, Map enabledFilters, SessionFactoryImplementor factory) {
/**
* Constructs a HQLQueryPlan
*
* @param hql The HQL query
* @param shallow Whether the execution is to be shallow or not
* @param enabledFilters The enabled filters (we only keep the names)
* @param factory The factory
*/
public HQLQueryPlan(String hql, boolean shallow, Map<String,Filter> enabledFilters, SessionFactoryImplementor factory) {
this( hql, null, shallow, enabledFilters, factory );
}
protected HQLQueryPlan(String hql, String collectionRole, boolean shallow, Map enabledFilters, SessionFactoryImplementor factory){
@SuppressWarnings("unchecked")
protected HQLQueryPlan(
String hql,
String collectionRole,
boolean shallow,
Map<String,Filter> enabledFilters,
SessionFactoryImplementor factory) {
this.sourceQuery = hql;
this.shallow = shallow;
Set copy = new HashSet();
final Set<String> copy = new HashSet<String>();
copy.addAll( enabledFilters.keySet() );
this.enabledFilterNames = java.util.Collections.unmodifiableSet( copy );
@ -91,8 +105,8 @@ public class HQLQueryPlan implements Serializable {
final int length = concreteQueryStrings.length;
this.translators = new QueryTranslator[length];
List<String> sqlStringList = new ArrayList<String>();
Set combinedQuerySpaces = new HashSet();
final List<String> sqlStringList = new ArrayList<String>();
final Set combinedQuerySpaces = new HashSet();
final boolean hasCollectionRole = (collectionRole == null);
final Map querySubstitutions = factory.getSettings().getQuerySubstitutions();
@ -107,7 +121,7 @@ public class HQLQueryPlan implements Serializable {
else {
translators[i] = queryTranslatorFactory
.createFilterTranslator( hql, concreteQueryStrings[i], enabledFilters, factory );
( ( FilterTranslator ) translators[i] ).compile( collectionRole, querySubstitutions, shallow );
( (FilterTranslator) translators[i] ).compile( collectionRole, querySubstitutions, shallow );
}
combinedQuerySpaces.addAll( translators[i].getQuerySpaces() );
sqlStringList.addAll( translators[i].collectSqlStrings() );
@ -165,20 +179,33 @@ public class HQLQueryPlan implements Serializable {
return shallow;
}
/**
* Coordinates the efforts to perform a list across all the included query translators.
*
* @param queryParameters The query parameters
* @param session The session
*
* @return The query result list
*
* @throws HibernateException Indicates a problem performing the query
*/
@SuppressWarnings("unchecked")
public List performList(
QueryParameters queryParameters,
SessionImplementor session) throws HibernateException {
SessionImplementor session) throws HibernateException {
if ( LOG.isTraceEnabled() ) {
LOG.tracev( "Find: {0}", getSourceQuery() );
queryParameters.traceParameters( session.getFactory() );
}
boolean hasLimit = queryParameters.getRowSelection() != null &&
queryParameters.getRowSelection().definesLimits();
boolean needsLimit = hasLimit && translators.length > 1;
QueryParameters queryParametersToUse;
final boolean hasLimit = queryParameters.getRowSelection() != null
&& queryParameters.getRowSelection().definesLimits();
final boolean needsLimit = hasLimit && translators.length > 1;
final QueryParameters queryParametersToUse;
if ( needsLimit ) {
LOG.needsLimit();
RowSelection selection = new RowSelection();
final RowSelection selection = new RowSelection();
selection.setFetchSize( queryParameters.getRowSelection().getFetchSize() );
selection.setTimeout( queryParameters.getRowSelection().getTimeout() );
queryParametersToUse = queryParameters.createCopyUsing( selection );
@ -187,12 +214,12 @@ public class HQLQueryPlan implements Serializable {
queryParametersToUse = queryParameters;
}
List combinedResults = new ArrayList();
IdentitySet distinction = new IdentitySet();
final List combinedResults = new ArrayList();
final IdentitySet distinction = new IdentitySet();
int includedCount = -1;
translator_loop:
for ( QueryTranslator translator : translators ) {
List tmp = translator.list( session, queryParametersToUse );
final List tmp = translator.list( session, queryParametersToUse );
if ( needsLimit ) {
// NOTE : firstRow is zero-based
final int first = queryParameters.getRowSelection().getFirstRow() == null
@ -223,9 +250,20 @@ public class HQLQueryPlan implements Serializable {
return combinedResults;
}
/**
* Coordinates the efforts to perform an iterate across all the included query translators.
*
* @param queryParameters The query parameters
* @param session The session
*
* @return The query result iterator
*
* @throws HibernateException Indicates a problem performing the query
*/
@SuppressWarnings("unchecked")
public Iterator performIterate(
QueryParameters queryParameters,
EventSource session) throws HibernateException {
EventSource session) throws HibernateException {
if ( LOG.isTraceEnabled() ) {
LOG.tracev( "Iterate: {0}", getSourceQuery() );
queryParameters.traceParameters( session.getFactory() );
@ -234,8 +272,8 @@ public class HQLQueryPlan implements Serializable {
return EmptyIterator.INSTANCE;
}
final boolean many = translators.length > 1;
Iterator[] results = null;
boolean many = translators.length > 1;
if ( many ) {
results = new Iterator[translators.length];
}
@ -248,12 +286,22 @@ public class HQLQueryPlan implements Serializable {
}
}
return many ? new JoinedIterator(results) : result;
return many ? new JoinedIterator( results ) : result;
}
/**
* Coordinates the efforts to perform a scroll across all the included query translators.
*
* @param queryParameters The query parameters
* @param session The session
*
* @return The query result iterator
*
* @throws HibernateException Indicates a problem performing the query
*/
public ScrollableResults performScroll(
QueryParameters queryParameters,
SessionImplementor session) throws HibernateException {
SessionImplementor session) throws HibernateException {
if ( LOG.isTraceEnabled() ) {
LOG.tracev( "Iterate: {0}", getSourceQuery() );
queryParameters.traceParameters( session.getFactory() );
@ -268,6 +316,16 @@ public class HQLQueryPlan implements Serializable {
return translators[0].scroll( queryParameters, session );
}
/**
* Coordinates the efforts to perform an execution across all the included query translators.
*
* @param queryParameters The query parameters
* @param session The session
*
* @return The aggregated "affected row" count
*
* @throws HibernateException Indicates a problem performing the execution
*/
public int performExecuteUpdate(QueryParameters queryParameters, SessionImplementor session)
throws HibernateException {
if ( LOG.isTraceEnabled() ) {
@ -285,32 +343,34 @@ public class HQLQueryPlan implements Serializable {
}
private ParameterMetadata buildParameterMetadata(ParameterTranslations parameterTranslations, String hql) {
long start = System.currentTimeMillis();
ParamLocationRecognizer recognizer = ParamLocationRecognizer.parseLocations( hql );
long end = System.currentTimeMillis();
final long start = System.currentTimeMillis();
final ParamLocationRecognizer recognizer = ParamLocationRecognizer.parseLocations( hql );
final long end = System.currentTimeMillis();
if ( LOG.isTraceEnabled() ) {
LOG.tracev( "HQL param location recognition took {0} mills ({1})", ( end - start ), hql );
}
int ordinalParamCount = parameterTranslations.getOrdinalParameterCount();
int[] locations = ArrayHelper.toIntArray( recognizer.getOrdinalParameterLocationList() );
final int[] locations = ArrayHelper.toIntArray( recognizer.getOrdinalParameterLocationList() );
if ( parameterTranslations.supportsOrdinalParameterMetadata() && locations.length != ordinalParamCount ) {
throw new HibernateException( "ordinal parameter mismatch" );
}
ordinalParamCount = locations.length;
OrdinalParameterDescriptor[] ordinalParamDescriptors = new OrdinalParameterDescriptor[ordinalParamCount];
final OrdinalParameterDescriptor[] ordinalParamDescriptors = new OrdinalParameterDescriptor[ordinalParamCount];
for ( int i = 1; i <= ordinalParamCount; i++ ) {
ordinalParamDescriptors[ i - 1 ] = new OrdinalParameterDescriptor(
i,
parameterTranslations.supportsOrdinalParameterMetadata()
? parameterTranslations.getOrdinalParameterExpectedType( i )
: null,
locations[ i - 1 ]
parameterTranslations.supportsOrdinalParameterMetadata()
? parameterTranslations.getOrdinalParameterExpectedType( i )
: null,
locations[ i - 1 ]
);
}
Map<String, NamedParameterDescriptor> namedParamDescriptorMap = new HashMap<String, NamedParameterDescriptor>();
Map<String, ParamLocationRecognizer.NamedParameterDescription> map = recognizer.getNamedParameterDescriptionMap();
final Map<String, NamedParameterDescriptor> namedParamDescriptorMap = new HashMap<String, NamedParameterDescriptor>();
final Map<String, ParamLocationRecognizer.NamedParameterDescription> map = recognizer.getNamedParameterDescriptionMap();
for ( final String name : map.keySet() ) {
final ParamLocationRecognizer.NamedParameterDescription description = map.get( name );
namedParamDescriptorMap.put(
@ -325,9 +385,15 @@ public class HQLQueryPlan implements Serializable {
}
return new ParameterMetadata( ordinalParamDescriptors, namedParamDescriptorMap );
}
/**
* Access to the underlying translators associated with this query
*
* @return The translators
*/
public QueryTranslator[] getTranslators() {
QueryTranslator[] copy = new QueryTranslator[translators.length];
System.arraycopy(translators, 0, copy, 0, copy.length);
final QueryTranslator[] copy = new QueryTranslator[translators.length];
System.arraycopy( translators, 0, copy, 0, copy.length );
return copy;
}

View File

@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
* Copyright (c) 2008, 2013, 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 Middleware LLC.
* 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
@ -20,9 +20,9 @@
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*
*/
package org.hibernate.engine.query.spi;
import java.io.Serializable;
import org.hibernate.type.Type;
@ -38,6 +38,14 @@ public class NamedParameterDescriptor implements Serializable {
private final int[] sourceLocations;
private final boolean jpaStyle;
/**
* Constructs a NamedParameterDescriptor
*
* @param name The name of the parameter
* @param expectedType The expected type of the parameter, according to the translator
* @param sourceLocations The locations of the named parameters (aye aye aye)
* @param jpaStyle Was the parameter a JPA style "named parameter"?
*/
public NamedParameterDescriptor(String name, Type expectedType, int[] sourceLocations, boolean jpaStyle) {
this.name = name;
this.expectedType = expectedType;
@ -61,6 +69,11 @@ public class NamedParameterDescriptor implements Serializable {
return jpaStyle;
}
/**
* Set the parameters expected type
*
* @param type The new expected type
*/
public void resetExpectedType(Type type) {
this.expectedType = type;
}

View File

@ -30,8 +30,6 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.jboss.logging.Logger;
import org.hibernate.HibernateException;
import org.hibernate.QueryException;
import org.hibernate.action.internal.BulkOperationCleanupAction;
@ -41,6 +39,7 @@ import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.engine.spi.TypedValue;
import org.hibernate.event.spi.EventSource;
import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.collections.ArrayHelper;
import org.hibernate.loader.custom.sql.SQLCustomQuery;
@ -52,10 +51,7 @@ import org.hibernate.type.Type;
* @author Steve Ebersole
*/
public class NativeSQLQueryPlan implements Serializable {
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
CoreMessageLogger.class,
NativeSQLQueryPlan.class.getName()
);
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( NativeSQLQueryPlan.class );
private final String sourceQuery;
private final SQLCustomQuery customQuery;
@ -87,7 +83,7 @@ public class NativeSQLQueryPlan implements Serializable {
}
private int[] getNamedParameterLocs(String name) throws QueryException {
Object loc = customQuery.getNamedParameterBindPoints().get( name );
final Object loc = customQuery.getNamedParameterBindPoints().get( name );
if ( loc == null ) {
throw new QueryException(
"Named parameter does not appear in Query: " + name,
@ -154,60 +150,73 @@ public class NativeSQLQueryPlan implements Serializable {
final SessionImplementor session) throws SQLException {
if ( namedParams != null ) {
// assumes that types are all of span 1
Iterator iter = namedParams.entrySet().iterator();
final Iterator iter = namedParams.entrySet().iterator();
int result = 0;
while ( iter.hasNext() ) {
Map.Entry e = (Map.Entry) iter.next();
String name = (String) e.getKey();
TypedValue typedval = (TypedValue) e.getValue();
int[] locs = getNamedParameterLocs( name );
for (int i = 0; i < locs.length; i++) {
LOG.debugf("bindNamedParameters() %s -> %s [%s]", typedval.getValue(), name, locs[i] + start);
typedval.getType().nullSafeSet( ps, typedval.getValue(),
locs[i] + start, session );
final Map.Entry e = (Map.Entry) iter.next();
final String name = (String) e.getKey();
final TypedValue typedval = (TypedValue) e.getValue();
final int[] locs = getNamedParameterLocs( name );
for ( int loc : locs ) {
LOG.debugf( "bindNamedParameters() %s -> %s [%s]", typedval.getValue(), name, loc + start );
typedval.getType().nullSafeSet(
ps,
typedval.getValue(),
loc + start,
session
);
}
result += locs.length;
}
return result;
}
return 0;
return 0;
}
protected void coordinateSharedCacheCleanup(SessionImplementor session) {
BulkOperationCleanupAction action = new BulkOperationCleanupAction( session, getCustomQuery().getQuerySpaces() );
final BulkOperationCleanupAction action = new BulkOperationCleanupAction( session, getCustomQuery().getQuerySpaces() );
if ( session.isEventSource() ) {
( ( EventSource ) session ).getActionQueue().addAction( action );
( (EventSource) session ).getActionQueue().addAction( action );
}
else {
action.getAfterTransactionCompletionProcess().doAfterTransactionCompletion( true, session );
}
}
public int performExecuteUpdate(QueryParameters queryParameters,
/**
* Performs the execute query
*
* @param queryParameters The query parameters
* @param session The session
*
* @return The number of affected rows as returned by the JDBC driver
*
* @throws HibernateException Indicates a problem performing the query execution
*/
public int performExecuteUpdate(
QueryParameters queryParameters,
SessionImplementor session) throws HibernateException {
coordinateSharedCacheCleanup( session );
if(queryParameters.isCallable()) {
if ( queryParameters.isCallable() ) {
throw new IllegalArgumentException("callable not yet supported for native queries");
}
int result = 0;
PreparedStatement ps;
try {
queryParameters.processFilters( this.customQuery.getSQL(),
session );
String sql = queryParameters.getFilteredSQL();
queryParameters.processFilters( this.customQuery.getSQL(), session );
final String sql = queryParameters.getFilteredSQL();
ps = session.getTransactionCoordinator().getJdbcCoordinator().getStatementPreparer().prepareStatement( sql, false );
try {
int col = 1;
col += bindPositionalParameters( ps, queryParameters, col,
session );
col += bindNamedParameters( ps, queryParameters
.getNamedParameters(), col, session );
col += bindPositionalParameters( ps, queryParameters, col, session );
col += bindNamedParameters( ps, queryParameters.getNamedParameters(), col, session );
result = session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().executeUpdate( ps );
}
finally {
@ -218,7 +227,10 @@ public class NativeSQLQueryPlan implements Serializable {
}
catch (SQLException sqle) {
throw session.getFactory().getSQLExceptionHelper().convert(
sqle, "could not execute native bulk manipulation query", this.sourceQuery );
sqle,
"could not execute native bulk manipulation query",
this.sourceQuery
);
}
return result;

View File

@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
* Copyright (c) 2008, 2013, 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 Middleware LLC.
* 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
@ -20,14 +20,16 @@
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*
*/
package org.hibernate.engine.query.spi;
import java.io.Serializable;
import org.hibernate.type.Type;
/**
* Descriptor regarding an ordinal parameter.
*
* @author Steve Ebersole
*/
public class OrdinalParameterDescriptor implements Serializable {
@ -35,6 +37,13 @@ public class OrdinalParameterDescriptor implements Serializable {
private final Type expectedType;
private final int sourceLocation;
/**
* Constructs an ordinal parameter descriptor.
*
* @param ordinalPosition The ordinal position
* @param expectedType The expected type of the parameter
* @param sourceLocation The location of the parameter
*/
public OrdinalParameterDescriptor(int ordinalPosition, Type expectedType, int sourceLocation) {
this.ordinalPosition = ordinalPosition;
this.expectedType = expectedType;

View File

@ -38,12 +38,14 @@ import org.hibernate.internal.util.collections.ArrayHelper;
* @author Steve Ebersole
*/
public class ParamLocationRecognizer implements ParameterParser.Recognizer {
/**
* Internal representation of a recognized named parameter
*/
public static class NamedParameterDescription {
private final boolean jpaStyle;
private final List<Integer> positions = new ArrayList<Integer>();
public NamedParameterDescription(boolean jpaStyle) {
NamedParameterDescription(boolean jpaStyle) {
this.jpaStyle = jpaStyle;
}
@ -71,7 +73,7 @@ public class ParamLocationRecognizer implements ParameterParser.Recognizer {
* @return The generated recognizer, with journaled location info.
*/
public static ParamLocationRecognizer parseLocations(String query) {
ParamLocationRecognizer recognizer = new ParamLocationRecognizer();
final ParamLocationRecognizer recognizer = new ParamLocationRecognizer();
ParameterParser.parse( query, recognizer );
return recognizer;
}
@ -88,8 +90,8 @@ public class ParamLocationRecognizer implements ParameterParser.Recognizer {
/**
* Returns the list of ordinal parameter locations. The list elements
* are Integers, representing the location for that given ordinal. Thus
* {@link #getOrdinalParameterLocationList()}.elementAt(n) represents the
* are Integers, representing the location for that given ordinal. Thus calling
* {@code getOrdinalParameterLocationList().elementAt(n)} represents the
* location for the nth parameter.
*
* @return The list of ordinal parameter locations.

View File

@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
* Copyright (c) 2008, 2013, 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 Middleware LLC.
* 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
@ -20,9 +20,9 @@
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*
*/
package org.hibernate.engine.query.spi;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
@ -37,33 +37,35 @@ import org.hibernate.type.Type;
* @author Steve Ebersole
*/
public class ParameterMetadata implements Serializable {
private static final OrdinalParameterDescriptor[] EMPTY_ORDINALS = new OrdinalParameterDescriptor[0];
private final OrdinalParameterDescriptor[] ordinalDescriptors;
private final Map namedDescriptorMap;
private final Map<String,NamedParameterDescriptor> namedDescriptorMap;
/**
* Instantiates a ParameterMetadata container.
*
* @param ordinalDescriptors
* @param namedDescriptorMap
* @param ordinalDescriptors Descriptors of the ordinal parameters
* @param namedDescriptorMap Descriptors of the named parameters
*/
public ParameterMetadata(OrdinalParameterDescriptor[] ordinalDescriptors, Map namedDescriptorMap) {
public ParameterMetadata(
OrdinalParameterDescriptor[] ordinalDescriptors,
Map<String,NamedParameterDescriptor> namedDescriptorMap) {
if ( ordinalDescriptors == null ) {
this.ordinalDescriptors = EMPTY_ORDINALS;
}
else {
OrdinalParameterDescriptor[] copy = new OrdinalParameterDescriptor[ ordinalDescriptors.length ];
final OrdinalParameterDescriptor[] copy = new OrdinalParameterDescriptor[ ordinalDescriptors.length ];
System.arraycopy( ordinalDescriptors, 0, copy, 0, ordinalDescriptors.length );
this.ordinalDescriptors = copy;
}
if ( namedDescriptorMap == null ) {
this.namedDescriptorMap = java.util.Collections.EMPTY_MAP;
this.namedDescriptorMap = java.util.Collections.emptyMap();
}
else {
int size = ( int ) ( ( namedDescriptorMap.size() / .75 ) + 1 );
Map copy = new HashMap( size );
final int size = (int) ( ( namedDescriptorMap.size() / .75 ) + 1 );
final Map<String,NamedParameterDescriptor> copy = new HashMap<String,NamedParameterDescriptor>( size );
copy.putAll( namedDescriptorMap );
this.namedDescriptorMap = java.util.Collections.unmodifiableMap( copy );
}
@ -73,39 +75,107 @@ public class ParameterMetadata implements Serializable {
return ordinalDescriptors.length;
}
/**
* Get the descriptor for an ordinal parameter given its position
*
* @param position The position (1 based)
*
* @return The ordinal parameter descriptor
*
* @throws QueryParameterException If the position is out of range
*/
public OrdinalParameterDescriptor getOrdinalParameterDescriptor(int position) {
if ( position < 1 || position > ordinalDescriptors.length ) {
String error = "Position beyond number of declared ordinal parameters. " +
"Remember that ordinal parameters are 1-based! Position: " + position;
throw new QueryParameterException( error );
throw new QueryParameterException(
"Position beyond number of declared ordinal parameters. " +
"Remember that ordinal parameters are 1-based! Position: " + position
);
}
return ordinalDescriptors[position - 1];
}
/**
* Deprecated.
*
* @param position The position
*
* @return The type
*
* @deprecated Use {@link OrdinalParameterDescriptor#getExpectedType()} from the
* {@link #getOrdinalParameterDescriptor} return instead
*/
@Deprecated
public Type getOrdinalParameterExpectedType(int position) {
return getOrdinalParameterDescriptor( position ).getExpectedType();
}
/**
* Deprecated.
*
* @param position The position
*
* @return The source location
*
* @deprecated Use {@link OrdinalParameterDescriptor#getSourceLocation()} from the
* {@link #getOrdinalParameterDescriptor} return instead
*/
@Deprecated
public int getOrdinalParameterSourceLocation(int position) {
return getOrdinalParameterDescriptor( position ).getSourceLocation();
}
/**
* Access to the names of all named parameters
*
* @return The named parameter names
*/
public Set getNamedParameterNames() {
return namedDescriptorMap.keySet();
}
/**
* Get the descriptor for a named parameter given the name
*
* @param name The name of the parameter to locate
*
* @return The named parameter descriptor
*
* @throws QueryParameterException If the name could not be resolved to a named parameter
*/
public NamedParameterDescriptor getNamedParameterDescriptor(String name) {
NamedParameterDescriptor meta = ( NamedParameterDescriptor ) namedDescriptorMap.get( name );
final NamedParameterDescriptor meta = namedDescriptorMap.get( name );
if ( meta == null ) {
throw new QueryParameterException( "could not locate named parameter [" + name + "]" );
}
return meta;
}
/**
* Deprecated.
*
* @param name The name of the parameter
*
* @return The type
*
* @deprecated Use {@link NamedParameterDescriptor#getExpectedType()} from the
* {@link #getNamedParameterDescriptor} return instead
*/
@Deprecated
public Type getNamedParameterExpectedType(String name) {
return getNamedParameterDescriptor( name ).getExpectedType();
}
/**
* Deprecated.
*
* @param name The name of the parameter
*
* @return The type
*
* @deprecated Use {@link NamedParameterDescriptor#getSourceLocations()} from the
* {@link #getNamedParameterDescriptor} return instead
*/
@Deprecated
public int[] getNamedParameterSourceLocations(String name) {
return getNamedParameterDescriptor( name ).getSourceLocations();
}

View File

@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
* Copyright (c) 2008, 2013, 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 Middleware LLC.
* 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
@ -20,9 +20,9 @@
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*
*/
package org.hibernate.engine.query.spi;
import org.hibernate.QueryException;
import org.hibernate.hql.internal.classic.ParserHelper;
import org.hibernate.internal.util.StringHelper;
@ -36,12 +36,45 @@ import org.hibernate.internal.util.StringHelper;
* @author Steve Ebersole
*/
public class ParameterParser {
/**
* Maybe better named a Journaler. Essentially provides a callback contract for things that recognize parameters
*/
public static interface Recognizer {
/**
* Called when an output parameter is recognized
*
* @param position The position within the query
*/
public void outParameter(int position);
/**
* Called when an ordinal parameter is recognized
*
* @param position The position within the query
*/
public void ordinalParameter(int position);
/**
* Called when a named parameter is recognized
*
* @param name The recognized parameter name
* @param position The position within the query
*/
public void namedParameter(String name, int position);
/**
* Called when a JPA-style named parameter is recognized
*
* @param name The name of the JPA-style parameter
* @param position The position within the query
*/
public void jpaPositionalParameter(String name, int position);
/**
* Called when a character that is not a parameter (or part of a parameter dfinition) is recognized.
*
* @param character The recognized character
*/
public void other(char character);
}
@ -64,13 +97,13 @@ public class ParameterParser {
* @throws QueryException Indicates unexpected parameter conditions.
*/
public static void parse(String sqlString, Recognizer recognizer) throws QueryException {
boolean hasMainOutputParameter = startsWithEscapeCallTemplate( sqlString );
final boolean hasMainOutputParameter = startsWithEscapeCallTemplate( sqlString );
boolean foundMainOutputParam = false;
int stringLength = sqlString.length();
final int stringLength = sqlString.length();
boolean inQuote = false;
for ( int indx = 0; indx < stringLength; indx++ ) {
char c = sqlString.charAt( indx );
final char c = sqlString.charAt( indx );
if ( inQuote ) {
if ( '\'' == c ) {
inQuote = false;
@ -88,9 +121,9 @@ public class ParameterParser {
else {
if ( c == ':' ) {
// named parameter
int right = StringHelper.firstIndexOfChar( sqlString, ParserHelper.HQL_SEPARATORS_BITSET, indx + 1 );
int chopLocation = right < 0 ? sqlString.length() : right;
String param = sqlString.substring( indx + 1, chopLocation );
final int right = StringHelper.firstIndexOfChar( sqlString, ParserHelper.HQL_SEPARATORS_BITSET, indx + 1 );
final int chopLocation = right < 0 ? sqlString.length() : right;
final String param = sqlString.substring( indx + 1, chopLocation );
if ( StringHelper.isEmpty( param ) ) {
throw new QueryException(
"Space is not allowed after parameter prefix ':' [" + sqlString + "]"
@ -103,12 +136,12 @@ public class ParameterParser {
// could be either an ordinal or JPA-positional parameter
if ( indx < stringLength - 1 && Character.isDigit( sqlString.charAt( indx + 1 ) ) ) {
// a peek ahead showed this as an JPA-positional parameter
int right = StringHelper.firstIndexOfChar( sqlString, ParserHelper.HQL_SEPARATORS, indx + 1 );
int chopLocation = right < 0 ? sqlString.length() : right;
String param = sqlString.substring( indx + 1, chopLocation );
final int right = StringHelper.firstIndexOfChar( sqlString, ParserHelper.HQL_SEPARATORS, indx + 1 );
final int chopLocation = right < 0 ? sqlString.length() : right;
final String param = sqlString.substring( indx + 1, chopLocation );
// make sure this "name" is an integral
try {
Integer.valueOf( param );
Integer.valueOf( param );
}
catch( NumberFormatException e ) {
throw new QueryException( "JPA-style positional param was not an integral ordinal" );
@ -133,12 +166,19 @@ public class ParameterParser {
}
}
/**
* Exposed as public solely for use from tests
*
* @param sqlString The SQL string to check
*
* @return true/false
*/
public static boolean startsWithEscapeCallTemplate(String sqlString) {
if ( ! ( sqlString.startsWith( "{" ) && sqlString.endsWith( "}" ) ) ) {
return false;
}
int chopLocation = sqlString.indexOf( "call" );
final int chopLocation = sqlString.indexOf( "call" );
if ( chopLocation <= 0 ) {
return false;
}
@ -147,7 +187,8 @@ public class ParameterParser {
final String fixture = "?=call";
int fixturePosition = 0;
boolean matches = true;
for ( int i = 0, max = checkString.length(); i < max; i++ ) {
final int max = checkString.length();
for ( int i = 0; i < max; i++ ) {
final char c = Character.toLowerCase( checkString.charAt( i ) );
if ( Character.isWhitespace( c ) ) {
continue;

View File

@ -1,95 +0,0 @@
/*
* 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.engine.query.spi;
import java.io.Serializable;
import java.util.Set;
import org.hibernate.type.Type;
/**
* Defines metadata regarding a translated HQL or native-SQL query.
*
* @author Steve Ebersole
*/
public class QueryMetadata implements Serializable {
private final String sourceQuery;
private final ParameterMetadata parameterMetadata;
private final String[] returnAliases;
private final Type[] returnTypes;
private final Set querySpaces;
public QueryMetadata(
String sourceQuery,
ParameterMetadata parameterMetadata,
String[] returnAliases,
Type[] returnTypes,
Set querySpaces) {
this.sourceQuery = sourceQuery;
this.parameterMetadata = parameterMetadata;
this.returnAliases = returnAliases;
this.returnTypes = returnTypes;
this.querySpaces = querySpaces;
}
/**
* Get the source HQL or native-SQL query.
*
* @return The source query.
*/
public String getSourceQuery() {
return sourceQuery;
}
public ParameterMetadata getParameterMetadata() {
return parameterMetadata;
}
/**
* Return source query select clause aliases (if any)
*
* @return an array of aliases as strings.
*/
public String[] getReturnAliases() {
return returnAliases;
}
/**
* An array of types describing the returns of the source query.
*
* @return The return type array.
*/
public Type[] getReturnTypes() {
return returnTypes;
}
/**
* The set of query spaces affected by this source query.
*
* @return The set of query spaces.
*/
public Set getQuerySpaces() {
return querySpaces;
}
}

View File

@ -28,18 +28,17 @@ import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import org.jboss.logging.Logger;
import org.hibernate.Filter;
import org.hibernate.MappingException;
import org.hibernate.QueryException;
import org.hibernate.cfg.Environment;
import org.hibernate.engine.query.spi.sql.NativeSQLQuerySpecification;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.FilterImpl;
import org.hibernate.internal.util.collections.BoundedConcurrentHashMap;
@ -55,8 +54,7 @@ import org.hibernate.internal.util.config.ConfigurationHelper;
* @author Steve Ebersole
*/
public class QueryPlanCache implements Serializable {
private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, QueryPlanCache.class.getName());
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( QueryPlanCache.class );
/**
* The default strong reference count.
@ -66,11 +64,14 @@ public class QueryPlanCache implements Serializable {
* The default soft reference count.
*/
public static final int DEFAULT_QUERY_PLAN_MAX_COUNT = 2048;
private final SessionFactoryImplementor factory;
/**
* the cache of the actual plans...
*/
private final BoundedConcurrentHashMap queryPlanCache;
/**
* simple cache of param metadata based on query string. Ideally, the original "user-supplied query"
* string should be used to obtain this metadata (i.e., not the para-list-expanded query string) to avoid
@ -81,6 +82,12 @@ public class QueryPlanCache implements Serializable {
*/
private final BoundedConcurrentHashMap<String,ParameterMetadata> parameterMetadataCache;
/**
* Constructs the QueryPlanCache to be used by the given SessionFactory
*
* @param factory The SessionFactory
*/
@SuppressWarnings("deprecation")
public QueryPlanCache(final SessionFactoryImplementor factory) {
this.factory = factory;
@ -136,15 +143,17 @@ public class QueryPlanCache implements Serializable {
}
private ParameterMetadata buildParameterMetadata(String query){
ParamLocationRecognizer recognizer = ParamLocationRecognizer.parseLocations( query );
final ParamLocationRecognizer recognizer = ParamLocationRecognizer.parseLocations( query );
final int size = recognizer.getOrdinalParameterLocationList().size();
OrdinalParameterDescriptor[] ordinalDescriptors = new OrdinalParameterDescriptor[ size ];
final OrdinalParameterDescriptor[] ordinalDescriptors = new OrdinalParameterDescriptor[ size ];
for ( int i = 0; i < size; i++ ) {
final Integer position = recognizer.getOrdinalParameterLocationList().get( i );
ordinalDescriptors[i] = new OrdinalParameterDescriptor( i, null, position );
}
Map<String, NamedParameterDescriptor> namedParamDescriptorMap = new HashMap<String, NamedParameterDescriptor>();
Map<String, ParamLocationRecognizer.NamedParameterDescription> map = recognizer.getNamedParameterDescriptionMap();
final Map<String, NamedParameterDescriptor> namedParamDescriptorMap = new HashMap<String, NamedParameterDescriptor>();
final Map<String, ParamLocationRecognizer.NamedParameterDescription> map = recognizer.getNamedParameterDescriptionMap();
for ( final String name : map.keySet() ) {
final ParamLocationRecognizer.NamedParameterDescription description = map.get( name );
namedParamDescriptorMap.put(
@ -160,9 +169,22 @@ public class QueryPlanCache implements Serializable {
return new ParameterMetadata( ordinalDescriptors, namedParamDescriptorMap );
}
public HQLQueryPlan getHQLQueryPlan( String queryString, boolean shallow, Map<String, Filter> enabledFilters)
/**
* Get the query plan for the given HQL query, creating it and caching it if not already cached
*
* @param queryString The HQL query string
* @param shallow Whether the execution will be shallow
* @param enabledFilters The filters enabled on the Session
*
* @return The query plan
*
* @throws QueryException Indicates a problem translating the query
* @throws MappingException Indicates a problem translating the query
*/
@SuppressWarnings("unchecked")
public HQLQueryPlan getHQLQueryPlan(String queryString, boolean shallow, Map<String,Filter> enabledFilters)
throws QueryException, MappingException {
HQLQueryPlanKey key = new HQLQueryPlanKey( queryString, shallow, enabledFilters );
final HQLQueryPlanKey key = new HQLQueryPlanKey( queryString, shallow, enabledFilters );
HQLQueryPlan value = (HQLQueryPlan) queryPlanCache.get( key );
if ( value == null ) {
LOG.tracev( "Unable to locate HQL query plan in cache; generating ({0})", queryString );
@ -174,37 +196,69 @@ public class QueryPlanCache implements Serializable {
return value;
}
public FilterQueryPlan getFilterQueryPlan(String filterString, String collectionRole, boolean shallow, Map enabledFilters)
throws QueryException, MappingException {
FilterQueryPlanKey key = new FilterQueryPlanKey( filterString, collectionRole, shallow, enabledFilters );
/**
* Get the query plan for the given collection HQL filter fragment, creating it and caching it if not already cached
*
* @param filterString The HQL filter fragment
* @param collectionRole The collection being filtered
* @param shallow Whether the execution will be shallow
* @param enabledFilters The filters enabled on the Session
*
* @return The query plan
*
* @throws QueryException Indicates a problem translating the query
* @throws MappingException Indicates a problem translating the query
*/
@SuppressWarnings("unchecked")
public FilterQueryPlan getFilterQueryPlan(
String filterString,
String collectionRole,
boolean shallow,
Map<String,Filter> enabledFilters) throws QueryException, MappingException {
final FilterQueryPlanKey key = new FilterQueryPlanKey( filterString, collectionRole, shallow, enabledFilters );
FilterQueryPlan value = (FilterQueryPlan) queryPlanCache.get( key );
if(value == null){
LOG.tracev( "Unable to locate collection-filter query plan in cache; generating ({0} : {1} )",
collectionRole, filterString );
if ( value == null ) {
LOG.tracev(
"Unable to locate collection-filter query plan in cache; generating ({0} : {1} )",
collectionRole,
filterString
);
value = new FilterQueryPlan( filterString, collectionRole, shallow, enabledFilters,factory );
queryPlanCache.putIfAbsent( key, value );
} else {
}
else {
LOG.tracev( "Located collection-filter query plan in cache ({0} : {1})", collectionRole, filterString );
}
return value;
}
/**
* Get the query plan for a native SQL query, creating it and caching it if not already cached
*
* @param spec The native SQL query specification
*
* @return The query plan
*
* @throws QueryException Indicates a problem translating the query
* @throws MappingException Indicates a problem translating the query
*/
@SuppressWarnings("unchecked")
public NativeSQLQueryPlan getNativeSQLQueryPlan(final NativeSQLQuerySpecification spec) {
NativeSQLQueryPlan value = (NativeSQLQueryPlan) queryPlanCache.get( spec );
if(value == null){
if ( value == null ) {
LOG.tracev( "Unable to locate native-sql query plan in cache; generating ({0})", spec.getQueryString() );
value = new NativeSQLQueryPlan( spec, factory);
queryPlanCache.putIfAbsent( spec, value );
} else {
}
else {
LOG.tracev( "Located native-sql query plan in cache ({0})", spec.getQueryString() );
}
return value;
}
//clean up QueryPlanCache when Sessionfactory is closed
/**
* clean up QueryPlanCache when SessionFactory is closed
*/
public void cleanup() {
LOG.trace( "Cleaning QueryPlan Cache" );
queryPlanCache.clear();
@ -224,7 +278,7 @@ public class QueryPlanCache implements Serializable {
filterKeys = Collections.emptySet();
}
else {
Set<DynamicFilterKey> tmp = new HashSet<DynamicFilterKey>(
final Set<DynamicFilterKey> tmp = new HashSet<DynamicFilterKey>(
CollectionHelper.determineProperSizing( enabledFilters ),
CollectionHelper.LOAD_FACTOR
);
@ -249,7 +303,7 @@ public class QueryPlanCache implements Serializable {
return false;
}
final HQLQueryPlanKey that = ( HQLQueryPlanKey ) o;
final HQLQueryPlanKey that = (HQLQueryPlanKey) o;
return shallow == that.shallow
&& filterKeys.equals( that.filterKeys )
@ -307,8 +361,7 @@ public class QueryPlanCache implements Serializable {
return false;
}
DynamicFilterKey that = ( DynamicFilterKey ) o;
final DynamicFilterKey that = (DynamicFilterKey) o;
return filterName.equals( that.filterName )
&& parameterMetadata.equals( that.parameterMetadata );
@ -337,7 +390,7 @@ public class QueryPlanCache implements Serializable {
this.filterNames = Collections.emptySet();
}
else {
Set<String> tmp = new HashSet<String>();
final Set<String> tmp = new HashSet<String>();
tmp.addAll( enabledFilters.keySet() );
this.filterNames = Collections.unmodifiableSet( tmp );
@ -359,8 +412,7 @@ public class QueryPlanCache implements Serializable {
return false;
}
final FilterQueryPlanKey that = ( FilterQueryPlanKey ) o;
final FilterQueryPlanKey that = (FilterQueryPlanKey) o;
return shallow == that.shallow
&& filterNames.equals( that.filterNames )
&& query.equals( that.query )

View File

@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
* Copyright (c) 2008, 2013, 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 Middleware LLC.
* 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
@ -20,21 +20,23 @@
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*
*/
package org.hibernate.engine.query.spi;
import java.io.Serializable;
import org.hibernate.type.Type;
/**
* Metadata about the query return(s).
*
* @author Steve Ebersole
*/
public class ReturnMetadata implements Serializable {
private final String[] returnAliases;
private final Type[] returnTypes;
public ReturnMetadata(String[] returnAliases, Type[] returnTypes) {
ReturnMetadata(String[] returnAliases, Type[] returnTypes) {
this.returnAliases = returnAliases;
this.returnTypes = returnTypes;
}

View File

@ -0,0 +1,4 @@
/**
* Defines support for query plans and stored metadata about queries
*/
package org.hibernate.engine.query.spi;

View File

@ -52,6 +52,7 @@ import org.hibernate.action.internal.EntityDeleteAction;
import org.hibernate.action.internal.EntityIdentityInsertAction;
import org.hibernate.action.internal.EntityInsertAction;
import org.hibernate.action.internal.EntityUpdateAction;
import org.hibernate.action.internal.QueuedOperationCollectionAction;
import org.hibernate.action.internal.UnresolvedEntityInsertActions;
import org.hibernate.action.spi.AfterTransactionCompletionProcess;
import org.hibernate.action.spi.BeforeTransactionCompletionProcess;
@ -63,7 +64,7 @@ import org.hibernate.type.Type;
/**
* Responsible for maintaining the queue of actions related to events.
* </p>
*
* The ActionQueue holds the DML operations queued as part of a session's
* transactional-write-behind semantics. DML operations are queued here
* until a flush forces them to be executed against the database.
@ -91,6 +92,7 @@ public class ActionQueue {
// just re-use the same Lists for convenience.
private ArrayList collectionCreations;
private ArrayList collectionUpdates;
private ArrayList collectionQueuedOps;
private ArrayList collectionRemovals;
private AfterTransactionCompletionProcessQueue afterTransactionProcesses;
@ -115,6 +117,7 @@ public class ActionQueue {
collectionCreations = new ArrayList( INIT_QUEUE_LIST_SIZE );
collectionRemovals = new ArrayList( INIT_QUEUE_LIST_SIZE );
collectionUpdates = new ArrayList( INIT_QUEUE_LIST_SIZE );
collectionQueuedOps = new ArrayList( INIT_QUEUE_LIST_SIZE );
afterTransactionProcesses = new AfterTransactionCompletionProcessQueue( session );
beforeTransactionProcesses = new BeforeTransactionCompletionProcessQueue( session );
@ -128,6 +131,7 @@ public class ActionQueue {
collectionCreations.clear();
collectionRemovals.clear();
collectionUpdates.clear();
collectionQueuedOps.clear();
unresolvedInsertions.clear();
}
@ -163,6 +167,11 @@ public class ActionQueue {
collectionUpdates.add( action );
}
@SuppressWarnings({ "unchecked" })
public void addAction(QueuedOperationCollectionAction action) {
collectionQueuedOps.add( action );
}
@SuppressWarnings({ "unchecked" })
public void addAction(EntityIdentityInsertAction insert) {
LOG.tracev( "Adding an EntityIdentityInsertAction for [{0}] object", insert.getEntityName() );
@ -276,6 +285,8 @@ public class ActionQueue {
}
executeActions( insertions );
executeActions( updates );
// do before actions are handled in the other collection queues
executeActions( collectionQueuedOps );
executeActions( collectionRemovals );
executeActions( collectionUpdates );
executeActions( collectionCreations );
@ -291,6 +302,7 @@ public class ActionQueue {
prepareActions( collectionRemovals );
prepareActions( collectionUpdates );
prepareActions( collectionCreations );
prepareActions( collectionQueuedOps );
}
/**
@ -325,6 +337,7 @@ public class ActionQueue {
areTablesToUpdated( deletions, tables ) ||
areTablesToUpdated( collectionUpdates, tables ) ||
areTablesToUpdated( collectionCreations, tables ) ||
areTablesToUpdated( collectionQueuedOps, tables ) ||
areTablesToUpdated( collectionRemovals, tables );
}
@ -401,6 +414,7 @@ public class ActionQueue {
.append( " collectionCreations=" ).append( collectionCreations )
.append( " collectionRemovals=" ).append( collectionRemovals )
.append( " collectionUpdates=" ).append( collectionUpdates )
.append( " collectionQueuedOps=" ).append( collectionQueuedOps )
.append( " unresolvedInsertDependencies=" ).append( unresolvedInsertions )
.append( "]" )
.toString();
@ -436,6 +450,7 @@ public class ActionQueue {
//sort the updates by fk
java.util.Collections.sort( collectionCreations );
java.util.Collections.sort( collectionUpdates );
java.util.Collections.sort( collectionQueuedOps );
java.util.Collections.sort( collectionRemovals );
}
}
@ -472,6 +487,7 @@ public class ActionQueue {
public void clearFromFlushNeededCheck(int previousCollectionRemovalSize) {
collectionCreations.clear();
collectionUpdates.clear();
collectionQueuedOps.clear();
updates.clear();
// collection deletions are a special case since update() can add
// deletions of collections not loaded by the session.
@ -495,6 +511,7 @@ public class ActionQueue {
! unresolvedInsertions.isEmpty() ||
deletions.size() > 0 ||
collectionUpdates.size() > 0 ||
collectionQueuedOps.size() > 0 ||
collectionRemovals.size() > 0 ||
collectionCreations.size() > 0;
}
@ -564,6 +581,13 @@ public class ActionQueue {
for ( int i = 0; i < queueSize; i++ ) {
oos.writeObject( collectionCreations.get( i ) );
}
queueSize = collectionQueuedOps.size();
LOG.tracev( "Starting serialization of [{0}] collectionQueuedOps entries", queueSize );
oos.writeInt( queueSize );
for ( int i = 0; i < queueSize; i++ ) {
oos.writeObject( collectionQueuedOps.get( i ) );
}
}
/**
@ -640,6 +664,15 @@ public class ActionQueue {
action.afterDeserialize( session );
rtn.collectionCreations.add( action );
}
queueSize = ois.readInt();
LOG.tracev( "Starting deserialization of [{0}] collectionQueuedOps entries", queueSize );
rtn.collectionQueuedOps = new ArrayList<Executable>( queueSize );
for ( int i = 0; i < queueSize; i++ ) {
CollectionAction action = ( CollectionAction ) ois.readObject();
action.afterDeserialize( session );
rtn.collectionQueuedOps.add( action );
}
return rtn;
}

View File

@ -32,6 +32,7 @@ import org.hibernate.HibernateException;
import org.hibernate.action.internal.CollectionRecreateAction;
import org.hibernate.action.internal.CollectionRemoveAction;
import org.hibernate.action.internal.CollectionUpdateAction;
import org.hibernate.action.internal.QueuedOperationCollectionAction;
import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.engine.internal.Cascade;
import org.hibernate.engine.internal.CascadePoint;
@ -294,6 +295,16 @@ public abstract class AbstractFlushingEventListener implements Serializable {
)
);
}
if ( !coll.wasInitialized() && coll.hasQueuedOperations() ) {
actionQueue.addAction(
new QueuedOperationCollectionAction(
coll,
ce.getLoadedPersister(),
ce.getLoadedKey(),
session
)
);
}
}

View File

@ -70,6 +70,7 @@ import org.hibernate.internal.util.ReflectHelper;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.internal.util.collections.IdentitySet;
import org.hibernate.loader.hql.QueryLoader;
import org.hibernate.param.ParameterSpecification;
import org.hibernate.persister.entity.Queryable;
import org.hibernate.type.Type;
@ -101,7 +102,7 @@ public class QueryTranslatorImpl implements FilterTranslator {
private String sql;
private ParameterTranslations paramTranslations;
private List collectedParameterSpecifications;
private List<ParameterSpecification> collectedParameterSpecifications;
/**
@ -570,12 +571,11 @@ public class QueryTranslatorImpl implements FilterTranslator {
public ParameterTranslations getParameterTranslations() {
if ( paramTranslations == null ) {
paramTranslations = new ParameterTranslationsImpl( getWalker().getParameters() );
// paramTranslations = new ParameterTranslationsImpl( collectedParameterSpecifications );
}
return paramTranslations;
}
public List getCollectedParameterSpecifications() {
public List<ParameterSpecification> getCollectedParameterSpecifications() {
return collectedParameterSpecifications;
}

View File

@ -76,7 +76,7 @@ public class SqlGenerator extends SqlGeneratorBase implements ErrorReporter {
private SessionFactoryImplementor sessionFactory;
private LinkedList<SqlWriter> outputStack = new LinkedList<SqlWriter>();
private final ASTPrinter printer = new ASTPrinter( SqlTokenTypes.class );
private List collectedParameters = new ArrayList();
private List<ParameterSpecification> collectedParameters = new ArrayList<ParameterSpecification>();
// handle trace logging ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -106,7 +106,7 @@ public class SqlGenerator extends SqlGeneratorBase implements ErrorReporter {
LOG.trace( prefix + ruleName );
}
public List getCollectedParameters() {
public List<ParameterSpecification> getCollectedParameters() {
return collectedParameters;
}

View File

@ -452,16 +452,12 @@ public class FromElement extends HqlSqlWalkerNode implements DisplayableNode, Pa
this.alias = alias;
}
/**
* {@inheritDoc}
*/
@Override
public String getSqlFragment() {
return persisterDiscriminatorMetadata.getSqlFragment( alias );
}
/**
* {@inheritDoc}
*/
@Override
public Type getResolutionType() {
return persisterDiscriminatorMetadata.getResolutionType();
}
@ -660,21 +656,24 @@ public class FromElement extends HqlSqlWalkerNode implements DisplayableNode, Pa
// ParameterContainer impl ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
private List embeddedParameters;
private List<ParameterSpecification> embeddedParameters;
@Override
public void addEmbeddedParameter(ParameterSpecification specification) {
if ( embeddedParameters == null ) {
embeddedParameters = new ArrayList();
embeddedParameters = new ArrayList<ParameterSpecification>();
}
embeddedParameters.add( specification );
}
@Override
public boolean hasEmbeddedParameters() {
return embeddedParameters != null && ! embeddedParameters.isEmpty();
}
@Override
public ParameterSpecification[] getEmbeddedParameters() {
return ( ParameterSpecification[] ) embeddedParameters.toArray( new ParameterSpecification[ embeddedParameters.size() ] );
return embeddedParameters.toArray( new ParameterSpecification[ embeddedParameters.size() ] );
}
public ParameterSpecification getIndexCollectionSelectorParamSpec() {

View File

@ -147,14 +147,14 @@ public class IndexNode extends FromReferenceNode {
}
String selectorExpression = gen.getSQL();
joinSequence.addCondition( collectionTableAlias + '.' + indexCols[0] + " = " + selectorExpression );
List paramSpecs = gen.getCollectedParameters();
List<ParameterSpecification> paramSpecs = gen.getCollectedParameters();
if ( paramSpecs != null ) {
switch ( paramSpecs.size() ) {
case 0 :
// nothing to do
break;
case 1 :
ParameterSpecification paramSpec = ( ParameterSpecification ) paramSpecs.get( 0 );
ParameterSpecification paramSpec = paramSpecs.get( 0 );
paramSpec.setExpectedType( queryableCollection.getIndexType() );
fromElement.setIndexCollectionSelectorParamSpec( paramSpec );
break;
@ -176,39 +176,40 @@ public class IndexNode extends FromReferenceNode {
* In the (rare?) case where the index selector contains multiple parameters...
*/
private static class AggregatedIndexCollectionSelectorParameterSpecifications implements ParameterSpecification {
private final List paramSpecs;
private final List<ParameterSpecification> paramSpecs;
public AggregatedIndexCollectionSelectorParameterSpecifications(List paramSpecs) {
public AggregatedIndexCollectionSelectorParameterSpecifications(List<ParameterSpecification> paramSpecs) {
this.paramSpecs = paramSpecs;
}
@Override
public int bind(PreparedStatement statement, QueryParameters qp, SessionImplementor session, int position)
throws SQLException {
int bindCount = 0;
Iterator itr = paramSpecs.iterator();
while ( itr.hasNext() ) {
final ParameterSpecification paramSpec = ( ParameterSpecification ) itr.next();
for ( ParameterSpecification paramSpec : paramSpecs ) {
bindCount += paramSpec.bind( statement, qp, session, position + bindCount );
}
return bindCount;
}
@Override
public Type getExpectedType() {
return null;
}
@Override
public void setExpectedType(Type expectedType) {
}
@Override
public String renderDisplayInfo() {
return "index-selector [" + collectDisplayInfo() + "]" ;
}
private String collectDisplayInfo() {
StringBuilder buffer = new StringBuilder();
Iterator itr = paramSpecs.iterator();
while ( itr.hasNext() ) {
buffer.append( ( ( ParameterSpecification ) itr.next() ).renderDisplayInfo() );
for ( ParameterSpecification paramSpec : paramSpecs ) {
buffer.append( ( paramSpec ).renderDisplayInfo() );
}
return buffer.toString();
}

Some files were not shown because too many files have changed in this diff Show More