Hibernate SVN: r20750 - core/trunk/documentation/manual/src/main/docbook/en-US/content.
by hibernate-commits@lists.jboss.org
Author: hardy.ferentschik
Date: 2010-09-29 08:50:23 -0400 (Wed, 29 Sep 2010)
New Revision: 20750
Modified:
core/trunk/documentation/manual/src/main/docbook/en-US/content/basic_mapping.xml
Log:
HHH-5190 added documentation
Modified: core/trunk/documentation/manual/src/main/docbook/en-US/content/basic_mapping.xml
===================================================================
--- core/trunk/documentation/manual/src/main/docbook/en-US/content/basic_mapping.xml 2010-09-29 10:45:08 UTC (rev 20749)
+++ core/trunk/documentation/manual/src/main/docbook/en-US/content/basic_mapping.xml 2010-09-29 12:50:23 UTC (rev 20750)
@@ -3385,23 +3385,53 @@
the table-per-class-hierarchy mapping strategy. It declares a
discriminator column of the table. The discriminator column contains
marker values that tell the persistence layer what subclass to
- instantiate for a particular row. A restricted set of types can be
- used: <literal>string</literal>, <literal>character</literal>,
+ instantiate for a particular row. Hibernate Core supports the
+ follwoing restricted set of types as discriminator column:
+ <literal>string</literal>, <literal>character</literal>,
<literal>integer</literal>, <literal>byte</literal>,
<literal>short</literal>, <literal>boolean</literal>,
<literal>yes_no</literal>, <literal>true_false</literal>.</para>
<para>Use the <classname>@DiscriminatorColumn</classname> to define
- the discriminator column as well as the discriminator type.
- Alternatively, you can also use
- <classname>@DiscriminatorFormula</classname> to express in SQL what
- would be in a virtual discriminator column. This is particularly
- handy when the discriminator value can be extracted from one or more
- columns of the table. Both
- <classname>@DiscriminatorColumn</classname> and
+ the discriminator column as well as the discriminator type. <note>
+ <para><classname>The enum DiscriminatorType</classname> used in
+ <classname>javax.persitence.DiscriminatorColumn</classname> only
+ contains the values <constant>STRING</constant>,
+ <constant>CHAR</constant> and <constant>INTEGER</constant> which
+ means that not all Hibernate supported types are available via
+ the <classname>@DiscriminatorColumn</classname>
+ annotation.</para>
+ </note>You can also use
+ <classname>@DiscriminatorFormula</classname> to express in SQL a
+ virtual discriminator column. This is particularly useful when the
+ discriminator value can be extracted from one or more columns of the
+ table. Both <classname>@DiscriminatorColumn</classname> and
<classname>@DiscriminatorFormula</classname> are to be set on the
root entity (once per persisted hierarchy).</para>
+ <para><classname>@org.hibernate.annotations.DiscriminatorOptions</classname>
+ allows to optionally specify Hibernate specific discriminator
+ options which are not standardized in JPA. The available options are
+ <literal>force</literal> and <literal>insert</literal>. The
+ <literal>force</literal> attribute is useful if the table contains
+ rows with "extra" discriminator values that are not mapped to a
+ persistent class. This could for example occur when working with a
+ legacy database. If <literal>force</literal> is set to
+ <constant>true</constant> Hibernate will specify the allowed
+ discriminator values in the <literal>SELECT</literal> query, even
+ when retrieving all instances of the root class. The second option -
+ <literal>insert</literal> - tells Hibernate whether or not to
+ include the discriminator column in SQL <literal>INSERTs</literal>.
+ Usually the column should be part of the <literal>INSERT</literal>
+ statement, but if your discriminator column is also part of a mapped
+ composite identifier you have to set this option to
+ <constant>false</constant>.<tip>
+ <para>There is also a
+ <classname>@org.hibernate.annotations.ForceDiscriminator</classname>
+ annotation which is deprecated since version 3.6. Use
+ <classname>@DiscriminatorOptions</classname> instead.</para>
+ </tip></para>
+
<para>Finally, use <classname>@DiscriminatorValue</classname> on
each class of the hierarchy to specify the value stored in the
discriminator column for a given entity. If you do not set
@@ -3487,11 +3517,6 @@
<literal><class></literal> and
<literal><subclass></literal> elements.</para>
- <para>The <literal>force</literal> attribute is only useful if the
- table contains rows with "extra" discriminator values that are not
- mapped to a persistent class. This will not usually be the
- case.</para>
-
<para>The <literal>formula</literal> attribute allows you to declare
an arbitrary SQL expression that will be used to evaluate the type
of a row. For example:</para>
13 years, 7 months
Hibernate SVN: r20749 - in core/trunk: core/src/main/java/org/hibernate/cfg and 3 other directories.
by hibernate-commits@lists.jboss.org
Author: hardy.ferentschik
Date: 2010-09-29 06:45:08 -0400 (Wed, 29 Sep 2010)
New Revision: 20749
Added:
core/trunk/core/src/main/java/org/hibernate/annotations/DiscriminatorOptions.java
core/trunk/testsuite/src/test/java/org/hibernate/test/annotations/inheritance/discriminatoroptions/
core/trunk/testsuite/src/test/java/org/hibernate/test/annotations/inheritance/discriminatoroptions/BaseClass.java
core/trunk/testsuite/src/test/java/org/hibernate/test/annotations/inheritance/discriminatoroptions/DiscriminatorOptionsTest.java
core/trunk/testsuite/src/test/java/org/hibernate/test/annotations/inheritance/discriminatoroptions/SubClass.java
Modified:
core/trunk/core/src/main/java/org/hibernate/annotations/ForceDiscriminator.java
core/trunk/core/src/main/java/org/hibernate/cfg/AnnotationBinder.java
core/trunk/core/src/main/java/org/hibernate/cfg/annotations/EntityBinder.java
Log:
HHH-5190 - Introduced new annotation @DiscriminatorOptions and deprecated @ForceDiscriminator
Copied: core/trunk/core/src/main/java/org/hibernate/annotations/DiscriminatorOptions.java (from rev 20741, core/trunk/core/src/main/java/org/hibernate/annotations/DiscriminatorFormula.java)
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/annotations/DiscriminatorOptions.java (rev 0)
+++ core/trunk/core/src/main/java/org/hibernate/annotations/DiscriminatorOptions.java 2010-09-29 10:45:08 UTC (rev 20749)
@@ -0,0 +1,56 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+// $Id:$
+package org.hibernate.annotations;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+/**
+ * Optional annotation to express Hibernate specific discrimintor properties.
+ *
+ * @author Hardy Ferentschik
+ */
+@Target({ TYPE })
+@Retention(RUNTIME)
+public @interface DiscriminatorOptions {
+ /**
+ * "Forces" Hibernate to specify the allowed discriminator values, even when retrieving all instances of the root class.
+ *
+ * @return {@code true} in case the discriminator value should be forces, {@code false} otherwise. Default is {@code false}.
+ */
+ boolean force() default false;
+
+ /**
+ * Set this to {@code false}, if your discriminator column is also part of a mapped composite identifier.
+ * It tells Hibernate not to include the column in SQL INSERTs.
+ *
+ * @return {@code true} in case the discriminator value should be included in inserts, {@code false} otherwise.
+ * Default is {@code true}.
+ */
+ boolean insert() default true;
+}
Property changes on: core/trunk/core/src/main/java/org/hibernate/annotations/DiscriminatorOptions.java
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Modified: core/trunk/core/src/main/java/org/hibernate/annotations/ForceDiscriminator.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/annotations/ForceDiscriminator.java 2010-09-29 09:44:15 UTC (rev 20748)
+++ core/trunk/core/src/main/java/org/hibernate/annotations/ForceDiscriminator.java 2010-09-29 10:45:08 UTC (rev 20749)
@@ -23,16 +23,19 @@
*/
package org.hibernate.annotations;
-import java.lang.annotation.Target;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
/**
* ForceDiscriminator flag
* To be placed at the root entity near @DiscriminatorColumn or @DiscriminatorFormula
*
* @author Serg Prasolov
+ * @deprecated use {@link org.hibernate.annotations.DiscriminatorOptions} instead
*/
-(a)Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME)
-public @interface ForceDiscriminator {}
+@Target({ ElementType.TYPE })
+(a)Retention(RetentionPolicy.RUNTIME)
+public @interface ForceDiscriminator {
+}
Modified: core/trunk/core/src/main/java/org/hibernate/cfg/AnnotationBinder.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/cfg/AnnotationBinder.java 2010-09-29 09:44:15 UTC (rev 20748)
+++ core/trunk/core/src/main/java/org/hibernate/cfg/AnnotationBinder.java 2010-09-29 10:45:08 UTC (rev 20749)
@@ -97,6 +97,7 @@
import org.hibernate.annotations.CollectionId;
import org.hibernate.annotations.CollectionOfElements;
import org.hibernate.annotations.Columns;
+import org.hibernate.annotations.DiscriminatorOptions;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchProfile;
import org.hibernate.annotations.FetchProfiles;
@@ -104,6 +105,7 @@
import org.hibernate.annotations.FilterDef;
import org.hibernate.annotations.FilterDefs;
import org.hibernate.annotations.Filters;
+import org.hibernate.annotations.ForceDiscriminator;
import org.hibernate.annotations.ForeignKey;
import org.hibernate.annotations.Formula;
import org.hibernate.annotations.GenericGenerator;
@@ -533,6 +535,16 @@
clazzToProcess, inheritanceStatePerClass, mappings, inheritanceState
);
+ PersistentClass persistentClass = makePersistentClass( inheritanceState, superEntity );
+ Entity entityAnn = clazzToProcess.getAnnotation( Entity.class );
+ org.hibernate.annotations.Entity hibEntityAnn = clazzToProcess.getAnnotation(
+ org.hibernate.annotations.Entity.class
+ );
+ EntityBinder entityBinder = new EntityBinder(
+ entityAnn, hibEntityAnn, clazzToProcess, persistentClass, mappings
+ );
+ entityBinder.setInheritanceState( inheritanceState );
+
bindQueries( clazzToProcess, mappings );
bindFilterDefs( clazzToProcess, mappings );
bindTypeDefs( clazzToProcess, mappings );
@@ -555,57 +567,17 @@
clazzToProcess, mappings, inheritanceState, superEntity
);
Ejb3DiscriminatorColumn discriminatorColumn = null;
- String discrimValue = null;
if ( InheritanceType.SINGLE_TABLE.equals( inheritanceState.getType() ) ) {
- javax.persistence.DiscriminatorColumn discAnn = clazzToProcess.getAnnotation(
- javax.persistence.DiscriminatorColumn.class
+ discriminatorColumn = processDiscriminatorProperties(
+ clazzToProcess, mappings, inheritanceState, entityBinder
);
- DiscriminatorType discriminatorType = discAnn != null ?
- discAnn.discriminatorType() :
- DiscriminatorType.STRING;
-
- org.hibernate.annotations.DiscriminatorFormula discFormulaAnn = clazzToProcess.getAnnotation(
- org.hibernate.annotations.DiscriminatorFormula.class
- );
- if ( !inheritanceState.hasParents() ) {
- discriminatorColumn = Ejb3DiscriminatorColumn.buildDiscriminatorColumn(
- discriminatorType, discAnn, discFormulaAnn, mappings
- );
- }
- if ( discAnn != null && inheritanceState.hasParents() ) {
- log.warn(
- "Discriminator column has to be defined in the root entity, it will be ignored in subclass: {}",
- clazzToProcess.getName()
- );
- }
-
- discrimValue = clazzToProcess.isAnnotationPresent( DiscriminatorValue.class ) ?
- clazzToProcess.getAnnotation( DiscriminatorValue.class ).value() :
- null;
}
- PersistentClass persistentClass = makePersistentClass( inheritanceState, superEntity );
+ entityBinder.setProxy( clazzToProcess.getAnnotation( Proxy.class ) );
+ entityBinder.setBatchSize( clazzToProcess.getAnnotation( BatchSize.class ) );
+ entityBinder.setWhere( clazzToProcess.getAnnotation( Where.class ) );
+ entityBinder.setCache( determineCacheSettings( clazzToProcess, mappings ) );
- Proxy proxyAnn = clazzToProcess.getAnnotation( Proxy.class );
- BatchSize sizeAnn = clazzToProcess.getAnnotation( BatchSize.class );
- Where whereAnn = clazzToProcess.getAnnotation( Where.class );
- Entity entityAnn = clazzToProcess.getAnnotation( Entity.class );
- org.hibernate.annotations.Entity hibEntityAnn = clazzToProcess.getAnnotation(
- org.hibernate.annotations.Entity.class
- );
-
- Cache cacheAnn = determineCacheSettings( clazzToProcess, mappings );
-
- EntityBinder entityBinder = new EntityBinder(
- entityAnn, hibEntityAnn, clazzToProcess, persistentClass, mappings
- );
- entityBinder.setDiscriminatorValue( discrimValue );
- entityBinder.setBatchSize( sizeAnn );
- entityBinder.setProxy( proxyAnn );
- entityBinder.setWhere( whereAnn );
- entityBinder.setCache( cacheAnn );
- entityBinder.setInheritanceState( inheritanceState );
-
//Filters are not allowed on subclasses
if ( !inheritanceState.hasParents() ) {
bindFilters( clazzToProcess, entityBinder, mappings );
@@ -763,6 +735,50 @@
}
+ // parse everything discriminator column relevant in case of single table inheritance
+ private static Ejb3DiscriminatorColumn processDiscriminatorProperties(XClass clazzToProcess, Mappings mappings, InheritanceState inheritanceState, EntityBinder entityBinder) {
+ Ejb3DiscriminatorColumn discriminatorColumn = null;
+ javax.persistence.DiscriminatorColumn discAnn = clazzToProcess.getAnnotation(
+ javax.persistence.DiscriminatorColumn.class
+ );
+ DiscriminatorType discriminatorType = discAnn != null ?
+ discAnn.discriminatorType() :
+ DiscriminatorType.STRING;
+
+ org.hibernate.annotations.DiscriminatorFormula discFormulaAnn = clazzToProcess.getAnnotation(
+ org.hibernate.annotations.DiscriminatorFormula.class
+ );
+ if ( !inheritanceState.hasParents() ) {
+ discriminatorColumn = Ejb3DiscriminatorColumn.buildDiscriminatorColumn(
+ discriminatorType, discAnn, discFormulaAnn, mappings
+ );
+ }
+ if ( discAnn != null && inheritanceState.hasParents() ) {
+ log.warn(
+ "Discriminator column has to be defined in the root entity, it will be ignored in subclass: {}",
+ clazzToProcess.getName()
+ );
+ }
+
+ String discrimValue = clazzToProcess.isAnnotationPresent( DiscriminatorValue.class ) ?
+ clazzToProcess.getAnnotation( DiscriminatorValue.class ).value() :
+ null;
+ entityBinder.setDiscriminatorValue( discrimValue );
+
+ if ( clazzToProcess.isAnnotationPresent( ForceDiscriminator.class ) ) {
+ log.warn( "@ForceDiscriminator is deprecated use @DiscriminatorOptions instead." );
+ entityBinder.setForceDiscriminator( true );
+ }
+
+ DiscriminatorOptions discriminatorOptions = clazzToProcess.getAnnotation( DiscriminatorOptions.class );
+ if ( discriminatorOptions != null) {
+ entityBinder.setForceDiscriminator( discriminatorOptions.force() );
+ entityBinder.setInsertableDiscriminator( discriminatorOptions.insert() );
+ }
+
+ return discriminatorColumn;
+ }
+
private static void processIdPropertiesIfNotAlready(
Map<XClass, InheritanceState> inheritanceStatePerClass,
Mappings mappings,
Modified: core/trunk/core/src/main/java/org/hibernate/cfg/annotations/EntityBinder.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/cfg/annotations/EntityBinder.java 2010-09-29 09:44:15 UTC (rev 20748)
+++ core/trunk/core/src/main/java/org/hibernate/cfg/annotations/EntityBinder.java 2010-09-29 10:45:08 UTC (rev 20749)
@@ -43,7 +43,6 @@
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.annotations.FetchMode;
-import org.hibernate.annotations.ForceDiscriminator;
import org.hibernate.annotations.Immutable;
import org.hibernate.annotations.Loader;
import org.hibernate.annotations.OptimisticLockType;
@@ -102,6 +101,8 @@
private Mappings mappings;
private Logger log = LoggerFactory.getLogger( EntityBinder.class );
private String discriminatorValue = "";
+ private Boolean forceDiscriminator;
+ private Boolean insertableDiscriminator;
private boolean dynamicInsert;
private boolean dynamicUpdate;
private boolean explicitHibernateEntityAnnotation;
@@ -182,6 +183,14 @@
this.discriminatorValue = discriminatorValue;
}
+ public void setForceDiscriminator(boolean forceDiscriminator) {
+ this.forceDiscriminator = forceDiscriminator;
+ }
+
+ public void setInsertableDiscriminator(boolean insertableDiscriminator) {
+ this.insertableDiscriminator = insertableDiscriminator;
+ }
+
public void bindEntity() {
persistentClass.setAbstract( annotatedClass.isAbstract() );
persistentClass.setClassName( annotatedClass.getName() );
@@ -219,7 +228,12 @@
rootClass.setCacheRegionName( cacheRegion );
rootClass.setLazyPropertiesCacheable( cacheLazyProperty );
}
- rootClass.setForceDiscriminator( annotatedClass.isAnnotationPresent( ForceDiscriminator.class ) );
+ if(forceDiscriminator != null) {
+ rootClass.setForceDiscriminator( forceDiscriminator );
+ }
+ if( insertableDiscriminator != null) {
+ rootClass.setDiscriminatorInsertable( insertableDiscriminator );
+ }
}
else {
if ( explicitHibernateEntityAnnotation ) {
Added: core/trunk/testsuite/src/test/java/org/hibernate/test/annotations/inheritance/discriminatoroptions/BaseClass.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/annotations/inheritance/discriminatoroptions/BaseClass.java (rev 0)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/annotations/inheritance/discriminatoroptions/BaseClass.java 2010-09-29 10:45:08 UTC (rev 20749)
@@ -0,0 +1,47 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+
+// $Id:$
+package org.hibernate.test.annotations.inheritance.discriminatoroptions;
+
+import javax.persistence.DiscriminatorValue;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+
+import org.hibernate.annotations.DiscriminatorOptions;
+
+/**
+ * @author Hardy Ferentschik
+ */
+@Entity
+@DiscriminatorValue("B")
+@DiscriminatorOptions(force = true, insert = false)
+public class BaseClass {
+ @Id
+ @GeneratedValue
+ private long id;
+}
+
+
Property changes on: core/trunk/testsuite/src/test/java/org/hibernate/test/annotations/inheritance/discriminatoroptions/BaseClass.java
___________________________________________________________________
Name: svn:keywords
+ Id
Copied: core/trunk/testsuite/src/test/java/org/hibernate/test/annotations/inheritance/discriminatoroptions/DiscriminatorOptionsTest.java (from rev 20741, core/trunk/testsuite/src/test/java/org/hibernate/test/annotations/various/TimestampTest.java)
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/annotations/inheritance/discriminatoroptions/DiscriminatorOptionsTest.java (rev 0)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/annotations/inheritance/discriminatoroptions/DiscriminatorOptionsTest.java 2010-09-29 10:45:08 UTC (rev 20749)
@@ -0,0 +1,56 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+
+//$Id$
+package org.hibernate.test.annotations.inheritance.discriminatoroptions;
+
+import org.hibernate.mapping.PersistentClass;
+import org.hibernate.mapping.RootClass;
+import org.hibernate.test.annotations.TestCase;
+
+/**
+ * Test for the @DiscriminatorOptions annotations.
+ *
+ * @author Hardy Ferentschik
+ */
+public class DiscriminatorOptionsTest extends TestCase {
+
+ public void testNonDefaultOptions() throws Exception {
+ buildConfiguration();
+
+ PersistentClass persistentClass = cfg.getClassMapping( BaseClass.class.getName() );
+ assertNotNull( persistentClass );
+ assertTrue( persistentClass instanceof RootClass );
+
+ RootClass root = ( RootClass ) persistentClass;
+ assertTrue( "Discriminator should be forced", root.isForceDiscriminator() );
+ assertFalse( "Discriminator should not be insertable", root.isDiscriminatorInsertable() );
+ }
+
+ protected Class[] getAnnotatedClasses() {
+ return new Class[] {
+ BaseClass.class, SubClass.class
+ };
+ }
+}
Added: core/trunk/testsuite/src/test/java/org/hibernate/test/annotations/inheritance/discriminatoroptions/SubClass.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/annotations/inheritance/discriminatoroptions/SubClass.java (rev 0)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/annotations/inheritance/discriminatoroptions/SubClass.java 2010-09-29 10:45:08 UTC (rev 20749)
@@ -0,0 +1,42 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+
+// $Id:$
+package org.hibernate.test.annotations.inheritance.discriminatoroptions;
+
+import javax.persistence.DiscriminatorValue;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+
+/**
+ * @author Hardy Ferentschik
+ */
+@Entity
+@DiscriminatorValue("B")
+public class SubClass extends BaseClass {
+
+}
+
+
Property changes on: core/trunk/testsuite/src/test/java/org/hibernate/test/annotations/inheritance/discriminatoroptions/SubClass.java
___________________________________________________________________
Name: svn:keywords
+ Id
13 years, 7 months
Hibernate SVN: r20748 - in core/trunk: core/src/main/java/org/hibernate/cfg and 2 other directories.
by hibernate-commits@lists.jboss.org
Author: epbernard
Date: 2010-09-29 05:44:15 -0400 (Wed, 29 Sep 2010)
New Revision: 20748
Added:
core/trunk/core/src/main/java/org/hibernate/annotations/ColumnTransformer.java
core/trunk/core/src/main/java/org/hibernate/annotations/ColumnTransformers.java
core/trunk/testsuite/src/test/java/org/hibernate/test/annotations/various/readwriteexpression/ColumnTransformerTest.java
Removed:
core/trunk/core/src/main/java/org/hibernate/annotations/ReadWriteExpression.java
core/trunk/core/src/main/java/org/hibernate/annotations/ReadWriteExpressions.java
core/trunk/testsuite/src/test/java/org/hibernate/test/annotations/various/readwriteexpression/ReadWriteExpressionTest.java
Modified:
core/trunk/core/src/main/java/org/hibernate/cfg/Ejb3Column.java
core/trunk/documentation/manual/src/main/docbook/en-US/content/basic_mapping.xml
core/trunk/testsuite/src/test/java/org/hibernate/test/annotations/various/readwriteexpression/Staff.java
Log:
HHH-4510 Rename @ReadWriteExpression to @ColumnTransformer
It relates to the ResultTransformer we have but at the column level
Copied: core/trunk/core/src/main/java/org/hibernate/annotations/ColumnTransformer.java (from rev 20747, core/trunk/core/src/main/java/org/hibernate/annotations/ReadWriteExpression.java)
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/annotations/ColumnTransformer.java (rev 0)
+++ core/trunk/core/src/main/java/org/hibernate/annotations/ColumnTransformer.java 2010-09-29 09:44:15 UTC (rev 20748)
@@ -0,0 +1,61 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat, Inc. and/or its affiliates 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.annotations;
+
+import java.lang.annotation.Retention;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+/**
+ * Custom SQL expression used to read the value from and write a value to a column.
+ * Use for direct object loading/saving as well as queries.
+ * The write expression must contain exactly one '?' placeholder for the value.
+ *
+ * For example: <code>read="decrypt(credit_card_num)" write="encrypt(?)"</code>
+ *
+ * @author Emmanuel Bernard
+ */
+(a)java.lang.annotation.Target({FIELD,METHOD})
+@Retention(RUNTIME)
+public @interface ColumnTransformer {
+ /**
+ * (Logical) column name for which the expression is used
+ *
+ * This can be left out if the property is bound to a single column
+ */
+ String forColumn() default "";
+
+ /**
+ * Custom SQL expression used to read from the column
+ */
+ String read() default "";
+
+ /**
+ * Custom SQL expression used to write to the column.
+ * The write expression must contain exactly one '?' placeholder for the value.
+ */
+ String write() default "";
+}
Copied: core/trunk/core/src/main/java/org/hibernate/annotations/ColumnTransformers.java (from rev 20747, core/trunk/core/src/main/java/org/hibernate/annotations/ReadWriteExpressions.java)
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/annotations/ColumnTransformers.java (rev 0)
+++ core/trunk/core/src/main/java/org/hibernate/annotations/ColumnTransformers.java 2010-09-29 09:44:15 UTC (rev 20748)
@@ -0,0 +1,42 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat, Inc. and/or its affiliates 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.annotations;
+
+import java.lang.annotation.Retention;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+/**
+ * Plural annotation for @ColumnTransformer.
+ * Useful when more than one column is using this behavior.
+ *
+ * @author Emmanuel Bernard
+ */
+(a)java.lang.annotation.Target({FIELD,METHOD})
+@Retention(RUNTIME)
+public @interface ColumnTransformers {
+ ColumnTransformer[] value();
+}
Deleted: core/trunk/core/src/main/java/org/hibernate/annotations/ReadWriteExpression.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/annotations/ReadWriteExpression.java 2010-09-29 09:42:52 UTC (rev 20747)
+++ core/trunk/core/src/main/java/org/hibernate/annotations/ReadWriteExpression.java 2010-09-29 09:44:15 UTC (rev 20748)
@@ -1,59 +0,0 @@
-/*
- * Hibernate, Relational Persistence for Idiomatic Java
- *
- * Copyright (c) 2010, Red Hat, Inc. and/or its affiliates 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.annotations;
-
-import java.lang.annotation.Retention;
-
-import static java.lang.annotation.ElementType.FIELD;
-import static java.lang.annotation.ElementType.METHOD;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-/**
- * Custom SQL expression used to read the value from and write a value to a column.
- * Use for direct object loading/saving as well as queries.
- * The write expression must contain exactly one '?' placeholder for the value.
- *
- * For example: <code>read="decrypt(credit_card_num)" write="encrypt(?)"</code>
- *
- * @author Emmanuel Bernard
- */
-(a)java.lang.annotation.Target({FIELD,METHOD})
-@Retention(RUNTIME)
-public @interface ReadWriteExpression {
- /**
- * (Logical) column name for which the expression is used
- */
- String forColumn() default "";
-
- /**
- * Custom SQL expression used to read from the column
- */
- String read() default "";
-
- /**
- * Custom SQL expression used to write to the column.
- * The write expression must contain exactly one '?' placeholder for the value.
- */
- String write() default "";
-}
Deleted: core/trunk/core/src/main/java/org/hibernate/annotations/ReadWriteExpressions.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/annotations/ReadWriteExpressions.java 2010-09-29 09:42:52 UTC (rev 20747)
+++ core/trunk/core/src/main/java/org/hibernate/annotations/ReadWriteExpressions.java 2010-09-29 09:44:15 UTC (rev 20748)
@@ -1,42 +0,0 @@
-/*
- * Hibernate, Relational Persistence for Idiomatic Java
- *
- * Copyright (c) 2010, Red Hat, Inc. and/or its affiliates 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.annotations;
-
-import java.lang.annotation.Retention;
-
-import static java.lang.annotation.ElementType.FIELD;
-import static java.lang.annotation.ElementType.METHOD;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-/**
- * Plural annotation for @ReadWriteExpressions.
- * Useful when more than one column is using this behavior.
- *
- * @author Emmanuel Bernard
- */
-(a)java.lang.annotation.Target({FIELD,METHOD})
-@Retention(RUNTIME)
-public @interface ReadWriteExpressions {
- ReadWriteExpression[] value();
-}
Modified: core/trunk/core/src/main/java/org/hibernate/cfg/Ejb3Column.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/cfg/Ejb3Column.java 2010-09-29 09:42:52 UTC (rev 20747)
+++ core/trunk/core/src/main/java/org/hibernate/cfg/Ejb3Column.java 2010-09-29 09:44:15 UTC (rev 20748)
@@ -27,9 +27,9 @@
import org.hibernate.AnnotationException;
import org.hibernate.AssertionFailure;
+import org.hibernate.annotations.ColumnTransformer;
+import org.hibernate.annotations.ColumnTransformers;
import org.hibernate.annotations.Index;
-import org.hibernate.annotations.ReadWriteExpression;
-import org.hibernate.annotations.ReadWriteExpressions;
import org.hibernate.annotations.common.reflection.XProperty;
import org.hibernate.cfg.annotations.Nullability;
import org.hibernate.mapping.Column;
@@ -483,10 +483,10 @@
if ( inferredData != null ) {
XProperty property = inferredData.getProperty();
if ( property != null ) {
- processExpression( property.getAnnotation( ReadWriteExpression.class ) );
- ReadWriteExpressions annotations = property.getAnnotation( ReadWriteExpressions.class );
+ processExpression( property.getAnnotation( ColumnTransformer.class ) );
+ ColumnTransformers annotations = property.getAnnotation( ColumnTransformers.class );
if (annotations != null) {
- for ( ReadWriteExpression annotation : annotations.value() ) {
+ for ( ColumnTransformer annotation : annotations.value() ) {
processExpression( annotation );
}
}
@@ -494,7 +494,7 @@
}
}
- private void processExpression(ReadWriteExpression annotation) {
+ private void processExpression(ColumnTransformer annotation) {
String nonNullLogicalColumnName = logicalColumnName != null ? logicalColumnName : ""; //use the default for annotations
if ( annotation != null &&
( StringHelper.isEmpty( annotation.forColumn() )
Modified: core/trunk/documentation/manual/src/main/docbook/en-US/content/basic_mapping.xml
===================================================================
--- core/trunk/documentation/manual/src/main/docbook/en-US/content/basic_mapping.xml 2010-09-29 09:42:52 UTC (rev 20747)
+++ core/trunk/documentation/manual/src/main/docbook/en-US/content/basic_mapping.xml 2010-09-29 09:44:15 UTC (rev 20748)
@@ -2225,8 +2225,8 @@
<classname>org.hibernate.annotations.SourceType.VM</classname> and
<classname>org.hibernate.annotations.SourceType.DB</classname>. The
default is <classname>SourceType.DB</classname> which is also used in
- case there is no <classname>@Source</classname> annotation at all.
- </para>
+ case there is no <classname>@Source</classname> annotation at
+ all.</para>
<para>Like in the case of version numbers, the timestamp can also be
generated by the database instead of Hibernate. To do that, use
@@ -5782,7 +5782,7 @@
</section>
<section id="mapping-column-read-and-write" revision="1">
- <title>Column read and write expressions</title>
+ <title>Column transformers: read and write expressions</title>
<para>Hibernate allows you to customize the SQL it uses to read and write
the values of columns mapped to <link
@@ -5793,7 +5793,7 @@
<programlisting role="JAVA">@Entity
class CreditCard {
@Column(name="credit_card_num")
- @ReadWriteExpression(
+ @ColumnTransformer(
read="decrypt(credit_card_num)",
write="encrypt(?)")
public String getCreditCardNumber() { return creditCardNumber; }
@@ -5812,8 +5812,8 @@
<note>
<para>You can use the plural form
- <classname>@ReadWriteExpressions</classname> if more than one columns
- need to define either of these rules.</para>
+ <classname>@ColumnTransformers</classname> if more than one columns need
+ to define either of these rules.</para>
</note>
<para>If a property uses more that one column, you must use the
@@ -5826,7 +5826,7 @@
@Columns( {
@Column(name="credit_card_num"),
@Column(name="exp_date") } )
- @ReadWriteExpression(
+ @ColumnTransformer(
forColumn="credit_card_num",
read="decrypt(credit_card_num)",
write="encrypt(?)")
Copied: core/trunk/testsuite/src/test/java/org/hibernate/test/annotations/various/readwriteexpression/ColumnTransformerTest.java (from rev 20747, core/trunk/testsuite/src/test/java/org/hibernate/test/annotations/various/readwriteexpression/ReadWriteExpressionTest.java)
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/annotations/various/readwriteexpression/ColumnTransformerTest.java (rev 0)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/annotations/various/readwriteexpression/ColumnTransformerTest.java 2010-09-29 09:44:15 UTC (rev 20748)
@@ -0,0 +1,89 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat, Inc. and/or its affiliates 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.test.annotations.various.readwriteexpression;
+
+import org.hibernate.Session;
+import org.hibernate.Transaction;
+import org.hibernate.criterion.Restrictions;
+import org.hibernate.test.annotations.TestCase;
+
+/**
+ * @author Emmanuel Bernard
+ */
+public class ColumnTransformerTest extends TestCase {
+
+ public void testCustomColumnReadAndWrite() throws Exception{
+ Session s = openSession();
+ Transaction t = s.beginTransaction();
+ final double HEIGHT_INCHES = 73;
+ final double HEIGHT_CENTIMETERS = HEIGHT_INCHES * 2.54d;
+
+ Staff staff = new Staff(HEIGHT_INCHES, HEIGHT_INCHES, HEIGHT_INCHES*2, 1);
+ s.persist( staff );
+ s.flush();
+
+ // Test value conversion during insert
+ Double heightViaSql = (Double)s.createSQLQuery("select size_in_cm from t_staff where t_staff.id=1").uniqueResult();
+ assertEquals(HEIGHT_CENTIMETERS, heightViaSql, 0.01d);
+
+ heightViaSql = (Double)s.createSQLQuery("select radiusS from t_staff where t_staff.id=1").uniqueResult();
+ assertEquals(HEIGHT_CENTIMETERS, heightViaSql, 0.01d);
+
+ heightViaSql = (Double)s.createSQLQuery("select diamet from t_staff where t_staff.id=1").uniqueResult();
+ assertEquals(HEIGHT_CENTIMETERS*2, heightViaSql, 0.01d);
+
+ // Test projection
+ Double heightViaHql = (Double)s.createQuery("select s.sizeInInches from Staff s where s.id = 1").uniqueResult();
+ assertEquals(HEIGHT_INCHES, heightViaHql, 0.01d);
+
+ // Test restriction and entity load via criteria
+ staff = (Staff)s.createCriteria(Staff.class)
+ .add( Restrictions.between("sizeInInches", HEIGHT_INCHES - 0.01d, HEIGHT_INCHES + 0.01d))
+ .uniqueResult();
+ assertEquals(HEIGHT_INCHES, staff.getSizeInInches(), 0.01d);
+
+ // Test predicate and entity load via HQL
+ staff = (Staff)s.createQuery("from Staff s where s.sizeInInches between ? and ?")
+ .setDouble(0, HEIGHT_INCHES - 0.01d)
+ .setDouble(1, HEIGHT_INCHES + 0.01d)
+ .uniqueResult();
+ assertEquals(HEIGHT_INCHES, staff.getSizeInInches(), 0.01d);
+
+ // Test update
+ staff.setSizeInInches(1);
+ s.flush();
+ heightViaSql = (Double)s.createSQLQuery("select size_in_cm from t_staff where t_staff.id=1").uniqueResult();
+ assertEquals(2.54d, heightViaSql, 0.01d);
+ s.delete(staff);
+ t.commit();
+ s.close();
+ }
+
+ @Override
+ protected Class<?>[] getAnnotatedClasses() {
+ return new Class<?>[] {
+ Staff.class
+ };
+ }
+}
Deleted: core/trunk/testsuite/src/test/java/org/hibernate/test/annotations/various/readwriteexpression/ReadWriteExpressionTest.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/annotations/various/readwriteexpression/ReadWriteExpressionTest.java 2010-09-29 09:42:52 UTC (rev 20747)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/annotations/various/readwriteexpression/ReadWriteExpressionTest.java 2010-09-29 09:44:15 UTC (rev 20748)
@@ -1,89 +0,0 @@
-/*
- * Hibernate, Relational Persistence for Idiomatic Java
- *
- * Copyright (c) 2010, Red Hat, Inc. and/or its affiliates 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.test.annotations.various.readwriteexpression;
-
-import org.hibernate.Session;
-import org.hibernate.Transaction;
-import org.hibernate.criterion.Restrictions;
-import org.hibernate.test.annotations.TestCase;
-
-/**
- * @author Emmanuel Bernard
- */
-public class ReadWriteExpressionTest extends TestCase {
-
- public void testCustomColumnReadAndWrite() throws Exception{
- Session s = openSession();
- Transaction t = s.beginTransaction();
- final double HEIGHT_INCHES = 73;
- final double HEIGHT_CENTIMETERS = HEIGHT_INCHES * 2.54d;
-
- Staff staff = new Staff(HEIGHT_INCHES, HEIGHT_INCHES, HEIGHT_INCHES*2, 1);
- s.persist( staff );
- s.flush();
-
- // Test value conversion during insert
- Double heightViaSql = (Double)s.createSQLQuery("select size_in_cm from t_staff where t_staff.id=1").uniqueResult();
- assertEquals(HEIGHT_CENTIMETERS, heightViaSql, 0.01d);
-
- heightViaSql = (Double)s.createSQLQuery("select radiusS from t_staff where t_staff.id=1").uniqueResult();
- assertEquals(HEIGHT_CENTIMETERS, heightViaSql, 0.01d);
-
- heightViaSql = (Double)s.createSQLQuery("select diamet from t_staff where t_staff.id=1").uniqueResult();
- assertEquals(HEIGHT_CENTIMETERS*2, heightViaSql, 0.01d);
-
- // Test projection
- Double heightViaHql = (Double)s.createQuery("select s.sizeInInches from Staff s where s.id = 1").uniqueResult();
- assertEquals(HEIGHT_INCHES, heightViaHql, 0.01d);
-
- // Test restriction and entity load via criteria
- staff = (Staff)s.createCriteria(Staff.class)
- .add( Restrictions.between("sizeInInches", HEIGHT_INCHES - 0.01d, HEIGHT_INCHES + 0.01d))
- .uniqueResult();
- assertEquals(HEIGHT_INCHES, staff.getSizeInInches(), 0.01d);
-
- // Test predicate and entity load via HQL
- staff = (Staff)s.createQuery("from Staff s where s.sizeInInches between ? and ?")
- .setDouble(0, HEIGHT_INCHES - 0.01d)
- .setDouble(1, HEIGHT_INCHES + 0.01d)
- .uniqueResult();
- assertEquals(HEIGHT_INCHES, staff.getSizeInInches(), 0.01d);
-
- // Test update
- staff.setSizeInInches(1);
- s.flush();
- heightViaSql = (Double)s.createSQLQuery("select size_in_cm from t_staff where t_staff.id=1").uniqueResult();
- assertEquals(2.54d, heightViaSql, 0.01d);
- s.delete(staff);
- t.commit();
- s.close();
- }
-
- @Override
- protected Class<?>[] getAnnotatedClasses() {
- return new Class<?>[] {
- Staff.class
- };
- }
-}
Modified: core/trunk/testsuite/src/test/java/org/hibernate/test/annotations/various/readwriteexpression/Staff.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/annotations/various/readwriteexpression/Staff.java 2010-09-29 09:42:52 UTC (rev 20747)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/annotations/various/readwriteexpression/Staff.java 2010-09-29 09:44:15 UTC (rev 20748)
@@ -28,7 +28,7 @@
import javax.persistence.Id;
import javax.persistence.Table;
-import org.hibernate.annotations.ReadWriteExpression;
+import org.hibernate.annotations.ColumnTransformer;
/**
* @author Emmanuel Bernard
@@ -50,7 +50,7 @@
private Integer id;
@Column(name="size_in_cm")
- @ReadWriteExpression(
+ @ColumnTransformer(
forColumn = "size_in_cm",
read = "size_in_cm / 2.54",
write = "? * 2.54" )
@@ -59,7 +59,7 @@
private double sizeInInches;
//Weird extra S to avoid potential SQL keywords
- @ReadWriteExpression(
+ @ColumnTransformer(
read = "radiusS / 2.54",
write = "? * 2.54" )
public double getRadiusS() { return radiusS; }
@@ -67,7 +67,7 @@
private double radiusS;
@Column(name="diamet")
- @ReadWriteExpression(
+ @ColumnTransformer(
read = "diamet / 2.54",
write = "? * 2.54" )
public double getDiameter() { return diameter; }
13 years, 7 months
Hibernate SVN: r20747 - in core/trunk: testsuite/src/test/java/org/hibernate/test/annotations/various/readwriteexpression and 1 other directory.
by hibernate-commits@lists.jboss.org
Author: epbernard
Date: 2010-09-29 05:42:52 -0400 (Wed, 29 Sep 2010)
New Revision: 20747
Modified:
core/trunk/core/src/main/java/org/hibernate/cfg/Ejb3Column.java
core/trunk/testsuite/src/test/java/org/hibernate/test/annotations/various/readwriteexpression/ReadWriteExpressionTest.java
core/trunk/testsuite/src/test/java/org/hibernate/test/annotations/various/readwriteexpression/Staff.java
Log:
HHH-4510 Fix bug where explicit @Column would not match @ReadWriteExpresion with empty forColumn
Modified: core/trunk/core/src/main/java/org/hibernate/cfg/Ejb3Column.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/cfg/Ejb3Column.java 2010-09-29 09:12:51 UTC (rev 20746)
+++ core/trunk/core/src/main/java/org/hibernate/cfg/Ejb3Column.java 2010-09-29 09:42:52 UTC (rev 20747)
@@ -496,7 +496,9 @@
private void processExpression(ReadWriteExpression annotation) {
String nonNullLogicalColumnName = logicalColumnName != null ? logicalColumnName : ""; //use the default for annotations
- if ( annotation != null && annotation.forColumn().equals( nonNullLogicalColumnName ) ) {
+ if ( annotation != null &&
+ ( StringHelper.isEmpty( annotation.forColumn() )
+ || annotation.forColumn().equals( nonNullLogicalColumnName ) ) ) {
readExpression = annotation.read();
if ( StringHelper.isEmpty( readExpression ) ) {
readExpression = null;
Modified: core/trunk/testsuite/src/test/java/org/hibernate/test/annotations/various/readwriteexpression/ReadWriteExpressionTest.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/annotations/various/readwriteexpression/ReadWriteExpressionTest.java 2010-09-29 09:12:51 UTC (rev 20746)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/annotations/various/readwriteexpression/ReadWriteExpressionTest.java 2010-09-29 09:42:52 UTC (rev 20747)
@@ -23,8 +23,6 @@
*/
package org.hibernate.test.annotations.various.readwriteexpression;
-import java.util.Date;
-
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.criterion.Restrictions;
@@ -41,7 +39,7 @@
final double HEIGHT_INCHES = 73;
final double HEIGHT_CENTIMETERS = HEIGHT_INCHES * 2.54d;
- Staff staff = new Staff(HEIGHT_INCHES, HEIGHT_INCHES, 1);
+ Staff staff = new Staff(HEIGHT_INCHES, HEIGHT_INCHES, HEIGHT_INCHES*2, 1);
s.persist( staff );
s.flush();
@@ -52,6 +50,9 @@
heightViaSql = (Double)s.createSQLQuery("select radiusS from t_staff where t_staff.id=1").uniqueResult();
assertEquals(HEIGHT_CENTIMETERS, heightViaSql, 0.01d);
+ heightViaSql = (Double)s.createSQLQuery("select diamet from t_staff where t_staff.id=1").uniqueResult();
+ assertEquals(HEIGHT_CENTIMETERS*2, heightViaSql, 0.01d);
+
// Test projection
Double heightViaHql = (Double)s.createQuery("select s.sizeInInches from Staff s where s.id = 1").uniqueResult();
assertEquals(HEIGHT_INCHES, heightViaHql, 0.01d);
Modified: core/trunk/testsuite/src/test/java/org/hibernate/test/annotations/various/readwriteexpression/Staff.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/annotations/various/readwriteexpression/Staff.java 2010-09-29 09:12:51 UTC (rev 20746)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/annotations/various/readwriteexpression/Staff.java 2010-09-29 09:42:52 UTC (rev 20747)
@@ -37,9 +37,10 @@
@Table(name="t_staff")
public class Staff {
- public Staff(double sizeInInches, double radius, Integer id) {
+ public Staff(double sizeInInches, double radius, double diameter, Integer id) {
this.sizeInInches = sizeInInches;
this.radiusS = radius;
+ this.diameter = diameter;
this.id = id;
}
@@ -57,10 +58,19 @@
public void setSizeInInches(double sizeInInches) { this.sizeInInches = sizeInInches; }
private double sizeInInches;
+ //Weird extra S to avoid potential SQL keywords
@ReadWriteExpression(
read = "radiusS / 2.54",
write = "? * 2.54" )
public double getRadiusS() { return radiusS; }
public void setRadiusS(double radiusS) { this.radiusS = radiusS; }
private double radiusS;
+
+ @Column(name="diamet")
+ @ReadWriteExpression(
+ read = "diamet / 2.54",
+ write = "? * 2.54" )
+ public double getDiameter() { return diameter; }
+ public void setDiameter(double diameter) { this.diameter = diameter; }
+ private double diameter;
}
13 years, 7 months
Hibernate SVN: r20746 - in core/trunk: core/src/main/java/org/hibernate/cfg and 2 other directories.
by hibernate-commits@lists.jboss.org
Author: epbernard
Date: 2010-09-29 05:12:51 -0400 (Wed, 29 Sep 2010)
New Revision: 20746
Modified:
core/trunk/core/src/main/java/org/hibernate/annotations/ReadWriteExpression.java
core/trunk/core/src/main/java/org/hibernate/cfg/Ejb3Column.java
core/trunk/documentation/manual/src/main/docbook/en-US/content/basic_mapping.xml
core/trunk/testsuite/src/test/java/org/hibernate/test/annotations/various/readwriteexpression/Staff.java
Log:
HHH-4510 Allow forColumn to be left if a property has a single column
Modified: core/trunk/core/src/main/java/org/hibernate/annotations/ReadWriteExpression.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/annotations/ReadWriteExpression.java 2010-09-28 23:50:53 UTC (rev 20745)
+++ core/trunk/core/src/main/java/org/hibernate/annotations/ReadWriteExpression.java 2010-09-29 09:12:51 UTC (rev 20746)
@@ -44,7 +44,7 @@
/**
* (Logical) column name for which the expression is used
*/
- String forColumn();
+ String forColumn() default "";
/**
* Custom SQL expression used to read from the column
Modified: core/trunk/core/src/main/java/org/hibernate/cfg/Ejb3Column.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/cfg/Ejb3Column.java 2010-09-28 23:50:53 UTC (rev 20745)
+++ core/trunk/core/src/main/java/org/hibernate/cfg/Ejb3Column.java 2010-09-29 09:12:51 UTC (rev 20746)
@@ -495,7 +495,8 @@
}
private void processExpression(ReadWriteExpression annotation) {
- if ( annotation != null && annotation.forColumn().equals( logicalColumnName ) ) {
+ String nonNullLogicalColumnName = logicalColumnName != null ? logicalColumnName : ""; //use the default for annotations
+ if ( annotation != null && annotation.forColumn().equals( nonNullLogicalColumnName ) ) {
readExpression = annotation.read();
if ( StringHelper.isEmpty( readExpression ) ) {
readExpression = null;
Modified: core/trunk/documentation/manual/src/main/docbook/en-US/content/basic_mapping.xml
===================================================================
--- core/trunk/documentation/manual/src/main/docbook/en-US/content/basic_mapping.xml 2010-09-28 23:50:53 UTC (rev 20745)
+++ core/trunk/documentation/manual/src/main/docbook/en-US/content/basic_mapping.xml 2010-09-29 09:12:51 UTC (rev 20746)
@@ -5794,7 +5794,6 @@
class CreditCard {
@Column(name="credit_card_num")
@ReadWriteExpression(
- forColumn="credit_card_num",
read="decrypt(credit_card_num)",
write="encrypt(?)")
public String getCreditCardNumber() { return creditCardNumber; }
@@ -5812,12 +5811,30 @@
</property></programlisting>
<note>
- <para>When using <classname>@ReadWriteExpression</classname>, you must
- explicitly declare the <literal>@Column.name</literal> property. You can
- use the plural form <classname>@ReadWriteExpressions</classname> if more
- than one columns need to define either of these rules.</para>
+ <para>You can use the plural form
+ <classname>@ReadWriteExpressions</classname> if more than one columns
+ need to define either of these rules.</para>
</note>
+ <para>If a property uses more that one column, you must use the
+ <literal>forColumn</literal> attribute to specify which column, the
+ expressions are targeting.</para>
+
+ <programlisting role="JAVA">@Entity
+class User {
+ @Type(type="com.acme.type.CreditCardType")
+ @Columns( {
+ @Column(name="credit_card_num"),
+ @Column(name="exp_date") } )
+ @ReadWriteExpression(
+ forColumn="credit_card_num",
+ read="decrypt(credit_card_num)",
+ write="encrypt(?)")
+ public CreditCard getCreditCard() { return creditCard; }
+ public void setCreditCard(CreditCard card) { this.creditCard = card; }
+ private CreditCard creditCard;
+}</programlisting>
+
<para>Hibernate applies the custom expressions automatically whenever the
property is referenced in a query. This functionality is similar to a
derived-property <literal>formula</literal> with two differences:
Modified: core/trunk/testsuite/src/test/java/org/hibernate/test/annotations/various/readwriteexpression/Staff.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/annotations/various/readwriteexpression/Staff.java 2010-09-28 23:50:53 UTC (rev 20745)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/annotations/various/readwriteexpression/Staff.java 2010-09-29 09:12:51 UTC (rev 20746)
@@ -57,9 +57,7 @@
public void setSizeInInches(double sizeInInches) { this.sizeInInches = sizeInInches; }
private double sizeInInches;
- @Column(name="radiusS")
@ReadWriteExpression(
- forColumn = "radiusS",
read = "radiusS / 2.54",
write = "? * 2.54" )
public double getRadiusS() { return radiusS; }
13 years, 7 months
Hibernate SVN: r20745 - in core/trunk: envers/src/main/java/org/hibernate/envers/configuration and 4 other directories.
by hibernate-commits@lists.jboss.org
Author: fbascheper
Date: 2010-09-28 19:50:53 -0400 (Tue, 28 Sep 2010)
New Revision: 20745
Removed:
core/trunk/envers/src/test/java/org/hibernate/envers/test/integration/strategy/
Modified:
core/trunk/documentation/envers/src/main/docbook/en-US/content/configuration.xml
core/trunk/envers/src/main/java/org/hibernate/envers/configuration/AuditConfiguration.java
core/trunk/envers/src/main/java/org/hibernate/envers/configuration/AuditEntitiesConfiguration.java
core/trunk/envers/src/main/java/org/hibernate/envers/configuration/RevisionInfoConfiguration.java
core/trunk/envers/src/main/java/org/hibernate/envers/configuration/metadata/AuditMetadataGenerator.java
core/trunk/envers/src/main/java/org/hibernate/envers/configuration/metadata/MetadataTools.java
core/trunk/envers/src/main/java/org/hibernate/envers/strategy/ValidityAuditStrategy.java
core/trunk/envers/src/test/resources/testng.xml
Log:
HHH5371 - Rollback until after 3.6.0 release as per Adam's request via IM
Modified: core/trunk/documentation/envers/src/main/docbook/en-US/content/configuration.xml
===================================================================
--- core/trunk/documentation/envers/src/main/docbook/en-US/content/configuration.xml 2010-09-28 22:24:09 UTC (rev 20744)
+++ core/trunk/documentation/envers/src/main/docbook/en-US/content/configuration.xml 2010-09-28 23:50:53 UTC (rev 20745)
@@ -249,33 +249,6 @@
valid if the validity audit strategy is used.
</entry>
</row>
- <row>
- <entry>
- <property>org.hibernate.envers.audit_strategy_validity_store_revend_timestamp</property>
- </entry>
- <entry>
- false
- </entry>
- <entry>
- Should the timestamp of the end revision be stored, until which the data was valid, in addition to the end revision itself.
- This is useful to be able to purge old Audit records out of a relational database by using table partitioning.
- Partitioning requires a column that exists within the table.
- This property is only evaluated if the ValidityAuditStrategy is used.
- </entry>
- </row>
- <row>
- <entry>
- <property>org.hibernate.envers.audit_strategy_validity_revend_timestamp_field_name</property>
- </entry>
- <entry>
- REVEND_TSTMP
- </entry>
- <entry>
- Column name of the timestamp of the end revision until which the data was valid.
- Only used if the ValidityAuditStrategy is used, and
- org.hibernate.envers.audit_strategy_validity_store_revend_timestamp evaluates to true
- </entry>
- </row>
</tbody>
</tgroup>
</table>
Modified: core/trunk/envers/src/main/java/org/hibernate/envers/configuration/AuditConfiguration.java
===================================================================
--- core/trunk/envers/src/main/java/org/hibernate/envers/configuration/AuditConfiguration.java 2010-09-28 22:24:09 UTC (rev 20744)
+++ core/trunk/envers/src/main/java/org/hibernate/envers/configuration/AuditConfiguration.java 2010-09-28 23:50:53 UTC (rev 20745)
@@ -28,18 +28,16 @@
import java.util.WeakHashMap;
import org.hibernate.MappingException;
-import org.hibernate.annotations.common.reflection.ReflectionManager;
-import org.hibernate.cfg.Configuration;
import org.hibernate.envers.entities.EntitiesConfigurations;
-import org.hibernate.envers.entities.PropertyData;
import org.hibernate.envers.revisioninfo.RevisionInfoNumberReader;
import org.hibernate.envers.revisioninfo.RevisionInfoQueryCreator;
-import org.hibernate.envers.strategy.AuditStrategy;
-import org.hibernate.envers.strategy.ValidityAuditStrategy;
import org.hibernate.envers.synchronization.AuditProcessManager;
-import org.hibernate.envers.tools.reflection.ReflectionTools;
-import org.hibernate.property.Getter;
+import org.hibernate.envers.strategy.AuditStrategy;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.cfg.AnnotationConfiguration;
+import org.hibernate.annotations.common.reflection.ReflectionManager;
+
/**
* @author Adam Warski (adam at warski dot org)
* @author Stephanie Pau at Markit Group Plc
@@ -81,6 +79,7 @@
return auditStrategy;
}
+ @SuppressWarnings({ "unchecked" })
public AuditConfiguration(Configuration cfg) {
Properties properties = cfg.getProperties();
@@ -90,33 +89,20 @@
auditEntCfg = new AuditEntitiesConfiguration(properties, revInfoCfgResult.getRevisionInfoEntityName());
globalCfg = new GlobalConfiguration(properties);
auditProcessManager = new AuditProcessManager(revInfoCfgResult.getRevisionInfoGenerator());
+
+ try {
+ Class auditStrategyClass = Thread.currentThread().getContextClassLoader().loadClass(auditEntCfg.getAuditStrategyName());
+ auditStrategy = (AuditStrategy) auditStrategyClass.newInstance();
+ } catch (Exception e) {
+ throw new MappingException(String.format("Unable to create AuditStrategy[%s] instance." , auditEntCfg.getAuditStrategyName()));
+ }
+
revisionInfoQueryCreator = revInfoCfgResult.getRevisionInfoQueryCreator();
revisionInfoNumberReader = revInfoCfgResult.getRevisionInfoNumberReader();
- auditStrategy = initializeAuditStrategy(revInfoCfgResult.getRevisionInfoClass(),
- revInfoCfgResult.getRevisionInfoTimestampData());
entCfg = new EntitiesConfigurator().configure(cfg, reflectionManager, globalCfg, auditEntCfg, auditStrategy,
revInfoCfgResult.getRevisionInfoXmlMapping(), revInfoCfgResult.getRevisionInfoRelationMapping());
}
- private AuditStrategy initializeAuditStrategy(Class<?> revisionInfoClass, PropertyData revisionInfoTimestampData) {
- AuditStrategy strategy;
-
- try {
- Class<?> auditStrategyClass = Thread.currentThread().getContextClassLoader().loadClass(auditEntCfg.getAuditStrategyName());
- strategy = (AuditStrategy) auditStrategyClass.newInstance();
- } catch (Exception e) {
- throw new MappingException(String.format("Unable to create AuditStrategy[%s] instance." , auditEntCfg.getAuditStrategyName()));
- }
-
- if (strategy instanceof ValidityAuditStrategy) {
- // further initialization required
- Getter revisionTimestampGetter = ReflectionTools.getGetter(revisionInfoClass, revisionInfoTimestampData);
- ((ValidityAuditStrategy) strategy).setRevisionTimestampGetter(revisionTimestampGetter);
- }
-
- return strategy;
- }
-
//
private static Map<Configuration, AuditConfiguration> cfgs
Modified: core/trunk/envers/src/main/java/org/hibernate/envers/configuration/AuditEntitiesConfiguration.java
===================================================================
--- core/trunk/envers/src/main/java/org/hibernate/envers/configuration/AuditEntitiesConfiguration.java 2010-09-28 22:24:09 UTC (rev 20744)
+++ core/trunk/envers/src/main/java/org/hibernate/envers/configuration/AuditEntitiesConfiguration.java 2010-09-28 23:50:53 UTC (rev 20745)
@@ -25,11 +25,17 @@
import static org.hibernate.envers.tools.Tools.getProperty;
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
+import org.hibernate.MappingException;
import org.hibernate.envers.strategy.DefaultAuditStrategy;
+import org.hibernate.envers.strategy.ValidityAuditStrategy;
/**
* Configuration of versions entities - names of fields, entities and tables created to store versioning information.
@@ -55,9 +61,6 @@
private final Map<String, String> customAuditTablesNames;
private final String revisionEndFieldName;
-
- private final boolean revisionEndTimestampEnabled;
- private final String revisionEndTimestampFieldName;
public AuditEntitiesConfiguration(Properties properties, String revisionInfoEntityName) {
this.revisionInfoEntityName = revisionInfoEntityName;
@@ -94,21 +97,6 @@
"org.hibernate.envers.audit_strategy_valid_time_end_name",
"REVEND");
- String revisionEndTimestampEnabledStr = getProperty(properties,
- "org.hibernate.envers.audit_strategy_validity_store_revend_timestamp",
- "org.hibernate.envers.audit_strategy_validity_store_revend_timestamp",
- "false");
- revisionEndTimestampEnabled = Boolean.parseBoolean(revisionEndTimestampEnabledStr);
-
- if (revisionEndTimestampEnabled) {
- revisionEndTimestampFieldName = getProperty(properties,
- "org.hibernate.envers.audit_strategy_validity_revend_timestamp_field_name",
- "org.hibernate.envers.audit_strategy_validity_revend_timestamp_field_name",
- "REVEND_TSTMP");
- } else {
- revisionEndTimestampFieldName = null;
- }
-
customAuditTablesNames = new HashMap<String, String>();
revisionNumberPath = originalIdPropName + "." + revisionFieldName + ".id";
@@ -123,14 +111,6 @@
return revisionFieldName;
}
- public boolean isRevisionEndTimestampEnabled() {
- return revisionEndTimestampEnabled;
- }
-
- public String getRevisionEndTimestampFieldName() {
- return revisionEndTimestampFieldName;
- }
-
public String getRevisionNumberPath() {
return revisionNumberPath;
}
Modified: core/trunk/envers/src/main/java/org/hibernate/envers/configuration/RevisionInfoConfiguration.java
===================================================================
--- core/trunk/envers/src/main/java/org/hibernate/envers/configuration/RevisionInfoConfiguration.java 2010-09-28 22:24:09 UTC (rev 20744)
+++ core/trunk/envers/src/main/java/org/hibernate/envers/configuration/RevisionInfoConfiguration.java 2010-09-28 23:50:53 UTC (rev 20745)
@@ -29,6 +29,7 @@
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
+import org.hibernate.envers.Audited;
import org.hibernate.envers.*;
import org.hibernate.envers.entities.PropertyData;
import org.hibernate.envers.configuration.metadata.MetadataTools;
@@ -175,6 +176,7 @@
"property");
}
+ @SuppressWarnings({"unchecked"})
public RevisionInfoConfigurationResult configure(Configuration cfg, ReflectionManager reflectionManager) {
Iterator<PersistentClass> classes = (Iterator<PersistentClass>) cfg.getClassMappings();
boolean revisionEntityFound = false;
@@ -243,8 +245,7 @@
new RevisionInfoQueryCreator(revisionInfoEntityName, revisionInfoIdData.getName(),
revisionInfoTimestampData.getName(), isTimestampAsDate()),
generateRevisionInfoRelationMapping(),
- new RevisionInfoNumberReader(revisionInfoClass, revisionInfoIdData), revisionInfoEntityName,
- revisionInfoClass, revisionInfoTimestampData);
+ new RevisionInfoNumberReader(revisionInfoClass, revisionInfoIdData), revisionInfoEntityName);
}
private boolean isTimestampAsDate() {
@@ -260,22 +261,17 @@
private final Element revisionInfoRelationMapping;
private final RevisionInfoNumberReader revisionInfoNumberReader;
private final String revisionInfoEntityName;
- private final Class<?> revisionInfoClass;
- private final PropertyData revisionInfoTimestampData;
RevisionInfoConfigurationResult(RevisionInfoGenerator revisionInfoGenerator,
Document revisionInfoXmlMapping, RevisionInfoQueryCreator revisionInfoQueryCreator,
Element revisionInfoRelationMapping,
- RevisionInfoNumberReader revisionInfoNumberReader, String revisionInfoEntityName, Class<?> revisionInfoClass,
- PropertyData revisionInfoTimestampData) {
+ RevisionInfoNumberReader revisionInfoNumberReader, String revisionInfoEntityName) {
this.revisionInfoGenerator = revisionInfoGenerator;
this.revisionInfoXmlMapping = revisionInfoXmlMapping;
this.revisionInfoQueryCreator = revisionInfoQueryCreator;
this.revisionInfoRelationMapping = revisionInfoRelationMapping;
this.revisionInfoNumberReader = revisionInfoNumberReader;
this.revisionInfoEntityName = revisionInfoEntityName;
- this.revisionInfoClass = revisionInfoClass;
- this.revisionInfoTimestampData = revisionInfoTimestampData;
}
public RevisionInfoGenerator getRevisionInfoGenerator() {
@@ -301,13 +297,4 @@
public String getRevisionInfoEntityName() {
return revisionInfoEntityName;
}
-
- public Class<?> getRevisionInfoClass() {
- return revisionInfoClass;
- }
-
- public PropertyData getRevisionInfoTimestampData() {
- return revisionInfoTimestampData;
- }
-
}
\ No newline at end of file
Modified: core/trunk/envers/src/main/java/org/hibernate/envers/configuration/metadata/AuditMetadataGenerator.java
===================================================================
--- core/trunk/envers/src/main/java/org/hibernate/envers/configuration/metadata/AuditMetadataGenerator.java 2010-09-28 22:24:09 UTC (rev 20744)
+++ core/trunk/envers/src/main/java/org/hibernate/envers/configuration/metadata/AuditMetadataGenerator.java 2010-09-28 23:50:53 UTC (rev 20745)
@@ -55,7 +55,6 @@
import org.hibernate.type.ComponentType;
import org.hibernate.type.ManyToOneType;
import org.hibernate.type.OneToOneType;
-import org.hibernate.type.TimestampType;
import org.hibernate.type.Type;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -65,7 +64,7 @@
* @author Sebastian Komander
* @author Tomasz Bech
* @author Stephanie Pau at Markit Group Plc
- * @author Hernán Chanfreau
+ * @author Hern�n Chanfreau
*/
public final class AuditMetadataGenerator {
private static final Logger log = LoggerFactory.getLogger(AuditMetadataGenerator.class);
@@ -145,7 +144,7 @@
addEndRevision(any_mapping);
}
- private void addEndRevision(Element any_mapping ) {
+ private void addEndRevision(Element any_mapping) {
// Add the end-revision field, if the appropriate strategy is used.
if (auditStrategy instanceof ValidityAuditStrategy) {
Element end_rev_mapping = (Element) revisionInfoRelationMapping.clone();
@@ -154,16 +153,10 @@
MetadataTools.addOrModifyColumn(end_rev_mapping, verEntCfg.getRevisionEndFieldName());
any_mapping.add(end_rev_mapping);
-
- if (verEntCfg.isRevisionEndTimestampEnabled()) {
- // add a column for the timestamp of the end revision
- String revisionInfoTimestampSqlType = TimestampType.INSTANCE.getName();
- Element timestampProperty = MetadataTools.addProperty(any_mapping, verEntCfg.getRevisionEndTimestampFieldName(), revisionInfoTimestampSqlType, true, true, false);
- MetadataTools.addColumn(timestampProperty, verEntCfg.getRevisionEndTimestampFieldName(), 0, 0, 0, null);
- }
}
}
+ @SuppressWarnings({"unchecked"})
void addValue(Element parent, Value value, CompositeMapperBuilder currentMapper, String entityName,
EntityXmlMappingData xmlMappingData, PropertyAuditingData propertyAuditingData,
boolean insertable, boolean firstPass) {
@@ -211,6 +204,7 @@
}
}
+ @SuppressWarnings({"unchecked"})
private void addProperties(Element parent, Iterator<Property> properties, CompositeMapperBuilder currentMapper,
ClassAuditingData auditingData, String entityName, EntityXmlMappingData xmlMappingData,
boolean firstPass) {
Modified: core/trunk/envers/src/main/java/org/hibernate/envers/configuration/metadata/MetadataTools.java
===================================================================
--- core/trunk/envers/src/main/java/org/hibernate/envers/configuration/metadata/MetadataTools.java 2010-09-28 22:24:09 UTC (rev 20744)
+++ core/trunk/envers/src/main/java/org/hibernate/envers/configuration/metadata/MetadataTools.java 2010-09-28 23:50:53 UTC (rev 20745)
@@ -49,7 +49,7 @@
return id_mapping;
}
- public static Element addProperty(Element parent, String name, String type, boolean insertable, boolean updateable, boolean key) {
+ public static Element addProperty(Element parent, String name, String type, boolean insertable, boolean key) {
Element prop_mapping;
if (key) {
prop_mapping = parent.addElement("key-property");
@@ -59,7 +59,7 @@
prop_mapping.addAttribute("name", name);
prop_mapping.addAttribute("insert", Boolean.toString(insertable));
- prop_mapping.addAttribute("update", Boolean.toString(updateable));
+ prop_mapping.addAttribute("update", "false");
if (type != null) {
prop_mapping.addAttribute("type", type);
@@ -68,10 +68,6 @@
return prop_mapping;
}
- public static Element addProperty(Element parent, String name, String type, boolean insertable, boolean key) {
- return addProperty(parent, name, type, insertable, false, key);
- }
-
private static void addOrModifyAttribute(Element parent, String name, String value) {
Attribute attribute = parent.attribute(name);
if (attribute == null) {
Modified: core/trunk/envers/src/main/java/org/hibernate/envers/strategy/ValidityAuditStrategy.java
===================================================================
--- core/trunk/envers/src/main/java/org/hibernate/envers/strategy/ValidityAuditStrategy.java 2010-09-28 22:24:09 UTC (rev 20744)
+++ core/trunk/envers/src/main/java/org/hibernate/envers/strategy/ValidityAuditStrategy.java 2010-09-28 23:50:53 UTC (rev 20745)
@@ -1,7 +1,6 @@
package org.hibernate.envers.strategy;
import java.io.Serializable;
-import java.util.Date;
import java.util.List;
import java.util.Map;
@@ -16,7 +15,6 @@
import org.hibernate.envers.entities.mapper.relation.MiddleIdData;
import org.hibernate.envers.tools.query.Parameters;
import org.hibernate.envers.tools.query.QueryBuilder;
-import org.hibernate.property.Getter;
/**
* Audit strategy which persists and retrieves audit information using a validity algorithm, based on the
@@ -41,11 +39,7 @@
* @author Adam Warski (adam at warski dot org)
*/
public class ValidityAuditStrategy implements AuditStrategy {
-
- /** getter for the revision entity field annotated with @RevisionTimestamp */
- private Getter revisionTimestampGetter = null;
-
- public void perform(Session session, String entityName, AuditConfiguration auditCfg, Serializable id, Object data,
+ public void perform(Session session, String entityName, AuditConfiguration auditCfg, Serializable id, Object data,
Object revision) {
AuditEntitiesConfiguration audEntCfg = auditCfg.getAuditEntCfg();
String auditedEntityName = audEntCfg.getAuditEntityName(entityName);
@@ -74,22 +68,27 @@
public void performCollectionChange(Session session, AuditConfiguration auditCfg,
PersistentCollectionChangeData persistentCollectionChangeData, Object revision) {
// Update the end date of the previous row if this operation is expected to have a previous row
- // Constructing a query (there are multiple id fields):
- // select e from audited_middle_ent e where e.end_rev is null and e.id1 = :id1 and e.id2 = :id2 ...
+ if (getRevisionType(auditCfg, persistentCollectionChangeData.getData()) != RevisionType.ADD) {
+ /*
+ Constructing a query (there are multiple id fields):
+ select e from audited_middle_ent e where e.end_rev is null and e.id1 = :id1 and e.id2 = :id2 ...
+ */
- QueryBuilder qb = new QueryBuilder(persistentCollectionChangeData.getEntityName(), "e");
+ QueryBuilder qb = new QueryBuilder(persistentCollectionChangeData.getEntityName(), "e");
- // Adding a parameter for each id component, except the rev number
- String originalIdPropName = auditCfg.getAuditEntCfg().getOriginalIdPropName();
- Map<String, Object> originalId = (Map<String, Object>) persistentCollectionChangeData.getData().get(
+ // Adding a parameter for each id component, except the rev number
+ String originalIdPropName = auditCfg.getAuditEntCfg().getOriginalIdPropName();
+ Map<String, Object> originalId = (Map<String, Object>) persistentCollectionChangeData.getData().get(
originalIdPropName);
- for (Map.Entry<String, Object> originalIdEntry : originalId.entrySet()) {
- if (!auditCfg.getAuditEntCfg().getRevisionFieldName().equals(originalIdEntry.getKey())) {
- qb.getRootParameters().addWhereWithParam(originalIdPropName + "." + originalIdEntry.getKey(),
- true, "=", originalIdEntry.getValue());
- }
+ for (Map.Entry<String, Object> originalIdEntry : originalId.entrySet()) {
+ if (!auditCfg.getAuditEntCfg().getRevisionFieldName().equals(originalIdEntry.getKey())) {
+ qb.getRootParameters().addWhereWithParam(originalIdPropName + "." + originalIdEntry.getKey(),
+ true, "=", originalIdEntry.getValue());
+ }
+ }
+
+ updateLastRevision(session, auditCfg, qb, originalId, persistentCollectionChangeData.getEntityName(), revision);
}
- updateLastRevision(session, auditCfg, qb, originalId, persistentCollectionChangeData.getEntityName(), revision);
// Save the audit data
session.save(persistentCollectionChangeData.getEntityName(), persistentCollectionChangeData.getData());
@@ -111,11 +110,7 @@
addRevisionRestriction(rootParameters, revisionProperty, revisionEndProperty, addAlias);
}
- public void setRevisionTimestampGetter(Getter revisionTimestampGetter) {
- this.revisionTimestampGetter = revisionTimestampGetter;
- }
-
- private void addRevisionRestriction(Parameters rootParameters,
+ private void addRevisionRestriction(Parameters rootParameters,
String revisionProperty, String revisionEndProperty, boolean addAlias) {
// e.revision <= _revision and (e.endRevision > _revision or e.endRevision is null)
@@ -134,7 +129,7 @@
private void updateLastRevision(Session session, AuditConfiguration auditCfg, QueryBuilder qb,
Object id, String auditedEntityName, Object revision) {
String revisionEndFieldName = auditCfg.getAuditEntCfg().getRevisionEndFieldName();
-
+
// e.end_rev is null
qb.getRootParameters().addWhere(revisionEndFieldName, true, "is", "null", false);
@@ -146,28 +141,10 @@
Object previousData = l.get(0);
((Map<String, Object>) previousData).put(revisionEndFieldName, revision);
- if (auditCfg.getAuditEntCfg().isRevisionEndTimestampEnabled()) {
- // Determine the value of the revision property annotated with @RevisionTimestamp
- Date revisionEndTimestamp;
- String revEndTimestampFieldName = auditCfg.getAuditEntCfg().getRevisionEndTimestampFieldName();
- Object revEndTimestampObj = this.revisionTimestampGetter.get(revision);
-
- // convert to a java.util.Date
- if (revEndTimestampObj instanceof Date) {
- revisionEndTimestamp = (Date) revEndTimestampObj;
- } else {
- revisionEndTimestamp = new Date((Long) revEndTimestampObj);
- }
-
- // Setting the end revision timestamp
- ((Map<String, Object>) previousData).put(revEndTimestampFieldName, revisionEndTimestamp);
- }
-
// Saving the previous version
session.save(auditedEntityName, previousData);
-
- } else if(l.size() > 1) {
- throw new RuntimeException("Cannot find previous revision for entity " + auditedEntityName + " and id " + id + " received " + l.size() + " rows back");
+ } else {
+ throw new RuntimeException("Cannot find previous revision for entity " + auditedEntityName + " and id " + id);
}
}
}
Modified: core/trunk/envers/src/test/resources/testng.xml
===================================================================
--- core/trunk/envers/src/test/resources/testng.xml 2010-09-28 22:24:09 UTC (rev 20744)
+++ core/trunk/envers/src/test/resources/testng.xml 2010-09-28 23:50:53 UTC (rev 20745)
@@ -68,7 +68,6 @@
<package name="org.hibernate.envers.test.integration.secondary" />
<package name="org.hibernate.envers.test.integration.secondary.ids" />
<package name="org.hibernate.envers.test.integration.serialization" />
- <package name="org.hibernate.envers.test.integration.strategy" />
<package name="org.hibernate.envers.test.integration.superclass" />
<package name="org.hibernate.envers.test.integration.entityNames.auditedEntity" />
<package name="org.hibernate.envers.test.integration.entityNames.manyToManyAudited" />
13 years, 7 months
Hibernate SVN: r20744 - core/trunk/documentation/envers/src/main/docbook/en-US/content.
by hibernate-commits@lists.jboss.org
Author: fbascheper
Date: 2010-09-28 18:24:09 -0400 (Tue, 28 Sep 2010)
New Revision: 20744
Modified:
core/trunk/documentation/envers/src/main/docbook/en-US/content/configuration.xml
Log:
HHH-5371 - Add support for REVEND_TSTMP which will enable audit table partitioning
Modified: core/trunk/documentation/envers/src/main/docbook/en-US/content/configuration.xml
===================================================================
--- core/trunk/documentation/envers/src/main/docbook/en-US/content/configuration.xml 2010-09-28 22:23:04 UTC (rev 20743)
+++ core/trunk/documentation/envers/src/main/docbook/en-US/content/configuration.xml 2010-09-28 22:24:09 UTC (rev 20744)
@@ -249,6 +249,33 @@
valid if the validity audit strategy is used.
</entry>
</row>
+ <row>
+ <entry>
+ <property>org.hibernate.envers.audit_strategy_validity_store_revend_timestamp</property>
+ </entry>
+ <entry>
+ false
+ </entry>
+ <entry>
+ Should the timestamp of the end revision be stored, until which the data was valid, in addition to the end revision itself.
+ This is useful to be able to purge old Audit records out of a relational database by using table partitioning.
+ Partitioning requires a column that exists within the table.
+ This property is only evaluated if the ValidityAuditStrategy is used.
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <property>org.hibernate.envers.audit_strategy_validity_revend_timestamp_field_name</property>
+ </entry>
+ <entry>
+ REVEND_TSTMP
+ </entry>
+ <entry>
+ Column name of the timestamp of the end revision until which the data was valid.
+ Only used if the ValidityAuditStrategy is used, and
+ org.hibernate.envers.audit_strategy_validity_store_revend_timestamp evaluates to true
+ </entry>
+ </row>
</tbody>
</tgroup>
</table>
13 years, 7 months
Hibernate SVN: r20743 - in core/trunk/envers/src: main/java/org/hibernate/envers/configuration/metadata and 4 other directories.
by hibernate-commits@lists.jboss.org
Author: fbascheper
Date: 2010-09-28 18:23:04 -0400 (Tue, 28 Sep 2010)
New Revision: 20743
Added:
core/trunk/envers/src/test/java/org/hibernate/envers/test/integration/strategy/
core/trunk/envers/src/test/java/org/hibernate/envers/test/integration/strategy/ValidityAuditStrategyRevEndTestCustomRevEnt.java
core/trunk/envers/src/test/java/org/hibernate/envers/test/integration/strategy/ValidityAuditStrategyRevEndTsTest.java
Modified:
core/trunk/envers/src/main/java/org/hibernate/envers/configuration/AuditConfiguration.java
core/trunk/envers/src/main/java/org/hibernate/envers/configuration/AuditEntitiesConfiguration.java
core/trunk/envers/src/main/java/org/hibernate/envers/configuration/RevisionInfoConfiguration.java
core/trunk/envers/src/main/java/org/hibernate/envers/configuration/metadata/AuditMetadataGenerator.java
core/trunk/envers/src/main/java/org/hibernate/envers/configuration/metadata/MetadataTools.java
core/trunk/envers/src/main/java/org/hibernate/envers/strategy/ValidityAuditStrategy.java
core/trunk/envers/src/test/resources/testng.xml
Log:
HHH-5371 - Add support for REVEND_TSTMP which will enable audit table partitioning
Modified: core/trunk/envers/src/main/java/org/hibernate/envers/configuration/AuditConfiguration.java
===================================================================
--- core/trunk/envers/src/main/java/org/hibernate/envers/configuration/AuditConfiguration.java 2010-09-28 16:39:06 UTC (rev 20742)
+++ core/trunk/envers/src/main/java/org/hibernate/envers/configuration/AuditConfiguration.java 2010-09-28 22:23:04 UTC (rev 20743)
@@ -28,16 +28,18 @@
import java.util.WeakHashMap;
import org.hibernate.MappingException;
+import org.hibernate.annotations.common.reflection.ReflectionManager;
+import org.hibernate.cfg.Configuration;
import org.hibernate.envers.entities.EntitiesConfigurations;
+import org.hibernate.envers.entities.PropertyData;
import org.hibernate.envers.revisioninfo.RevisionInfoNumberReader;
import org.hibernate.envers.revisioninfo.RevisionInfoQueryCreator;
+import org.hibernate.envers.strategy.AuditStrategy;
+import org.hibernate.envers.strategy.ValidityAuditStrategy;
import org.hibernate.envers.synchronization.AuditProcessManager;
-import org.hibernate.envers.strategy.AuditStrategy;
+import org.hibernate.envers.tools.reflection.ReflectionTools;
+import org.hibernate.property.Getter;
-import org.hibernate.cfg.Configuration;
-import org.hibernate.cfg.AnnotationConfiguration;
-import org.hibernate.annotations.common.reflection.ReflectionManager;
-
/**
* @author Adam Warski (adam at warski dot org)
* @author Stephanie Pau at Markit Group Plc
@@ -79,7 +81,6 @@
return auditStrategy;
}
- @SuppressWarnings({ "unchecked" })
public AuditConfiguration(Configuration cfg) {
Properties properties = cfg.getProperties();
@@ -89,20 +90,33 @@
auditEntCfg = new AuditEntitiesConfiguration(properties, revInfoCfgResult.getRevisionInfoEntityName());
globalCfg = new GlobalConfiguration(properties);
auditProcessManager = new AuditProcessManager(revInfoCfgResult.getRevisionInfoGenerator());
-
- try {
- Class auditStrategyClass = Thread.currentThread().getContextClassLoader().loadClass(auditEntCfg.getAuditStrategyName());
- auditStrategy = (AuditStrategy) auditStrategyClass.newInstance();
- } catch (Exception e) {
- throw new MappingException(String.format("Unable to create AuditStrategy[%s] instance." , auditEntCfg.getAuditStrategyName()));
- }
-
revisionInfoQueryCreator = revInfoCfgResult.getRevisionInfoQueryCreator();
revisionInfoNumberReader = revInfoCfgResult.getRevisionInfoNumberReader();
+ auditStrategy = initializeAuditStrategy(revInfoCfgResult.getRevisionInfoClass(),
+ revInfoCfgResult.getRevisionInfoTimestampData());
entCfg = new EntitiesConfigurator().configure(cfg, reflectionManager, globalCfg, auditEntCfg, auditStrategy,
revInfoCfgResult.getRevisionInfoXmlMapping(), revInfoCfgResult.getRevisionInfoRelationMapping());
}
+ private AuditStrategy initializeAuditStrategy(Class<?> revisionInfoClass, PropertyData revisionInfoTimestampData) {
+ AuditStrategy strategy;
+
+ try {
+ Class<?> auditStrategyClass = Thread.currentThread().getContextClassLoader().loadClass(auditEntCfg.getAuditStrategyName());
+ strategy = (AuditStrategy) auditStrategyClass.newInstance();
+ } catch (Exception e) {
+ throw new MappingException(String.format("Unable to create AuditStrategy[%s] instance." , auditEntCfg.getAuditStrategyName()));
+ }
+
+ if (strategy instanceof ValidityAuditStrategy) {
+ // further initialization required
+ Getter revisionTimestampGetter = ReflectionTools.getGetter(revisionInfoClass, revisionInfoTimestampData);
+ ((ValidityAuditStrategy) strategy).setRevisionTimestampGetter(revisionTimestampGetter);
+ }
+
+ return strategy;
+ }
+
//
private static Map<Configuration, AuditConfiguration> cfgs
Modified: core/trunk/envers/src/main/java/org/hibernate/envers/configuration/AuditEntitiesConfiguration.java
===================================================================
--- core/trunk/envers/src/main/java/org/hibernate/envers/configuration/AuditEntitiesConfiguration.java 2010-09-28 16:39:06 UTC (rev 20742)
+++ core/trunk/envers/src/main/java/org/hibernate/envers/configuration/AuditEntitiesConfiguration.java 2010-09-28 22:23:04 UTC (rev 20743)
@@ -25,17 +25,11 @@
import static org.hibernate.envers.tools.Tools.getProperty;
-import java.text.DateFormat;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
-import org.hibernate.MappingException;
import org.hibernate.envers.strategy.DefaultAuditStrategy;
-import org.hibernate.envers.strategy.ValidityAuditStrategy;
/**
* Configuration of versions entities - names of fields, entities and tables created to store versioning information.
@@ -61,6 +55,9 @@
private final Map<String, String> customAuditTablesNames;
private final String revisionEndFieldName;
+
+ private final boolean revisionEndTimestampEnabled;
+ private final String revisionEndTimestampFieldName;
public AuditEntitiesConfiguration(Properties properties, String revisionInfoEntityName) {
this.revisionInfoEntityName = revisionInfoEntityName;
@@ -97,6 +94,21 @@
"org.hibernate.envers.audit_strategy_valid_time_end_name",
"REVEND");
+ String revisionEndTimestampEnabledStr = getProperty(properties,
+ "org.hibernate.envers.audit_strategy_validity_store_revend_timestamp",
+ "org.hibernate.envers.audit_strategy_validity_store_revend_timestamp",
+ "false");
+ revisionEndTimestampEnabled = Boolean.parseBoolean(revisionEndTimestampEnabledStr);
+
+ if (revisionEndTimestampEnabled) {
+ revisionEndTimestampFieldName = getProperty(properties,
+ "org.hibernate.envers.audit_strategy_validity_revend_timestamp_field_name",
+ "org.hibernate.envers.audit_strategy_validity_revend_timestamp_field_name",
+ "REVEND_TSTMP");
+ } else {
+ revisionEndTimestampFieldName = null;
+ }
+
customAuditTablesNames = new HashMap<String, String>();
revisionNumberPath = originalIdPropName + "." + revisionFieldName + ".id";
@@ -111,6 +123,14 @@
return revisionFieldName;
}
+ public boolean isRevisionEndTimestampEnabled() {
+ return revisionEndTimestampEnabled;
+ }
+
+ public String getRevisionEndTimestampFieldName() {
+ return revisionEndTimestampFieldName;
+ }
+
public String getRevisionNumberPath() {
return revisionNumberPath;
}
Modified: core/trunk/envers/src/main/java/org/hibernate/envers/configuration/RevisionInfoConfiguration.java
===================================================================
--- core/trunk/envers/src/main/java/org/hibernate/envers/configuration/RevisionInfoConfiguration.java 2010-09-28 16:39:06 UTC (rev 20742)
+++ core/trunk/envers/src/main/java/org/hibernate/envers/configuration/RevisionInfoConfiguration.java 2010-09-28 22:23:04 UTC (rev 20743)
@@ -29,7 +29,6 @@
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
-import org.hibernate.envers.Audited;
import org.hibernate.envers.*;
import org.hibernate.envers.entities.PropertyData;
import org.hibernate.envers.configuration.metadata.MetadataTools;
@@ -176,7 +175,6 @@
"property");
}
- @SuppressWarnings({"unchecked"})
public RevisionInfoConfigurationResult configure(Configuration cfg, ReflectionManager reflectionManager) {
Iterator<PersistentClass> classes = (Iterator<PersistentClass>) cfg.getClassMappings();
boolean revisionEntityFound = false;
@@ -245,7 +243,8 @@
new RevisionInfoQueryCreator(revisionInfoEntityName, revisionInfoIdData.getName(),
revisionInfoTimestampData.getName(), isTimestampAsDate()),
generateRevisionInfoRelationMapping(),
- new RevisionInfoNumberReader(revisionInfoClass, revisionInfoIdData), revisionInfoEntityName);
+ new RevisionInfoNumberReader(revisionInfoClass, revisionInfoIdData), revisionInfoEntityName,
+ revisionInfoClass, revisionInfoTimestampData);
}
private boolean isTimestampAsDate() {
@@ -261,17 +260,22 @@
private final Element revisionInfoRelationMapping;
private final RevisionInfoNumberReader revisionInfoNumberReader;
private final String revisionInfoEntityName;
+ private final Class<?> revisionInfoClass;
+ private final PropertyData revisionInfoTimestampData;
RevisionInfoConfigurationResult(RevisionInfoGenerator revisionInfoGenerator,
Document revisionInfoXmlMapping, RevisionInfoQueryCreator revisionInfoQueryCreator,
Element revisionInfoRelationMapping,
- RevisionInfoNumberReader revisionInfoNumberReader, String revisionInfoEntityName) {
+ RevisionInfoNumberReader revisionInfoNumberReader, String revisionInfoEntityName, Class<?> revisionInfoClass,
+ PropertyData revisionInfoTimestampData) {
this.revisionInfoGenerator = revisionInfoGenerator;
this.revisionInfoXmlMapping = revisionInfoXmlMapping;
this.revisionInfoQueryCreator = revisionInfoQueryCreator;
this.revisionInfoRelationMapping = revisionInfoRelationMapping;
this.revisionInfoNumberReader = revisionInfoNumberReader;
this.revisionInfoEntityName = revisionInfoEntityName;
+ this.revisionInfoClass = revisionInfoClass;
+ this.revisionInfoTimestampData = revisionInfoTimestampData;
}
public RevisionInfoGenerator getRevisionInfoGenerator() {
@@ -297,4 +301,13 @@
public String getRevisionInfoEntityName() {
return revisionInfoEntityName;
}
+
+ public Class<?> getRevisionInfoClass() {
+ return revisionInfoClass;
+ }
+
+ public PropertyData getRevisionInfoTimestampData() {
+ return revisionInfoTimestampData;
+ }
+
}
\ No newline at end of file
Modified: core/trunk/envers/src/main/java/org/hibernate/envers/configuration/metadata/AuditMetadataGenerator.java
===================================================================
--- core/trunk/envers/src/main/java/org/hibernate/envers/configuration/metadata/AuditMetadataGenerator.java 2010-09-28 16:39:06 UTC (rev 20742)
+++ core/trunk/envers/src/main/java/org/hibernate/envers/configuration/metadata/AuditMetadataGenerator.java 2010-09-28 22:23:04 UTC (rev 20743)
@@ -55,6 +55,7 @@
import org.hibernate.type.ComponentType;
import org.hibernate.type.ManyToOneType;
import org.hibernate.type.OneToOneType;
+import org.hibernate.type.TimestampType;
import org.hibernate.type.Type;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -64,7 +65,7 @@
* @author Sebastian Komander
* @author Tomasz Bech
* @author Stephanie Pau at Markit Group Plc
- * @author Hern�n Chanfreau
+ * @author Hernán Chanfreau
*/
public final class AuditMetadataGenerator {
private static final Logger log = LoggerFactory.getLogger(AuditMetadataGenerator.class);
@@ -144,7 +145,7 @@
addEndRevision(any_mapping);
}
- private void addEndRevision(Element any_mapping) {
+ private void addEndRevision(Element any_mapping ) {
// Add the end-revision field, if the appropriate strategy is used.
if (auditStrategy instanceof ValidityAuditStrategy) {
Element end_rev_mapping = (Element) revisionInfoRelationMapping.clone();
@@ -153,10 +154,16 @@
MetadataTools.addOrModifyColumn(end_rev_mapping, verEntCfg.getRevisionEndFieldName());
any_mapping.add(end_rev_mapping);
+
+ if (verEntCfg.isRevisionEndTimestampEnabled()) {
+ // add a column for the timestamp of the end revision
+ String revisionInfoTimestampSqlType = TimestampType.INSTANCE.getName();
+ Element timestampProperty = MetadataTools.addProperty(any_mapping, verEntCfg.getRevisionEndTimestampFieldName(), revisionInfoTimestampSqlType, true, true, false);
+ MetadataTools.addColumn(timestampProperty, verEntCfg.getRevisionEndTimestampFieldName(), 0, 0, 0, null);
+ }
}
}
- @SuppressWarnings({"unchecked"})
void addValue(Element parent, Value value, CompositeMapperBuilder currentMapper, String entityName,
EntityXmlMappingData xmlMappingData, PropertyAuditingData propertyAuditingData,
boolean insertable, boolean firstPass) {
@@ -204,7 +211,6 @@
}
}
- @SuppressWarnings({"unchecked"})
private void addProperties(Element parent, Iterator<Property> properties, CompositeMapperBuilder currentMapper,
ClassAuditingData auditingData, String entityName, EntityXmlMappingData xmlMappingData,
boolean firstPass) {
Modified: core/trunk/envers/src/main/java/org/hibernate/envers/configuration/metadata/MetadataTools.java
===================================================================
--- core/trunk/envers/src/main/java/org/hibernate/envers/configuration/metadata/MetadataTools.java 2010-09-28 16:39:06 UTC (rev 20742)
+++ core/trunk/envers/src/main/java/org/hibernate/envers/configuration/metadata/MetadataTools.java 2010-09-28 22:23:04 UTC (rev 20743)
@@ -49,7 +49,7 @@
return id_mapping;
}
- public static Element addProperty(Element parent, String name, String type, boolean insertable, boolean key) {
+ public static Element addProperty(Element parent, String name, String type, boolean insertable, boolean updateable, boolean key) {
Element prop_mapping;
if (key) {
prop_mapping = parent.addElement("key-property");
@@ -59,7 +59,7 @@
prop_mapping.addAttribute("name", name);
prop_mapping.addAttribute("insert", Boolean.toString(insertable));
- prop_mapping.addAttribute("update", "false");
+ prop_mapping.addAttribute("update", Boolean.toString(updateable));
if (type != null) {
prop_mapping.addAttribute("type", type);
@@ -68,6 +68,10 @@
return prop_mapping;
}
+ public static Element addProperty(Element parent, String name, String type, boolean insertable, boolean key) {
+ return addProperty(parent, name, type, insertable, false, key);
+ }
+
private static void addOrModifyAttribute(Element parent, String name, String value) {
Attribute attribute = parent.attribute(name);
if (attribute == null) {
Modified: core/trunk/envers/src/main/java/org/hibernate/envers/strategy/ValidityAuditStrategy.java
===================================================================
--- core/trunk/envers/src/main/java/org/hibernate/envers/strategy/ValidityAuditStrategy.java 2010-09-28 16:39:06 UTC (rev 20742)
+++ core/trunk/envers/src/main/java/org/hibernate/envers/strategy/ValidityAuditStrategy.java 2010-09-28 22:23:04 UTC (rev 20743)
@@ -1,6 +1,7 @@
package org.hibernate.envers.strategy;
import java.io.Serializable;
+import java.util.Date;
import java.util.List;
import java.util.Map;
@@ -15,6 +16,7 @@
import org.hibernate.envers.entities.mapper.relation.MiddleIdData;
import org.hibernate.envers.tools.query.Parameters;
import org.hibernate.envers.tools.query.QueryBuilder;
+import org.hibernate.property.Getter;
/**
* Audit strategy which persists and retrieves audit information using a validity algorithm, based on the
@@ -39,7 +41,11 @@
* @author Adam Warski (adam at warski dot org)
*/
public class ValidityAuditStrategy implements AuditStrategy {
- public void perform(Session session, String entityName, AuditConfiguration auditCfg, Serializable id, Object data,
+
+ /** getter for the revision entity field annotated with @RevisionTimestamp */
+ private Getter revisionTimestampGetter = null;
+
+ public void perform(Session session, String entityName, AuditConfiguration auditCfg, Serializable id, Object data,
Object revision) {
AuditEntitiesConfiguration audEntCfg = auditCfg.getAuditEntCfg();
String auditedEntityName = audEntCfg.getAuditEntityName(entityName);
@@ -68,27 +74,22 @@
public void performCollectionChange(Session session, AuditConfiguration auditCfg,
PersistentCollectionChangeData persistentCollectionChangeData, Object revision) {
// Update the end date of the previous row if this operation is expected to have a previous row
- if (getRevisionType(auditCfg, persistentCollectionChangeData.getData()) != RevisionType.ADD) {
- /*
- Constructing a query (there are multiple id fields):
- select e from audited_middle_ent e where e.end_rev is null and e.id1 = :id1 and e.id2 = :id2 ...
- */
+ // Constructing a query (there are multiple id fields):
+ // select e from audited_middle_ent e where e.end_rev is null and e.id1 = :id1 and e.id2 = :id2 ...
- QueryBuilder qb = new QueryBuilder(persistentCollectionChangeData.getEntityName(), "e");
+ QueryBuilder qb = new QueryBuilder(persistentCollectionChangeData.getEntityName(), "e");
- // Adding a parameter for each id component, except the rev number
- String originalIdPropName = auditCfg.getAuditEntCfg().getOriginalIdPropName();
- Map<String, Object> originalId = (Map<String, Object>) persistentCollectionChangeData.getData().get(
+ // Adding a parameter for each id component, except the rev number
+ String originalIdPropName = auditCfg.getAuditEntCfg().getOriginalIdPropName();
+ Map<String, Object> originalId = (Map<String, Object>) persistentCollectionChangeData.getData().get(
originalIdPropName);
- for (Map.Entry<String, Object> originalIdEntry : originalId.entrySet()) {
- if (!auditCfg.getAuditEntCfg().getRevisionFieldName().equals(originalIdEntry.getKey())) {
- qb.getRootParameters().addWhereWithParam(originalIdPropName + "." + originalIdEntry.getKey(),
- true, "=", originalIdEntry.getValue());
- }
- }
-
- updateLastRevision(session, auditCfg, qb, originalId, persistentCollectionChangeData.getEntityName(), revision);
+ for (Map.Entry<String, Object> originalIdEntry : originalId.entrySet()) {
+ if (!auditCfg.getAuditEntCfg().getRevisionFieldName().equals(originalIdEntry.getKey())) {
+ qb.getRootParameters().addWhereWithParam(originalIdPropName + "." + originalIdEntry.getKey(),
+ true, "=", originalIdEntry.getValue());
+ }
}
+ updateLastRevision(session, auditCfg, qb, originalId, persistentCollectionChangeData.getEntityName(), revision);
// Save the audit data
session.save(persistentCollectionChangeData.getEntityName(), persistentCollectionChangeData.getData());
@@ -110,7 +111,11 @@
addRevisionRestriction(rootParameters, revisionProperty, revisionEndProperty, addAlias);
}
- private void addRevisionRestriction(Parameters rootParameters,
+ public void setRevisionTimestampGetter(Getter revisionTimestampGetter) {
+ this.revisionTimestampGetter = revisionTimestampGetter;
+ }
+
+ private void addRevisionRestriction(Parameters rootParameters,
String revisionProperty, String revisionEndProperty, boolean addAlias) {
// e.revision <= _revision and (e.endRevision > _revision or e.endRevision is null)
@@ -129,7 +134,7 @@
private void updateLastRevision(Session session, AuditConfiguration auditCfg, QueryBuilder qb,
Object id, String auditedEntityName, Object revision) {
String revisionEndFieldName = auditCfg.getAuditEntCfg().getRevisionEndFieldName();
-
+
// e.end_rev is null
qb.getRootParameters().addWhere(revisionEndFieldName, true, "is", "null", false);
@@ -141,10 +146,28 @@
Object previousData = l.get(0);
((Map<String, Object>) previousData).put(revisionEndFieldName, revision);
+ if (auditCfg.getAuditEntCfg().isRevisionEndTimestampEnabled()) {
+ // Determine the value of the revision property annotated with @RevisionTimestamp
+ Date revisionEndTimestamp;
+ String revEndTimestampFieldName = auditCfg.getAuditEntCfg().getRevisionEndTimestampFieldName();
+ Object revEndTimestampObj = this.revisionTimestampGetter.get(revision);
+
+ // convert to a java.util.Date
+ if (revEndTimestampObj instanceof Date) {
+ revisionEndTimestamp = (Date) revEndTimestampObj;
+ } else {
+ revisionEndTimestamp = new Date((Long) revEndTimestampObj);
+ }
+
+ // Setting the end revision timestamp
+ ((Map<String, Object>) previousData).put(revEndTimestampFieldName, revisionEndTimestamp);
+ }
+
// Saving the previous version
session.save(auditedEntityName, previousData);
- } else {
- throw new RuntimeException("Cannot find previous revision for entity " + auditedEntityName + " and id " + id);
+
+ } else if(l.size() > 1) {
+ throw new RuntimeException("Cannot find previous revision for entity " + auditedEntityName + " and id " + id + " received " + l.size() + " rows back");
}
}
}
Added: core/trunk/envers/src/test/java/org/hibernate/envers/test/integration/strategy/ValidityAuditStrategyRevEndTestCustomRevEnt.java
===================================================================
--- core/trunk/envers/src/test/java/org/hibernate/envers/test/integration/strategy/ValidityAuditStrategyRevEndTestCustomRevEnt.java (rev 0)
+++ core/trunk/envers/src/test/java/org/hibernate/envers/test/integration/strategy/ValidityAuditStrategyRevEndTestCustomRevEnt.java 2010-09-28 22:23:04 UTC (rev 20743)
@@ -0,0 +1,433 @@
+/*
+ * 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.envers.test.integration.strategy;
+
+import java.util.Arrays;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
+
+import org.hibernate.Session;
+import org.hibernate.ejb.Ejb3Configuration;
+import org.hibernate.envers.strategy.ValidityAuditStrategy;
+import org.hibernate.envers.test.AbstractEntityTest;
+import org.hibernate.envers.test.entities.manytomany.sametable.Child1Entity;
+import org.hibernate.envers.test.entities.manytomany.sametable.Child2Entity;
+import org.hibernate.envers.test.entities.manytomany.sametable.ParentEntity;
+import org.hibernate.envers.test.entities.reventity.CustomDateRevEntity;
+import org.hibernate.envers.test.tools.TestTools;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+/**
+ * Test which checks that the revision end timestamp is correctly set for
+ * {@link ValidityAuditStrategy}.
+ *
+ * @author Erik-Berndt Scheper
+ */
+public class ValidityAuditStrategyRevEndTestCustomRevEnt extends AbstractEntityTest {
+ private final String revendTimestampColumName = "REVEND_TIMESTAMP";
+
+ private Integer p1_id;
+ private Integer p2_id;
+ private Integer c1_1_id;
+ private Integer c1_2_id;
+ private Integer c2_1_id;
+ private Integer c2_2_id;
+ private Map<Number, CustomDateRevEntity> revisions;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(ParentEntity.class);
+ cfg.addAnnotatedClass(Child1Entity.class);
+ cfg.addAnnotatedClass(Child2Entity.class);
+ cfg.addAnnotatedClass(CustomDateRevEntity.class);
+
+ cfg.setProperty("org.hibernate.envers.audit_strategy",
+ "org.hibernate.envers.strategy.ValidityAuditStrategy");
+ cfg
+ .setProperty(
+ "org.hibernate.envers.audit_strategy_validity_store_revend_timestamp",
+ "true");
+ cfg
+ .setProperty(
+ "org.hibernate.envers.audit_strategy_validity_revend_timestamp_field_name",
+ revendTimestampColumName);
+ }
+
+ @BeforeClass(enabled = true, dependsOnMethods = "init")
+ public void initData() {
+ EntityManager em = getEntityManager();
+
+ // We need first to modify the columns in the middle (join table) to
+ // allow null values. Hbm2ddl doesn't seem
+ // to allow this.
+ em.getTransaction().begin();
+ Session session = (Session) em.getDelegate();
+ session.createSQLQuery("DROP TABLE children").executeUpdate();
+ session
+ .createSQLQuery(
+ "CREATE TABLE children(parent_id integer, child1_id integer NULL, child2_id integer NULL)")
+ .executeUpdate();
+ session.createSQLQuery("DROP TABLE children_AUD").executeUpdate();
+ session
+ .createSQLQuery(
+ "CREATE TABLE children_AUD(REV integer NOT NULL, REVEND integer, "
+ + revendTimestampColumName
+ + " timestamp, REVTYPE tinyint, "
+ + "parent_id integer, child1_id integer NULL, child2_id integer NULL)")
+ .executeUpdate();
+ em.getTransaction().commit();
+ em.clear();
+
+ ParentEntity p1 = new ParentEntity("parent_1");
+ ParentEntity p2 = new ParentEntity("parent_2");
+
+ Child1Entity c1_1 = new Child1Entity("child1_1");
+ Child1Entity c1_2 = new Child1Entity("child1_2");
+
+ Child2Entity c2_1 = new Child2Entity("child2_1");
+ Child2Entity c2_2 = new Child2Entity("child2_2");
+
+ // Revision 1
+ em.getTransaction().begin();
+
+ em.persist(p1);
+ em.persist(p2);
+ em.persist(c1_1);
+ em.persist(c1_2);
+ em.persist(c2_1);
+ em.persist(c2_2);
+
+ em.getTransaction().commit();
+ em.clear();
+
+ // Revision 2 - (p1: c1_1, p2: c2_1)
+
+ em.getTransaction().begin();
+
+ p1 = em.find(ParentEntity.class, p1.getId());
+ p2 = em.find(ParentEntity.class, p2.getId());
+ c1_1 = em.find(Child1Entity.class, c1_1.getId());
+ c2_1 = em.find(Child2Entity.class, c2_1.getId());
+
+ p1.getChildren1().add(c1_1);
+ p2.getChildren2().add(c2_1);
+
+ em.getTransaction().commit();
+ em.clear();
+
+ // Revision 3 - (p1: c1_1, c1_2, c2_2, p2: c1_1, c2_1)
+ em.getTransaction().begin();
+
+ p1 = em.find(ParentEntity.class, p1.getId());
+ p2 = em.find(ParentEntity.class, p2.getId());
+ c1_1 = em.find(Child1Entity.class, c1_1.getId());
+ c1_2 = em.find(Child1Entity.class, c1_2.getId());
+ c2_2 = em.find(Child2Entity.class, c2_2.getId());
+
+ p1.getChildren1().add(c1_2);
+ p1.getChildren2().add(c2_2);
+
+ p2.getChildren1().add(c1_1);
+
+ em.getTransaction().commit();
+ em.clear();
+
+ // Revision 4 - (p1: c1_2, c2_2, p2: c1_1, c2_1, c2_2)
+ em.getTransaction().begin();
+
+ p1 = em.find(ParentEntity.class, p1.getId());
+ p2 = em.find(ParentEntity.class, p2.getId());
+ c1_1 = em.find(Child1Entity.class, c1_1.getId());
+ c2_2 = em.find(Child2Entity.class, c2_2.getId());
+
+ p1.getChildren1().remove(c1_1);
+ p2.getChildren2().add(c2_2);
+
+ em.getTransaction().commit();
+ em.clear();
+
+ // Revision 5 - (p1: c2_2, p2: c1_1, c2_1)
+ em.getTransaction().begin();
+
+ p1 = em.find(ParentEntity.class, p1.getId());
+ p2 = em.find(ParentEntity.class, p2.getId());
+ c1_2 = em.find(Child1Entity.class, c1_2.getId());
+ c2_2 = em.find(Child2Entity.class, c2_2.getId());
+
+ c2_2.getParents().remove(p2);
+ c1_2.getParents().remove(p1);
+
+ em.getTransaction().commit();
+ em.clear();
+
+ //
+
+ p1_id = p1.getId();
+ p2_id = p2.getId();
+ c1_1_id = c1_1.getId();
+ c1_2_id = c1_2.getId();
+ c2_1_id = c2_1.getId();
+ c2_2_id = c2_2.getId();
+
+ Set<Number> revisionNumbers = new HashSet<Number>();
+ revisionNumbers.addAll(Arrays.asList(1, 2, 3, 4, 5));
+ revisions = getAuditReader().findRevisions(CustomDateRevEntity.class,
+ revisionNumbers);
+
+ assert revisions.size() == 5;
+ }
+
+ @Test(enabled = true)
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 2, 3, 4).equals(
+ getAuditReader().getRevisions(ParentEntity.class, p1_id));
+ assert Arrays.asList(1, 2, 3, 4).equals(
+ getAuditReader().getRevisions(ParentEntity.class, p2_id));
+
+ assert Arrays.asList(1).equals(
+ getAuditReader().getRevisions(Child1Entity.class, c1_1_id));
+ assert Arrays.asList(1, 5).equals(
+ getAuditReader().getRevisions(Child1Entity.class, c1_2_id));
+
+ assert Arrays.asList(1).equals(
+ getAuditReader().getRevisions(Child2Entity.class, c2_1_id));
+ assert Arrays.asList(1, 5).equals(
+ getAuditReader().getRevisions(Child2Entity.class, c2_2_id));
+ }
+
+ @Test(enabled = true)
+ public void testAllRevEndTimeStamps() {
+ List<Map<String, Object>> p1RevList = getRevisions(ParentEntity.class,
+ p1_id);
+ List<Map<String, Object>> p2RevList = getRevisions(ParentEntity.class,
+ p2_id);
+ List<Map<String, Object>> c1_1_List = getRevisions(Child1Entity.class,
+ c1_1_id);
+ List<Map<String, Object>> c1_2_List = getRevisions(Child1Entity.class,
+ c1_2_id);
+ List<Map<String, Object>> c2_1_List = getRevisions(Child2Entity.class,
+ c2_1_id);
+ List<Map<String, Object>> c2_2_List = getRevisions(Child2Entity.class,
+ c2_2_id);
+
+ verifyRevEndTimeStamps("ParentEntity: " + p1_id, p1RevList);
+ verifyRevEndTimeStamps("ParentEntity: " + p2_id, p2RevList);
+ verifyRevEndTimeStamps("Child1Entity: " + c1_1_id, c1_1_List);
+ verifyRevEndTimeStamps("Child1Entity: " + c1_2_id, c1_2_List);
+ verifyRevEndTimeStamps("Child2Entity: " + c2_1_id, c2_1_List);
+ verifyRevEndTimeStamps("Child2Entity: " + c2_2_id, c2_2_List);
+
+ }
+
+ @Test(enabled = true)
+ public void testHistoryOfParent1() {
+
+ Child1Entity c1_1 = getEntityManager()
+ .find(Child1Entity.class, c1_1_id);
+ Child1Entity c1_2 = getEntityManager()
+ .find(Child1Entity.class, c1_2_id);
+ Child2Entity c2_2 = getEntityManager()
+ .find(Child2Entity.class, c2_2_id);
+
+ ParentEntity rev1 = getAuditReader().find(ParentEntity.class, p1_id, 1);
+ ParentEntity rev2 = getAuditReader().find(ParentEntity.class, p1_id, 2);
+ ParentEntity rev3 = getAuditReader().find(ParentEntity.class, p1_id, 3);
+ ParentEntity rev4 = getAuditReader().find(ParentEntity.class, p1_id, 4);
+ ParentEntity rev5 = getAuditReader().find(ParentEntity.class, p1_id, 5);
+
+ assert TestTools.checkList(rev1.getChildren1());
+ assert TestTools.checkList(rev2.getChildren1(), c1_1);
+ assert TestTools.checkList(rev3.getChildren1(), c1_1, c1_2);
+ assert TestTools.checkList(rev4.getChildren1(), c1_2);
+ assert TestTools.checkList(rev5.getChildren1());
+
+ assert TestTools.checkList(rev1.getChildren2());
+ assert TestTools.checkList(rev2.getChildren2());
+ assert TestTools.checkList(rev3.getChildren2(), c2_2);
+ assert TestTools.checkList(rev4.getChildren2(), c2_2);
+ assert TestTools.checkList(rev5.getChildren2(), c2_2);
+ }
+
+ @Test(enabled = true)
+ public void testHistoryOfParent2() {
+ Child1Entity c1_1 = getEntityManager()
+ .find(Child1Entity.class, c1_1_id);
+ Child2Entity c2_1 = getEntityManager()
+ .find(Child2Entity.class, c2_1_id);
+ Child2Entity c2_2 = getEntityManager()
+ .find(Child2Entity.class, c2_2_id);
+
+ ParentEntity rev1 = getAuditReader().find(ParentEntity.class, p2_id, 1);
+ ParentEntity rev2 = getAuditReader().find(ParentEntity.class, p2_id, 2);
+ ParentEntity rev3 = getAuditReader().find(ParentEntity.class, p2_id, 3);
+ ParentEntity rev4 = getAuditReader().find(ParentEntity.class, p2_id, 4);
+ ParentEntity rev5 = getAuditReader().find(ParentEntity.class, p2_id, 5);
+
+ assert TestTools.checkList(rev1.getChildren1());
+ assert TestTools.checkList(rev2.getChildren1());
+ assert TestTools.checkList(rev3.getChildren1(), c1_1);
+ assert TestTools.checkList(rev4.getChildren1(), c1_1);
+ assert TestTools.checkList(rev5.getChildren1(), c1_1);
+
+ assert TestTools.checkList(rev1.getChildren2());
+ assert TestTools.checkList(rev2.getChildren2(), c2_1);
+ assert TestTools.checkList(rev3.getChildren2(), c2_1);
+ assert TestTools.checkList(rev4.getChildren2(), c2_1, c2_2);
+ assert TestTools.checkList(rev5.getChildren2(), c2_1);
+ }
+
+ @Test(enabled = true)
+ public void testHistoryOfChild1_1() {
+ ParentEntity p1 = getEntityManager().find(ParentEntity.class, p1_id);
+ ParentEntity p2 = getEntityManager().find(ParentEntity.class, p2_id);
+
+ Child1Entity rev1 = getAuditReader().find(Child1Entity.class, c1_1_id,
+ 1);
+ Child1Entity rev2 = getAuditReader().find(Child1Entity.class, c1_1_id,
+ 2);
+ Child1Entity rev3 = getAuditReader().find(Child1Entity.class, c1_1_id,
+ 3);
+ Child1Entity rev4 = getAuditReader().find(Child1Entity.class, c1_1_id,
+ 4);
+ Child1Entity rev5 = getAuditReader().find(Child1Entity.class, c1_1_id,
+ 5);
+
+ assert TestTools.checkList(rev1.getParents());
+ assert TestTools.checkList(rev2.getParents(), p1);
+ assert TestTools.checkList(rev3.getParents(), p1, p2);
+ assert TestTools.checkList(rev4.getParents(), p2);
+ assert TestTools.checkList(rev5.getParents(), p2);
+ }
+
+ @Test(enabled = false)
+ public void testHistoryOfChild1_2() {
+ ParentEntity p1 = getEntityManager().find(ParentEntity.class, p1_id);
+
+ Child1Entity rev1 = getAuditReader().find(Child1Entity.class, c1_2_id,
+ 1);
+ Child1Entity rev2 = getAuditReader().find(Child1Entity.class, c1_2_id,
+ 2);
+ Child1Entity rev3 = getAuditReader().find(Child1Entity.class, c1_2_id,
+ 3);
+ Child1Entity rev4 = getAuditReader().find(Child1Entity.class, c1_2_id,
+ 4);
+ Child1Entity rev5 = getAuditReader().find(Child1Entity.class, c1_2_id,
+ 5);
+
+ assert TestTools.checkList(rev1.getParents());
+ assert TestTools.checkList(rev2.getParents());
+ assert TestTools.checkList(rev3.getParents(), p1);
+ assert TestTools.checkList(rev4.getParents(), p1);
+ assert TestTools.checkList(rev5.getParents());
+ }
+
+ @Test(enabled = true)
+ public void testHistoryOfChild2_1() {
+ ParentEntity p2 = getEntityManager().find(ParentEntity.class, p2_id);
+
+ Child2Entity rev1 = getAuditReader().find(Child2Entity.class, c2_1_id,
+ 1);
+ Child2Entity rev2 = getAuditReader().find(Child2Entity.class, c2_1_id,
+ 2);
+ Child2Entity rev3 = getAuditReader().find(Child2Entity.class, c2_1_id,
+ 3);
+ Child2Entity rev4 = getAuditReader().find(Child2Entity.class, c2_1_id,
+ 4);
+ Child2Entity rev5 = getAuditReader().find(Child2Entity.class, c2_1_id,
+ 5);
+
+ assert TestTools.checkList(rev1.getParents());
+ assert TestTools.checkList(rev2.getParents(), p2);
+ assert TestTools.checkList(rev3.getParents(), p2);
+ assert TestTools.checkList(rev4.getParents(), p2);
+ assert TestTools.checkList(rev5.getParents(), p2);
+ }
+
+ @Test(enabled = true)
+ public void testHistoryOfChild2_2() {
+ ParentEntity p1 = getEntityManager().find(ParentEntity.class, p1_id);
+ ParentEntity p2 = getEntityManager().find(ParentEntity.class, p2_id);
+
+ Child2Entity rev1 = getAuditReader().find(Child2Entity.class, c2_2_id,
+ 1);
+ Child2Entity rev2 = getAuditReader().find(Child2Entity.class, c2_2_id,
+ 2);
+ Child2Entity rev3 = getAuditReader().find(Child2Entity.class, c2_2_id,
+ 3);
+ Child2Entity rev4 = getAuditReader().find(Child2Entity.class, c2_2_id,
+ 4);
+ Child2Entity rev5 = getAuditReader().find(Child2Entity.class, c2_2_id,
+ 5);
+
+ assert TestTools.checkList(rev1.getParents());
+ assert TestTools.checkList(rev2.getParents());
+ assert TestTools.checkList(rev3.getParents(), p1);
+ assert TestTools.checkList(rev4.getParents(), p1, p2);
+ assert TestTools.checkList(rev5.getParents(), p1);
+ }
+
+ private List<Map<String, Object>> getRevisions(
+ Class<?> originalEntityClazz, Integer originalEntityId) {
+ // Build the query:
+ // select auditEntity from
+ // org.hibernate.envers.test.entities.manytomany.sametable.ParentEntity_AUD
+ // auditEntity where auditEntity.originalId.id = :originalEntityId
+
+ StringBuilder builder = new StringBuilder("select auditEntity from ");
+ builder.append(originalEntityClazz.getName())
+ .append("_AUD auditEntity");
+ builder.append(" where auditEntity.originalId.id = :originalEntityId");
+
+ Query qry = getEntityManager().createQuery(builder.toString());
+ qry.setParameter("originalEntityId", originalEntityId);
+
+ @SuppressWarnings("unchecked")
+ List<Map<String, Object>> resultList = qry.getResultList();
+ return resultList;
+ }
+
+ private void verifyRevEndTimeStamps(String debugInfo,
+ List<Map<String, Object>> revisionEntities) {
+ for (Map<String, Object> revisionEntity : revisionEntities) {
+
+ Date revendTimestamp = (Date) revisionEntity
+ .get(revendTimestampColumName);
+ CustomDateRevEntity revEnd = (CustomDateRevEntity) revisionEntity
+ .get("REVEND");
+
+ if (revendTimestamp == null) {
+ assert revEnd == null;
+ } else {
+ assert revendTimestamp.getTime() == revEnd.getDateTimestamp().getTime();
+ }
+ }
+ }
+
+}
Added: core/trunk/envers/src/test/java/org/hibernate/envers/test/integration/strategy/ValidityAuditStrategyRevEndTsTest.java
===================================================================
--- core/trunk/envers/src/test/java/org/hibernate/envers/test/integration/strategy/ValidityAuditStrategyRevEndTsTest.java (rev 0)
+++ core/trunk/envers/src/test/java/org/hibernate/envers/test/integration/strategy/ValidityAuditStrategyRevEndTsTest.java 2010-09-28 22:23:04 UTC (rev 20743)
@@ -0,0 +1,432 @@
+/*
+ * 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.envers.test.integration.strategy;
+
+import java.util.Arrays;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
+
+import org.hibernate.Session;
+import org.hibernate.ejb.Ejb3Configuration;
+import org.hibernate.envers.DefaultRevisionEntity;
+import org.hibernate.envers.strategy.ValidityAuditStrategy;
+import org.hibernate.envers.test.AbstractEntityTest;
+import org.hibernate.envers.test.entities.manytomany.sametable.Child1Entity;
+import org.hibernate.envers.test.entities.manytomany.sametable.Child2Entity;
+import org.hibernate.envers.test.entities.manytomany.sametable.ParentEntity;
+import org.hibernate.envers.test.tools.TestTools;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+/**
+ * Test which checks that the revision end timestamp is correctly set for
+ * {@link ValidityAuditStrategy}.
+ *
+ * @author Erik-Berndt Scheper
+ */
+public class ValidityAuditStrategyRevEndTsTest extends AbstractEntityTest {
+ private final String revendTimestampColumName = "REVEND_TIMESTAMP";
+
+ private Integer p1_id;
+ private Integer p2_id;
+ private Integer c1_1_id;
+ private Integer c1_2_id;
+ private Integer c2_1_id;
+ private Integer c2_2_id;
+ private Map<Number, DefaultRevisionEntity> revisions;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(ParentEntity.class);
+ cfg.addAnnotatedClass(Child1Entity.class);
+ cfg.addAnnotatedClass(Child2Entity.class);
+
+ cfg.setProperty("org.hibernate.envers.audit_strategy",
+ "org.hibernate.envers.strategy.ValidityAuditStrategy");
+ cfg
+ .setProperty(
+ "org.hibernate.envers.audit_strategy_validity_store_revend_timestamp",
+ "true");
+ cfg
+ .setProperty(
+ "org.hibernate.envers.audit_strategy_validity_revend_timestamp_field_name",
+ revendTimestampColumName);
+ }
+
+ @BeforeClass(enabled = true, dependsOnMethods = "init")
+ public void initData() {
+ EntityManager em = getEntityManager();
+
+ // We need first to modify the columns in the middle (join table) to
+ // allow null values. Hbm2ddl doesn't seem
+ // to allow this.
+ em.getTransaction().begin();
+ Session session = (Session) em.getDelegate();
+ session.createSQLQuery("DROP TABLE children").executeUpdate();
+ session
+ .createSQLQuery(
+ "CREATE TABLE children(parent_id integer, child1_id integer NULL, child2_id integer NULL)")
+ .executeUpdate();
+ session.createSQLQuery("DROP TABLE children_AUD").executeUpdate();
+ session
+ .createSQLQuery(
+ "CREATE TABLE children_AUD(REV integer NOT NULL, REVEND integer, "
+ + revendTimestampColumName
+ + " timestamp, REVTYPE tinyint, "
+ + "parent_id integer, child1_id integer NULL, child2_id integer NULL)")
+ .executeUpdate();
+ em.getTransaction().commit();
+ em.clear();
+
+ ParentEntity p1 = new ParentEntity("parent_1");
+ ParentEntity p2 = new ParentEntity("parent_2");
+
+ Child1Entity c1_1 = new Child1Entity("child1_1");
+ Child1Entity c1_2 = new Child1Entity("child1_2");
+
+ Child2Entity c2_1 = new Child2Entity("child2_1");
+ Child2Entity c2_2 = new Child2Entity("child2_2");
+
+ // Revision 1
+ em.getTransaction().begin();
+
+ em.persist(p1);
+ em.persist(p2);
+ em.persist(c1_1);
+ em.persist(c1_2);
+ em.persist(c2_1);
+ em.persist(c2_2);
+
+ em.getTransaction().commit();
+ em.clear();
+
+ // Revision 2 - (p1: c1_1, p2: c2_1)
+
+ em.getTransaction().begin();
+
+ p1 = em.find(ParentEntity.class, p1.getId());
+ p2 = em.find(ParentEntity.class, p2.getId());
+ c1_1 = em.find(Child1Entity.class, c1_1.getId());
+ c2_1 = em.find(Child2Entity.class, c2_1.getId());
+
+ p1.getChildren1().add(c1_1);
+ p2.getChildren2().add(c2_1);
+
+ em.getTransaction().commit();
+ em.clear();
+
+ // Revision 3 - (p1: c1_1, c1_2, c2_2, p2: c1_1, c2_1)
+ em.getTransaction().begin();
+
+ p1 = em.find(ParentEntity.class, p1.getId());
+ p2 = em.find(ParentEntity.class, p2.getId());
+ c1_1 = em.find(Child1Entity.class, c1_1.getId());
+ c1_2 = em.find(Child1Entity.class, c1_2.getId());
+ c2_2 = em.find(Child2Entity.class, c2_2.getId());
+
+ p1.getChildren1().add(c1_2);
+ p1.getChildren2().add(c2_2);
+
+ p2.getChildren1().add(c1_1);
+
+ em.getTransaction().commit();
+ em.clear();
+
+ // Revision 4 - (p1: c1_2, c2_2, p2: c1_1, c2_1, c2_2)
+ em.getTransaction().begin();
+
+ p1 = em.find(ParentEntity.class, p1.getId());
+ p2 = em.find(ParentEntity.class, p2.getId());
+ c1_1 = em.find(Child1Entity.class, c1_1.getId());
+ c2_2 = em.find(Child2Entity.class, c2_2.getId());
+
+ p1.getChildren1().remove(c1_1);
+ p2.getChildren2().add(c2_2);
+
+ em.getTransaction().commit();
+ em.clear();
+
+ // Revision 5 - (p1: c2_2, p2: c1_1, c2_1)
+ em.getTransaction().begin();
+
+ p1 = em.find(ParentEntity.class, p1.getId());
+ p2 = em.find(ParentEntity.class, p2.getId());
+ c1_2 = em.find(Child1Entity.class, c1_2.getId());
+ c2_2 = em.find(Child2Entity.class, c2_2.getId());
+
+ c2_2.getParents().remove(p2);
+ c1_2.getParents().remove(p1);
+
+ em.getTransaction().commit();
+ em.clear();
+
+ //
+
+ p1_id = p1.getId();
+ p2_id = p2.getId();
+ c1_1_id = c1_1.getId();
+ c1_2_id = c1_2.getId();
+ c2_1_id = c2_1.getId();
+ c2_2_id = c2_2.getId();
+
+ Set<Number> revisionNumbers = new HashSet<Number>();
+ revisionNumbers.addAll(Arrays.asList(1, 2, 3, 4, 5));
+ revisions = getAuditReader().findRevisions(DefaultRevisionEntity.class,
+ revisionNumbers);
+
+ assert revisions.size() == 5;
+ }
+
+ @Test(enabled = true)
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 2, 3, 4).equals(
+ getAuditReader().getRevisions(ParentEntity.class, p1_id));
+ assert Arrays.asList(1, 2, 3, 4).equals(
+ getAuditReader().getRevisions(ParentEntity.class, p2_id));
+
+ assert Arrays.asList(1).equals(
+ getAuditReader().getRevisions(Child1Entity.class, c1_1_id));
+ assert Arrays.asList(1, 5).equals(
+ getAuditReader().getRevisions(Child1Entity.class, c1_2_id));
+
+ assert Arrays.asList(1).equals(
+ getAuditReader().getRevisions(Child2Entity.class, c2_1_id));
+ assert Arrays.asList(1, 5).equals(
+ getAuditReader().getRevisions(Child2Entity.class, c2_2_id));
+ }
+
+ @Test(enabled = true)
+ public void testAllRevEndTimeStamps() {
+ List<Map<String, Object>> p1RevList = getRevisions(ParentEntity.class,
+ p1_id);
+ List<Map<String, Object>> p2RevList = getRevisions(ParentEntity.class,
+ p2_id);
+ List<Map<String, Object>> c1_1_List = getRevisions(Child1Entity.class,
+ c1_1_id);
+ List<Map<String, Object>> c1_2_List = getRevisions(Child1Entity.class,
+ c1_2_id);
+ List<Map<String, Object>> c2_1_List = getRevisions(Child2Entity.class,
+ c2_1_id);
+ List<Map<String, Object>> c2_2_List = getRevisions(Child2Entity.class,
+ c2_2_id);
+
+ verifyRevEndTimeStamps("ParentEntity: " + p1_id, p1RevList);
+ verifyRevEndTimeStamps("ParentEntity: " + p2_id, p2RevList);
+ verifyRevEndTimeStamps("Child1Entity: " + c1_1_id, c1_1_List);
+ verifyRevEndTimeStamps("Child1Entity: " + c1_2_id, c1_2_List);
+ verifyRevEndTimeStamps("Child2Entity: " + c2_1_id, c2_1_List);
+ verifyRevEndTimeStamps("Child2Entity: " + c2_2_id, c2_2_List);
+
+ }
+
+ @Test(enabled = true)
+ public void testHistoryOfParent1() {
+
+ Child1Entity c1_1 = getEntityManager()
+ .find(Child1Entity.class, c1_1_id);
+ Child1Entity c1_2 = getEntityManager()
+ .find(Child1Entity.class, c1_2_id);
+ Child2Entity c2_2 = getEntityManager()
+ .find(Child2Entity.class, c2_2_id);
+
+ ParentEntity rev1 = getAuditReader().find(ParentEntity.class, p1_id, 1);
+ ParentEntity rev2 = getAuditReader().find(ParentEntity.class, p1_id, 2);
+ ParentEntity rev3 = getAuditReader().find(ParentEntity.class, p1_id, 3);
+ ParentEntity rev4 = getAuditReader().find(ParentEntity.class, p1_id, 4);
+ ParentEntity rev5 = getAuditReader().find(ParentEntity.class, p1_id, 5);
+
+ assert TestTools.checkList(rev1.getChildren1());
+ assert TestTools.checkList(rev2.getChildren1(), c1_1);
+ assert TestTools.checkList(rev3.getChildren1(), c1_1, c1_2);
+ assert TestTools.checkList(rev4.getChildren1(), c1_2);
+ assert TestTools.checkList(rev5.getChildren1());
+
+ assert TestTools.checkList(rev1.getChildren2());
+ assert TestTools.checkList(rev2.getChildren2());
+ assert TestTools.checkList(rev3.getChildren2(), c2_2);
+ assert TestTools.checkList(rev4.getChildren2(), c2_2);
+ assert TestTools.checkList(rev5.getChildren2(), c2_2);
+ }
+
+ @Test(enabled = true)
+ public void testHistoryOfParent2() {
+ Child1Entity c1_1 = getEntityManager()
+ .find(Child1Entity.class, c1_1_id);
+ Child2Entity c2_1 = getEntityManager()
+ .find(Child2Entity.class, c2_1_id);
+ Child2Entity c2_2 = getEntityManager()
+ .find(Child2Entity.class, c2_2_id);
+
+ ParentEntity rev1 = getAuditReader().find(ParentEntity.class, p2_id, 1);
+ ParentEntity rev2 = getAuditReader().find(ParentEntity.class, p2_id, 2);
+ ParentEntity rev3 = getAuditReader().find(ParentEntity.class, p2_id, 3);
+ ParentEntity rev4 = getAuditReader().find(ParentEntity.class, p2_id, 4);
+ ParentEntity rev5 = getAuditReader().find(ParentEntity.class, p2_id, 5);
+
+ assert TestTools.checkList(rev1.getChildren1());
+ assert TestTools.checkList(rev2.getChildren1());
+ assert TestTools.checkList(rev3.getChildren1(), c1_1);
+ assert TestTools.checkList(rev4.getChildren1(), c1_1);
+ assert TestTools.checkList(rev5.getChildren1(), c1_1);
+
+ assert TestTools.checkList(rev1.getChildren2());
+ assert TestTools.checkList(rev2.getChildren2(), c2_1);
+ assert TestTools.checkList(rev3.getChildren2(), c2_1);
+ assert TestTools.checkList(rev4.getChildren2(), c2_1, c2_2);
+ assert TestTools.checkList(rev5.getChildren2(), c2_1);
+ }
+
+ @Test(enabled = true)
+ public void testHistoryOfChild1_1() {
+ ParentEntity p1 = getEntityManager().find(ParentEntity.class, p1_id);
+ ParentEntity p2 = getEntityManager().find(ParentEntity.class, p2_id);
+
+ Child1Entity rev1 = getAuditReader().find(Child1Entity.class, c1_1_id,
+ 1);
+ Child1Entity rev2 = getAuditReader().find(Child1Entity.class, c1_1_id,
+ 2);
+ Child1Entity rev3 = getAuditReader().find(Child1Entity.class, c1_1_id,
+ 3);
+ Child1Entity rev4 = getAuditReader().find(Child1Entity.class, c1_1_id,
+ 4);
+ Child1Entity rev5 = getAuditReader().find(Child1Entity.class, c1_1_id,
+ 5);
+
+ assert TestTools.checkList(rev1.getParents());
+ assert TestTools.checkList(rev2.getParents(), p1);
+ assert TestTools.checkList(rev3.getParents(), p1, p2);
+ assert TestTools.checkList(rev4.getParents(), p2);
+ assert TestTools.checkList(rev5.getParents(), p2);
+ }
+
+ @Test(enabled = false)
+ public void testHistoryOfChild1_2() {
+ ParentEntity p1 = getEntityManager().find(ParentEntity.class, p1_id);
+
+ Child1Entity rev1 = getAuditReader().find(Child1Entity.class, c1_2_id,
+ 1);
+ Child1Entity rev2 = getAuditReader().find(Child1Entity.class, c1_2_id,
+ 2);
+ Child1Entity rev3 = getAuditReader().find(Child1Entity.class, c1_2_id,
+ 3);
+ Child1Entity rev4 = getAuditReader().find(Child1Entity.class, c1_2_id,
+ 4);
+ Child1Entity rev5 = getAuditReader().find(Child1Entity.class, c1_2_id,
+ 5);
+
+ assert TestTools.checkList(rev1.getParents());
+ assert TestTools.checkList(rev2.getParents());
+ assert TestTools.checkList(rev3.getParents(), p1);
+ assert TestTools.checkList(rev4.getParents(), p1);
+ assert TestTools.checkList(rev5.getParents());
+ }
+
+ @Test(enabled = true)
+ public void testHistoryOfChild2_1() {
+ ParentEntity p2 = getEntityManager().find(ParentEntity.class, p2_id);
+
+ Child2Entity rev1 = getAuditReader().find(Child2Entity.class, c2_1_id,
+ 1);
+ Child2Entity rev2 = getAuditReader().find(Child2Entity.class, c2_1_id,
+ 2);
+ Child2Entity rev3 = getAuditReader().find(Child2Entity.class, c2_1_id,
+ 3);
+ Child2Entity rev4 = getAuditReader().find(Child2Entity.class, c2_1_id,
+ 4);
+ Child2Entity rev5 = getAuditReader().find(Child2Entity.class, c2_1_id,
+ 5);
+
+ assert TestTools.checkList(rev1.getParents());
+ assert TestTools.checkList(rev2.getParents(), p2);
+ assert TestTools.checkList(rev3.getParents(), p2);
+ assert TestTools.checkList(rev4.getParents(), p2);
+ assert TestTools.checkList(rev5.getParents(), p2);
+ }
+
+ @Test(enabled = true)
+ public void testHistoryOfChild2_2() {
+ ParentEntity p1 = getEntityManager().find(ParentEntity.class, p1_id);
+ ParentEntity p2 = getEntityManager().find(ParentEntity.class, p2_id);
+
+ Child2Entity rev1 = getAuditReader().find(Child2Entity.class, c2_2_id,
+ 1);
+ Child2Entity rev2 = getAuditReader().find(Child2Entity.class, c2_2_id,
+ 2);
+ Child2Entity rev3 = getAuditReader().find(Child2Entity.class, c2_2_id,
+ 3);
+ Child2Entity rev4 = getAuditReader().find(Child2Entity.class, c2_2_id,
+ 4);
+ Child2Entity rev5 = getAuditReader().find(Child2Entity.class, c2_2_id,
+ 5);
+
+ assert TestTools.checkList(rev1.getParents());
+ assert TestTools.checkList(rev2.getParents());
+ assert TestTools.checkList(rev3.getParents(), p1);
+ assert TestTools.checkList(rev4.getParents(), p1, p2);
+ assert TestTools.checkList(rev5.getParents(), p1);
+ }
+
+ private List<Map<String, Object>> getRevisions(
+ Class<?> originalEntityClazz, Integer originalEntityId) {
+ // Build the query:
+ // select auditEntity from
+ // org.hibernate.envers.test.entities.manytomany.sametable.ParentEntity_AUD
+ // auditEntity where auditEntity.originalId.id = :originalEntityId
+
+ StringBuilder builder = new StringBuilder("select auditEntity from ");
+ builder.append(originalEntityClazz.getName())
+ .append("_AUD auditEntity");
+ builder.append(" where auditEntity.originalId.id = :originalEntityId");
+
+ Query qry = getEntityManager().createQuery(builder.toString());
+ qry.setParameter("originalEntityId", originalEntityId);
+
+ @SuppressWarnings("unchecked")
+ List<Map<String, Object>> resultList = qry.getResultList();
+ return resultList;
+ }
+
+ private void verifyRevEndTimeStamps(String debugInfo,
+ List<Map<String, Object>> revisionEntities) {
+ for (Map<String, Object> revisionEntity : revisionEntities) {
+
+ Date revendTimestamp = (Date) revisionEntity
+ .get(revendTimestampColumName);
+ DefaultRevisionEntity revEnd = (DefaultRevisionEntity) revisionEntity
+ .get("REVEND");
+
+ if (revendTimestamp == null) {
+ assert revEnd == null;
+ } else {
+ assert revendTimestamp.getTime() == revEnd.getTimestamp();
+ }
+ }
+ }
+
+}
Modified: core/trunk/envers/src/test/resources/testng.xml
===================================================================
--- core/trunk/envers/src/test/resources/testng.xml 2010-09-28 16:39:06 UTC (rev 20742)
+++ core/trunk/envers/src/test/resources/testng.xml 2010-09-28 22:23:04 UTC (rev 20743)
@@ -68,6 +68,7 @@
<package name="org.hibernate.envers.test.integration.secondary" />
<package name="org.hibernate.envers.test.integration.secondary.ids" />
<package name="org.hibernate.envers.test.integration.serialization" />
+ <package name="org.hibernate.envers.test.integration.strategy" />
<package name="org.hibernate.envers.test.integration.superclass" />
<package name="org.hibernate.envers.test.integration.entityNames.auditedEntity" />
<package name="org.hibernate.envers.test.integration.entityNames.manyToManyAudited" />
13 years, 7 months
Hibernate SVN: r20742 - core/trunk/documentation/manual/src/main/docbook/en-US/content.
by hibernate-commits@lists.jboss.org
Author: hardy.ferentschik
Date: 2010-09-28 12:39:06 -0400 (Tue, 28 Sep 2010)
New Revision: 20742
Modified:
core/trunk/documentation/manual/src/main/docbook/en-US/content/basic_mapping.xml
Log:
HHH-5205 Updated documentation about @Source
Modified: core/trunk/documentation/manual/src/main/docbook/en-US/content/basic_mapping.xml
===================================================================
--- core/trunk/documentation/manual/src/main/docbook/en-US/content/basic_mapping.xml 2010-09-28 16:32:26 UTC (rev 20741)
+++ core/trunk/documentation/manual/src/main/docbook/en-US/content/basic_mapping.xml 2010-09-28 16:39:06 UTC (rev 20742)
@@ -2203,8 +2203,8 @@
<title>Timestamp</title>
<para>Alternatively, you can use a timestamp. Timestamps are a less
- safe implementation of optimistic locking. However, sometimes the
- application might use the timestamps in other ways.</para>
+ safe implementation of optimistic locking. However, sometimes an
+ application might use the timestamps in other ways as well.</para>
<para>Simply mark a property of type <classname>Date</classname> or
<classname>Calendar</classname> as
@@ -2217,8 +2217,19 @@
public Date getLastUpdate() { ... }
} </programlisting>
- <para>Like version numbers, the timestamp can be generated by the
- database instead of Hibernate. To do that, use
+ <para>When using timestamp versioning you can tell Hibernate where to
+ retrieve the timestamp value from - database or JVM - by optionally
+ adding the <classname>@org.hibernate.annotations.Source</classname>
+ annotation to the property. Possible values for the value attribute of
+ the annotation are
+ <classname>org.hibernate.annotations.SourceType.VM</classname> and
+ <classname>org.hibernate.annotations.SourceType.DB</classname>. The
+ default is <classname>SourceType.DB</classname> which is also used in
+ case there is no <classname>@Source</classname> annotation at all.
+ </para>
+
+ <para>Like in the case of version numbers, the timestamp can also be
+ generated by the database instead of Hibernate. To do that, use
<code>@org.hibernate.annotations.Generated(GenerationTime.ALWAYS).</code></para>
<para>In hbm.xml, use the <literal><timestamp></literal>
13 years, 7 months
Hibernate SVN: r20741 - in core/trunk: core/src/main/java/org/hibernate/cfg/annotations and 1 other directories.
by hibernate-commits@lists.jboss.org
Author: hardy.ferentschik
Date: 2010-09-28 12:32:26 -0400 (Tue, 28 Sep 2010)
New Revision: 20741
Added:
core/trunk/testsuite/src/test/java/org/hibernate/test/annotations/various/OptimisticLockAnnotationTest.java
Removed:
core/trunk/testsuite/src/test/java/org/hibernate/test/annotations/various/VersionTest.java
Modified:
core/trunk/core/src/main/java/org/hibernate/cfg/BinderHelper.java
core/trunk/core/src/main/java/org/hibernate/cfg/CopyIdentifierComponentSecondPass.java
core/trunk/core/src/main/java/org/hibernate/cfg/Ejb3DiscriminatorColumn.java
core/trunk/core/src/main/java/org/hibernate/cfg/Ejb3JoinColumn.java
core/trunk/core/src/main/java/org/hibernate/cfg/IndexColumn.java
core/trunk/core/src/main/java/org/hibernate/cfg/OneToOneSecondPass.java
core/trunk/core/src/main/java/org/hibernate/cfg/SetSimpleValueTypeSecondPass.java
core/trunk/core/src/main/java/org/hibernate/cfg/annotations/CollectionBinder.java
core/trunk/core/src/main/java/org/hibernate/cfg/annotations/EntityBinder.java
core/trunk/core/src/main/java/org/hibernate/cfg/annotations/IdBagBinder.java
core/trunk/core/src/main/java/org/hibernate/cfg/annotations/MapBinder.java
core/trunk/core/src/main/java/org/hibernate/cfg/annotations/QueryBinder.java
core/trunk/core/src/main/java/org/hibernate/cfg/annotations/ResultsetMappingSecondPass.java
core/trunk/core/src/main/java/org/hibernate/cfg/annotations/TableBinder.java
Log:
HHH-5205 - Renamed BinderHelper.isDefault() to BinderHelper.isEmptyAnnotationValue() , because this describes better what the function does. Also renamed VersionTest to OptimisitcLockAnnotationTest to better describe what gets tested.
Modified: core/trunk/core/src/main/java/org/hibernate/cfg/BinderHelper.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/cfg/BinderHelper.java 2010-09-28 16:28:30 UTC (rev 20740)
+++ core/trunk/core/src/main/java/org/hibernate/cfg/BinderHelper.java 2010-09-28 16:32:26 UTC (rev 20741)
@@ -499,7 +499,7 @@
// YUCK! but cannot think of a clean way to do this given the string-config based scheme
params.put( PersistentIdentifierGenerator.IDENTIFIER_NORMALIZER, mappings.getObjectNameNormalizer() );
- if ( !isDefault( generatorName ) ) {
+ if ( !isEmptyAnnotationValue( generatorName ) ) {
//we have a named generator
IdGenerator gen = mappings.getGenerator( generatorName, localGenerators );
if ( gen == null ) {
@@ -526,7 +526,7 @@
id.setIdentifierGeneratorProperties( params );
}
- public static boolean isDefault(String annotationString) {
+ public static boolean isEmptyAnnotationValue(String annotationString) {
return annotationString != null && annotationString.length() == 0;
//equivalent to (but faster) ANNOTATION_STRING_DEFAULT.equals( annotationString );
}
@@ -628,7 +628,7 @@
}
private static void checkAnyMetaDefValidity(boolean mustHaveName, AnyMetaDef defAnn, XAnnotatedElement annotatedElement) {
- if ( mustHaveName && isDefault( defAnn.name() ) ) {
+ if ( mustHaveName && isEmptyAnnotationValue( defAnn.name() ) ) {
String name = XClass.class.isAssignableFrom( annotatedElement.getClass() ) ?
( (XClass) annotatedElement ).getName() :
( (XPackage) annotatedElement ).getName();
@@ -637,7 +637,7 @@
}
private static void bindAnyMetaDef(AnyMetaDef defAnn, Mappings mappings) {
- if ( isDefault( defAnn.name() ) ) return; //don't map not named definitions
+ if ( isEmptyAnnotationValue( defAnn.name() ) ) return; //don't map not named definitions
log.info( "Binding Any Meta definition: {}", defAnn.name() );
mappings.addAnyMetaDef( defAnn );
}
Property changes on: core/trunk/core/src/main/java/org/hibernate/cfg/BinderHelper.java
___________________________________________________________________
Name: svn:keywords
- Date Revision Author Id
+ Id
Modified: core/trunk/core/src/main/java/org/hibernate/cfg/CopyIdentifierComponentSecondPass.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/cfg/CopyIdentifierComponentSecondPass.java 2010-09-28 16:28:30 UTC (rev 20740)
+++ core/trunk/core/src/main/java/org/hibernate/cfg/CopyIdentifierComponentSecondPass.java 2010-09-28 16:32:26 UTC (rev 20741)
@@ -78,7 +78,7 @@
Map<String, Ejb3JoinColumn> columnByReferencedName = new HashMap<String, Ejb3JoinColumn>(joinColumns.length);
for (Ejb3JoinColumn joinColumn : joinColumns) {
final String referencedColumnName = joinColumn.getReferencedColumn();
- if ( referencedColumnName == null || BinderHelper.isDefault( referencedColumnName ) ) {
+ if ( referencedColumnName == null || BinderHelper.isEmptyAnnotationValue( referencedColumnName ) ) {
break;
}
//JPA 2 requires referencedColumnNames to be case insensitive
Property changes on: core/trunk/core/src/main/java/org/hibernate/cfg/CopyIdentifierComponentSecondPass.java
___________________________________________________________________
Name: svn:keywords
+ Id
Modified: core/trunk/core/src/main/java/org/hibernate/cfg/Ejb3DiscriminatorColumn.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/cfg/Ejb3DiscriminatorColumn.java 2010-09-28 16:28:30 UTC (rev 20740)
+++ core/trunk/core/src/main/java/org/hibernate/cfg/Ejb3DiscriminatorColumn.java 2010-09-28 16:32:26 UTC (rev 20741)
@@ -71,12 +71,12 @@
}
else if ( discAnn != null ) {
discriminatorColumn.setImplicit( false );
- if ( !BinderHelper.isDefault( discAnn.columnDefinition() ) ) {
+ if ( !BinderHelper.isEmptyAnnotationValue( discAnn.columnDefinition() ) ) {
discriminatorColumn.setSqlType(
discAnn.columnDefinition()
);
}
- if ( !BinderHelper.isDefault( discAnn.name() ) ) {
+ if ( !BinderHelper.isEmptyAnnotationValue( discAnn.name() ) ) {
discriminatorColumn.setLogicalColumnName( discAnn.name() );
}
discriminatorColumn.setNullable( false );
Property changes on: core/trunk/core/src/main/java/org/hibernate/cfg/Ejb3DiscriminatorColumn.java
___________________________________________________________________
Name: svn:keywords
- Date Revision Author Id
+ Id
Modified: core/trunk/core/src/main/java/org/hibernate/cfg/Ejb3JoinColumn.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/cfg/Ejb3JoinColumn.java 2010-09-28 16:28:30 UTC (rev 20740)
+++ core/trunk/core/src/main/java/org/hibernate/cfg/Ejb3JoinColumn.java 2010-09-28 16:32:26 UTC (rev 20741)
@@ -249,7 +249,7 @@
String suffixForDefaultColumnName,
Mappings mappings) {
if ( ann != null ) {
- if ( BinderHelper.isDefault( mappedBy ) ) {
+ if ( BinderHelper.isEmptyAnnotationValue( mappedBy ) ) {
throw new AnnotationException(
"Illegal attempt to define a @JoinColumn with a mappedBy association: "
+ BinderHelper.getRelativePath( propertyHolder, propertyName )
@@ -299,8 +299,8 @@
}
else {
setImplicit( false );
- if ( !BinderHelper.isDefault( annJoin.columnDefinition() ) ) setSqlType( annJoin.columnDefinition() );
- if ( !BinderHelper.isDefault( annJoin.name() ) ) setLogicalColumnName( annJoin.name() );
+ if ( !BinderHelper.isEmptyAnnotationValue( annJoin.columnDefinition() ) ) setSqlType( annJoin.columnDefinition() );
+ if ( !BinderHelper.isEmptyAnnotationValue( annJoin.name() ) ) setLogicalColumnName( annJoin.name() );
setNullable( annJoin.nullable() );
setUnique( annJoin.unique() );
setInsertable( annJoin.insertable() );
Property changes on: core/trunk/core/src/main/java/org/hibernate/cfg/Ejb3JoinColumn.java
___________________________________________________________________
Name: svn:keywords
- Date Revision Author Id
+ Id
Modified: core/trunk/core/src/main/java/org/hibernate/cfg/IndexColumn.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/cfg/IndexColumn.java 2010-09-28 16:28:30 UTC (rev 20740)
+++ core/trunk/core/src/main/java/org/hibernate/cfg/IndexColumn.java 2010-09-28 16:32:26 UTC (rev 20741)
@@ -88,8 +88,8 @@
Mappings mappings) {
IndexColumn column;
if ( ann != null ) {
- String sqlType = BinderHelper.isDefault( ann.columnDefinition() ) ? null : ann.columnDefinition();
- String name = BinderHelper.isDefault( ann.name() ) ? inferredData.getPropertyName() + "_ORDER" : ann.name();
+ String sqlType = BinderHelper.isEmptyAnnotationValue( ann.columnDefinition() ) ? null : ann.columnDefinition();
+ String name = BinderHelper.isEmptyAnnotationValue( ann.name() ) ? inferredData.getPropertyName() + "_ORDER" : ann.name();
//TODO move it to a getter based system and remove the constructor
// The JPA OrderColumn annotation defines no table element...
// column = new IndexColumn(
@@ -120,8 +120,8 @@
Mappings mappings) {
IndexColumn column;
if ( ann != null ) {
- String sqlType = BinderHelper.isDefault( ann.columnDefinition() ) ? null : ann.columnDefinition();
- String name = BinderHelper.isDefault( ann.name() ) ? inferredData.getPropertyName() : ann.name();
+ String sqlType = BinderHelper.isEmptyAnnotationValue( ann.columnDefinition() ) ? null : ann.columnDefinition();
+ String name = BinderHelper.isEmptyAnnotationValue( ann.name() ) ? inferredData.getPropertyName() : ann.name();
//TODO move it to a getter based system and remove the constructor
column = new IndexColumn(
false, sqlType, 0, 0, 0, name, ann.nullable(),
Property changes on: core/trunk/core/src/main/java/org/hibernate/cfg/IndexColumn.java
___________________________________________________________________
Name: svn:keywords
- Date Revision Author Id
+ Id
Modified: core/trunk/core/src/main/java/org/hibernate/cfg/OneToOneSecondPass.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/cfg/OneToOneSecondPass.java 2010-09-28 16:28:30 UTC (rev 20740)
+++ core/trunk/core/src/main/java/org/hibernate/cfg/OneToOneSecondPass.java 2010-09-28 16:32:26 UTC (rev 20741)
@@ -114,7 +114,7 @@
binder.setCascade( cascadeStrategy );
binder.setAccessType( inferredData.getDefaultAccess() );
Property prop = binder.makeProperty();
- if ( BinderHelper.isDefault( mappedBy ) ) {
+ if ( BinderHelper.isEmptyAnnotationValue( mappedBy ) ) {
/*
* we need to check if the columns are in the right order
* if not, then we need to create a many to one and formula
@@ -236,7 +236,7 @@
}
ForeignKey fk = inferredData.getProperty().getAnnotation( ForeignKey.class );
String fkName = fk != null ? fk.name() : "";
- if ( !BinderHelper.isDefault( fkName ) ) value.setForeignKeyName( fkName );
+ if ( !BinderHelper.isEmptyAnnotationValue( fkName ) ) value.setForeignKeyName( fkName );
}
/**
Property changes on: core/trunk/core/src/main/java/org/hibernate/cfg/OneToOneSecondPass.java
___________________________________________________________________
Name: svn:keywords
- Date Revision Author Id
+ Id
Modified: core/trunk/core/src/main/java/org/hibernate/cfg/SetSimpleValueTypeSecondPass.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/cfg/SetSimpleValueTypeSecondPass.java 2010-09-28 16:28:30 UTC (rev 20740)
+++ core/trunk/core/src/main/java/org/hibernate/cfg/SetSimpleValueTypeSecondPass.java 2010-09-28 16:32:26 UTC (rev 20741)
@@ -24,12 +24,12 @@
package org.hibernate.cfg;
import java.util.Map;
+
import org.hibernate.MappingException;
import org.hibernate.cfg.annotations.SimpleValueBinder;
/**
* @author Sharath Reddy
- *
*/
public class SetSimpleValueTypeSecondPass implements SecondPass {
@@ -38,9 +38,8 @@
public SetSimpleValueTypeSecondPass(SimpleValueBinder val) {
binder = val;
}
-
+
public void doSecondPass(Map persistentClasses) throws MappingException {
binder.fillSimpleValue();
}
-
}
Property changes on: core/trunk/core/src/main/java/org/hibernate/cfg/SetSimpleValueTypeSecondPass.java
___________________________________________________________________
Name: svn:keywords
+ Id
Modified: core/trunk/core/src/main/java/org/hibernate/cfg/annotations/CollectionBinder.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/cfg/annotations/CollectionBinder.java 2010-09-28 16:28:30 UTC (rev 20740)
+++ core/trunk/core/src/main/java/org/hibernate/cfg/annotations/CollectionBinder.java 2010-09-28 16:32:26 UTC (rev 20741)
@@ -224,7 +224,7 @@
public void setSqlOrderBy(OrderBy orderByAnn) {
if ( orderByAnn != null ) {
- if ( !BinderHelper.isDefault( orderByAnn.clause() ) ) {
+ if ( !BinderHelper.isEmptyAnnotationValue( orderByAnn.clause() ) ) {
orderBy = orderByAnn.clause();
}
}
@@ -471,7 +471,7 @@
}
//work on association
- boolean isMappedBy = !BinderHelper.isDefault( mappedBy );
+ boolean isMappedBy = !BinderHelper.isEmptyAnnotationValue( mappedBy );
if (isMappedBy
&& (property.isAnnotationPresent( JoinColumn.class )
@@ -672,7 +672,7 @@
&& !reversePropertyInJoin
&& oneToMany
&& !this.isExplicitAssociationTable
- && ( joinColumns[0].isImplicit() && !BinderHelper.isDefault( this.mappedBy ) //implicit @JoinColumn
+ && ( joinColumns[0].isImplicit() && !BinderHelper.isEmptyAnnotationValue( this.mappedBy ) //implicit @JoinColumn
|| !fkJoinColumns[0].isImplicit() ) //this is an explicit @JoinColumn
) {
//this is a Foreign key
@@ -865,7 +865,7 @@
}
private String getCondition(String cond, String name) {
- if ( BinderHelper.isDefault( cond ) ) {
+ if ( BinderHelper.isEmptyAnnotationValue( cond ) ) {
cond = mappings.getFilterDefinition( name ).getDefaultFilterCondition();
if ( StringHelper.isEmpty( cond ) ) {
throw new AnnotationException(
@@ -879,7 +879,7 @@
public void setCache(Cache cacheAnn) {
if ( cacheAnn != null ) {
- cacheRegionName = BinderHelper.isDefault( cacheAnn.region() ) ? null : cacheAnn.region();
+ cacheRegionName = BinderHelper.isEmptyAnnotationValue( cacheAnn.region() ) ? null : cacheAnn.region();
cacheConcurrencyStrategy = EntityBinder.getCacheConcurrencyStrategy( cacheAnn.usage() );
}
else {
@@ -1123,7 +1123,7 @@
collValue.setKey( key );
ForeignKey fk = property != null ? property.getAnnotation( ForeignKey.class ) : null;
String fkName = fk != null ? fk.name() : "";
- if ( !BinderHelper.isDefault( fkName ) ) key.setForeignKeyName( fkName );
+ if ( !BinderHelper.isEmptyAnnotationValue( fkName ) ) key.setForeignKeyName( fkName );
return key;
}
@@ -1188,7 +1188,7 @@
}
}
- boolean mappedBy = !BinderHelper.isDefault( joinColumns[0].getMappedBy() );
+ boolean mappedBy = !BinderHelper.isEmptyAnnotationValue( joinColumns[0].getMappedBy() );
if ( mappedBy ) {
if ( !isCollectionOfEntities ) {
StringBuilder error = new StringBuilder( 80 )
@@ -1281,7 +1281,7 @@
}
ForeignKey fk = property != null ? property.getAnnotation( ForeignKey.class ) : null;
String fkName = fk != null ? fk.inverseName() : "";
- if ( !BinderHelper.isDefault( fkName ) ) element.setForeignKeyName( fkName );
+ if ( !BinderHelper.isEmptyAnnotationValue( fkName ) ) element.setForeignKeyName( fkName );
}
else if ( anyAnn != null ) {
//@ManyToAny
Property changes on: core/trunk/core/src/main/java/org/hibernate/cfg/annotations/CollectionBinder.java
___________________________________________________________________
Name: svn:keywords
- Date Revision Author Id
+ Id
Modified: core/trunk/core/src/main/java/org/hibernate/cfg/annotations/EntityBinder.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/cfg/annotations/EntityBinder.java 2010-09-28 16:28:30 UTC (rev 20740)
+++ core/trunk/core/src/main/java/org/hibernate/cfg/annotations/EntityBinder.java 2010-09-28 16:32:26 UTC (rev 20741)
@@ -170,7 +170,7 @@
private void bindEjb3Annotation(Entity ejb3Ann) {
if ( ejb3Ann == null ) throw new AssertionFailure( "@Entity should always be not null" );
- if ( BinderHelper.isDefault( ejb3Ann.name() ) ) {
+ if ( BinderHelper.isEmptyAnnotationValue( ejb3Ann.name() ) ) {
name = StringHelper.unqualify( annotatedClass.getName() );
}
else {
@@ -243,7 +243,7 @@
}
else {
org.hibernate.annotations.Entity entityAnn = annotatedClass.getAnnotation( org.hibernate.annotations.Entity.class );
- if ( entityAnn != null && !BinderHelper.isDefault( entityAnn.persister() ) ) {
+ if ( entityAnn != null && !BinderHelper.isEmptyAnnotationValue( entityAnn.persister() ) ) {
try {
persister = ReflectHelper.classForName( entityAnn.persister() );
}
@@ -319,7 +319,7 @@
for ( Map.Entry<String, String> filter : filters.entrySet() ) {
String filterName = filter.getKey();
String cond = filter.getValue();
- if ( BinderHelper.isDefault( cond ) ) {
+ if ( BinderHelper.isEmptyAnnotationValue( cond ) ) {
FilterDefinition definition = mappings.getFilterDefinition( filterName );
cond = definition == null ? null : definition.getDefaultFilterCondition();
if ( StringHelper.isEmpty( cond ) ) {
@@ -606,7 +606,7 @@
private void setFKNameIfDefined(Join join) {
org.hibernate.annotations.Table matchingTable = findMatchingComplimentTableAnnotation( join );
- if ( matchingTable != null && !BinderHelper.isDefault( matchingTable.foreignKey().name() ) ) {
+ if ( matchingTable != null && !BinderHelper.isEmptyAnnotationValue( matchingTable.foreignKey().name() ) ) {
( (SimpleValue) join.getKey() ).setForeignKeyName( matchingTable.foreignKey().name() );
}
}
@@ -740,19 +740,19 @@
join.setSequentialSelect( FetchMode.JOIN != matchingTable.fetch() );
join.setInverse( matchingTable.inverse() );
join.setOptional( matchingTable.optional() );
- if ( !BinderHelper.isDefault( matchingTable.sqlInsert().sql() ) ) {
+ if ( !BinderHelper.isEmptyAnnotationValue( matchingTable.sqlInsert().sql() ) ) {
join.setCustomSQLInsert( matchingTable.sqlInsert().sql().trim(),
matchingTable.sqlInsert().callable(),
ExecuteUpdateResultCheckStyle.parse( matchingTable.sqlInsert().check().toString().toLowerCase() )
);
}
- if ( !BinderHelper.isDefault( matchingTable.sqlUpdate().sql() ) ) {
+ if ( !BinderHelper.isEmptyAnnotationValue( matchingTable.sqlUpdate().sql() ) ) {
join.setCustomSQLUpdate( matchingTable.sqlUpdate().sql().trim(),
matchingTable.sqlUpdate().callable(),
ExecuteUpdateResultCheckStyle.parse( matchingTable.sqlUpdate().check().toString().toLowerCase() )
);
}
- if ( !BinderHelper.isDefault( matchingTable.sqlDelete().sql() ) ) {
+ if ( !BinderHelper.isEmptyAnnotationValue( matchingTable.sqlDelete().sql() ) ) {
join.setCustomSQLDelete( matchingTable.sqlDelete().sql().trim(),
matchingTable.sqlDelete().callable(),
ExecuteUpdateResultCheckStyle.parse( matchingTable.sqlDelete().check().toString().toLowerCase() )
@@ -782,7 +782,7 @@
public void setCache(Cache cacheAnn) {
if ( cacheAnn != null ) {
- cacheRegion = BinderHelper.isDefault( cacheAnn.region() ) ?
+ cacheRegion = BinderHelper.isEmptyAnnotationValue( cacheAnn.region() ) ?
null :
cacheAnn.region();
cacheConcurrentStrategy = getCacheConcurrencyStrategy( cacheAnn.usage() );
@@ -853,7 +853,7 @@
"@org.hibernate.annotations.Table references an unknown table: " + appliedTable
);
}
- if ( !BinderHelper.isDefault( table.comment() ) ) hibTable.setComment( table.comment() );
+ if ( !BinderHelper.isEmptyAnnotationValue( table.comment() ) ) hibTable.setComment( table.comment() );
TableBinder.addIndexes( hibTable, table.indexes(), mappings );
}
Modified: core/trunk/core/src/main/java/org/hibernate/cfg/annotations/IdBagBinder.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/cfg/annotations/IdBagBinder.java 2010-09-28 16:28:30 UTC (rev 20740)
+++ core/trunk/core/src/main/java/org/hibernate/cfg/annotations/IdBagBinder.java 2010-09-28 16:32:26 UTC (rev 20741)
@@ -101,7 +101,7 @@
simpleValue.setTable( table );
simpleValue.setColumns( idColumns );
Type typeAnn = collectionIdAnn.type();
- if ( typeAnn != null && !BinderHelper.isDefault( typeAnn.type() ) ) {
+ if ( typeAnn != null && !BinderHelper.isEmptyAnnotationValue( typeAnn.type() ) ) {
simpleValue.setExplicitType( typeAnn );
}
else {
Modified: core/trunk/core/src/main/java/org/hibernate/cfg/annotations/MapBinder.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/cfg/annotations/MapBinder.java 2010-09-28 16:28:30 UTC (rev 20740)
+++ core/trunk/core/src/main/java/org/hibernate/cfg/annotations/MapBinder.java 2010-09-28 16:32:26 UTC (rev 20741)
@@ -285,12 +285,12 @@
//the algorithm generally does not apply for map key anyway
MapKey mapKeyAnn = property.getAnnotation( org.hibernate.annotations.MapKey.class );
elementBinder.setKey(true);
- if (mapKeyAnn != null && ! BinderHelper.isDefault( mapKeyAnn.type().type() ) ) {
+ if (mapKeyAnn != null && ! BinderHelper.isEmptyAnnotationValue( mapKeyAnn.type().type() ) ) {
elementBinder.setExplicitType( mapKeyAnn.type() );
}
else {
MapKeyType mapKeyTypeAnnotation = property.getAnnotation( MapKeyType.class );
- if ( mapKeyTypeAnnotation != null && ! BinderHelper.isDefault( mapKeyTypeAnnotation.value().type() ) ) {
+ if ( mapKeyTypeAnnotation != null && ! BinderHelper.isEmptyAnnotationValue( mapKeyTypeAnnotation.value().type() ) ) {
elementBinder.setExplicitType( mapKeyTypeAnnotation.value() );
}
else {
Property changes on: core/trunk/core/src/main/java/org/hibernate/cfg/annotations/MapBinder.java
___________________________________________________________________
Name: svn:keywords
- Date Revision Author Id
+ Id
Modified: core/trunk/core/src/main/java/org/hibernate/cfg/annotations/QueryBinder.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/cfg/annotations/QueryBinder.java 2010-09-28 16:28:30 UTC (rev 20740)
+++ core/trunk/core/src/main/java/org/hibernate/cfg/annotations/QueryBinder.java 2010-09-28 16:32:26 UTC (rev 20741)
@@ -59,7 +59,7 @@
public static void bindQuery(NamedQuery queryAnn, Mappings mappings, boolean isDefault) {
if ( queryAnn == null ) return;
- if ( BinderHelper.isDefault( queryAnn.name() ) ) {
+ if ( BinderHelper.isEmptyAnnotationValue( queryAnn.name() ) ) {
throw new AnnotationException( "A named query must have a name when used in class or package level" );
}
//EJBQL Query
@@ -90,14 +90,14 @@
public static void bindNativeQuery(NamedNativeQuery queryAnn, Mappings mappings, boolean isDefault) {
if ( queryAnn == null ) return;
//ResultSetMappingDefinition mappingDefinition = mappings.getResultSetMapping( queryAnn.resultSetMapping() );
- if ( BinderHelper.isDefault( queryAnn.name() ) ) {
+ if ( BinderHelper.isEmptyAnnotationValue( queryAnn.name() ) ) {
throw new AnnotationException( "A named query must have a name when used in class or package level" );
}
NamedSQLQueryDefinition query;
String resultSetMapping = queryAnn.resultSetMapping();
QueryHint[] hints = queryAnn.hints();
String queryName = queryAnn.query();
- if ( !BinderHelper.isDefault( resultSetMapping ) ) {
+ if ( !BinderHelper.isEmptyAnnotationValue( resultSetMapping ) ) {
//sql result set usage
query = new NamedSQLQueryDefinition(
queryName,
@@ -151,25 +151,25 @@
public static void bindNativeQuery(org.hibernate.annotations.NamedNativeQuery queryAnn, Mappings mappings) {
if ( queryAnn == null ) return;
//ResultSetMappingDefinition mappingDefinition = mappings.getResultSetMapping( queryAnn.resultSetMapping() );
- if ( BinderHelper.isDefault( queryAnn.name() ) ) {
+ if ( BinderHelper.isEmptyAnnotationValue( queryAnn.name() ) ) {
throw new AnnotationException( "A named query must have a name when used in class or package level" );
}
NamedSQLQueryDefinition query;
String resultSetMapping = queryAnn.resultSetMapping();
- if ( !BinderHelper.isDefault( resultSetMapping ) ) {
+ if ( !BinderHelper.isEmptyAnnotationValue( resultSetMapping ) ) {
//sql result set usage
query = new NamedSQLQueryDefinition(
queryAnn.query(),
resultSetMapping,
null,
queryAnn.cacheable(),
- BinderHelper.isDefault( queryAnn.cacheRegion() ) ? null : queryAnn.cacheRegion(),
+ BinderHelper.isEmptyAnnotationValue( queryAnn.cacheRegion() ) ? null : queryAnn.cacheRegion(),
queryAnn.timeout() < 0 ? null : queryAnn.timeout(),
queryAnn.fetchSize() < 0 ? null : queryAnn.fetchSize(),
getFlushMode( queryAnn.flushMode() ),
getCacheMode( queryAnn.cacheMode() ),
queryAnn.readOnly(),
- BinderHelper.isDefault( queryAnn.comment() ) ? null : queryAnn.comment(),
+ BinderHelper.isEmptyAnnotationValue( queryAnn.comment() ) ? null : queryAnn.comment(),
null,
queryAnn.callable()
);
@@ -184,13 +184,13 @@
new NativeSQLQueryReturn[] { entityQueryReturn },
null,
queryAnn.cacheable(),
- BinderHelper.isDefault( queryAnn.cacheRegion() ) ? null : queryAnn.cacheRegion(),
+ BinderHelper.isEmptyAnnotationValue( queryAnn.cacheRegion() ) ? null : queryAnn.cacheRegion(),
queryAnn.timeout() < 0 ? null : queryAnn.timeout(),
queryAnn.fetchSize() < 0 ? null : queryAnn.fetchSize(),
getFlushMode( queryAnn.flushMode() ),
getCacheMode( queryAnn.cacheMode() ),
queryAnn.readOnly(),
- BinderHelper.isDefault( queryAnn.comment() ) ? null : queryAnn.comment(),
+ BinderHelper.isEmptyAnnotationValue( queryAnn.comment() ) ? null : queryAnn.comment(),
null,
queryAnn.callable()
);
@@ -227,7 +227,7 @@
public static void bindQuery(org.hibernate.annotations.NamedQuery queryAnn, Mappings mappings) {
if ( queryAnn == null ) return;
- if ( BinderHelper.isDefault( queryAnn.name() ) ) {
+ if ( BinderHelper.isEmptyAnnotationValue( queryAnn.name() ) ) {
throw new AnnotationException( "A named query must have a name when used in class or package level" );
}
@@ -237,13 +237,13 @@
NamedQueryDefinition query = new NamedQueryDefinition(
queryAnn.query(),
queryAnn.cacheable(),
- BinderHelper.isDefault( queryAnn.cacheRegion() ) ? null : queryAnn.cacheRegion(),
+ BinderHelper.isEmptyAnnotationValue( queryAnn.cacheRegion() ) ? null : queryAnn.cacheRegion(),
queryAnn.timeout() < 0 ? null : queryAnn.timeout(),
queryAnn.fetchSize() < 0 ? null : queryAnn.fetchSize(),
flushMode,
getCacheMode( queryAnn.cacheMode() ),
queryAnn.readOnly(),
- BinderHelper.isDefault( queryAnn.comment() ) ? null : queryAnn.comment(),
+ BinderHelper.isEmptyAnnotationValue( queryAnn.comment() ) ? null : queryAnn.comment(),
null
);
Property changes on: core/trunk/core/src/main/java/org/hibernate/cfg/annotations/QueryBinder.java
___________________________________________________________________
Name: svn:keywords
- Date Revision Author Id
+ Id
Modified: core/trunk/core/src/main/java/org/hibernate/cfg/annotations/ResultsetMappingSecondPass.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/cfg/annotations/ResultsetMappingSecondPass.java 2010-09-28 16:28:30 UTC (rev 20740)
+++ core/trunk/core/src/main/java/org/hibernate/cfg/annotations/ResultsetMappingSecondPass.java 2010-09-28 16:32:26 UTC (rev 20741)
@@ -157,7 +157,7 @@
);
}
- if ( !BinderHelper.isDefault( entity.discriminatorColumn() ) ) {
+ if ( !BinderHelper.isEmptyAnnotationValue( entity.discriminatorColumn() ) ) {
final String quotingNormalizedName = mappings.getObjectNameNormalizer().normalizeIdentifierQuoting(
entity.discriminatorColumn()
);
Property changes on: core/trunk/core/src/main/java/org/hibernate/cfg/annotations/ResultsetMappingSecondPass.java
___________________________________________________________________
Name: svn:keywords
- Date Revision Author Id
+ Id
Modified: core/trunk/core/src/main/java/org/hibernate/cfg/annotations/TableBinder.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/cfg/annotations/TableBinder.java 2010-09-28 16:28:30 UTC (rev 20740)
+++ core/trunk/core/src/main/java/org/hibernate/cfg/annotations/TableBinder.java 2010-09-28 16:32:26 UTC (rev 20741)
@@ -213,8 +213,8 @@
Table denormalizedSuperTable,
Mappings mappings,
String subselect) {
- schema = BinderHelper.isDefault( schema ) ? mappings.getSchemaName() : schema;
- catalog = BinderHelper.isDefault( catalog ) ? mappings.getCatalogName() : catalog;
+ schema = BinderHelper.isEmptyAnnotationValue( schema ) ? mappings.getSchemaName() : schema;
+ catalog = BinderHelper.isEmptyAnnotationValue( catalog ) ? mappings.getCatalogName() : catalog;
String realTableName = mappings.getObjectNameNormalizer().normalizeDatabaseIdentifier(
nameSource.getExplicitName(),
@@ -282,8 +282,8 @@
String constraints,
Table denormalizedSuperTable,
Mappings mappings) {
- schema = BinderHelper.isDefault( schema ) ? mappings.getSchemaName() : schema;
- catalog = BinderHelper.isDefault( catalog ) ? mappings.getCatalogName() : catalog;
+ schema = BinderHelper.isEmptyAnnotationValue( schema ) ? mappings.getSchemaName() : schema;
+ catalog = BinderHelper.isEmptyAnnotationValue( catalog ) ? mappings.getCatalogName() : catalog;
Table table;
if ( denormalizedSuperTable != null ) {
table = mappings.addDenormalizedTable(
Property changes on: core/trunk/core/src/main/java/org/hibernate/cfg/annotations/TableBinder.java
___________________________________________________________________
Name: svn:keywords
- Date Revision Author Id
+ Id
Copied: core/trunk/testsuite/src/test/java/org/hibernate/test/annotations/various/OptimisticLockAnnotationTest.java (from rev 20735, core/trunk/testsuite/src/test/java/org/hibernate/test/annotations/various/VersionTest.java)
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/annotations/various/OptimisticLockAnnotationTest.java (rev 0)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/annotations/various/OptimisticLockAnnotationTest.java 2010-09-28 16:32:26 UTC (rev 20741)
@@ -0,0 +1,67 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+
+//$Id$
+package org.hibernate.test.annotations.various;
+
+import org.hibernate.Session;
+import org.hibernate.test.annotations.TestCase;
+
+/**
+ * Test for the @OptimisticLock annotation.
+ *
+ * @author Emmanuel Bernard
+ */
+public class OptimisticLockAnnotationTest extends TestCase {
+
+ public void testOptimisticLockExcludeOnNameProperty() throws Exception {
+ Conductor c = new Conductor();
+ c.setName( "Bob" );
+ Session s = openSession();
+ s.getTransaction().begin();
+ s.persist( c );
+ s.flush();
+
+ s.clear();
+
+ c = ( Conductor ) s.get( Conductor.class, c.getId() );
+ Long version = c.getVersion();
+ c.setName( "Don" );
+ s.flush();
+
+ s.clear();
+
+ c = ( Conductor ) s.get( Conductor.class, c.getId() );
+ assertEquals( version, c.getVersion() );
+
+ s.getTransaction().rollback();
+ s.close();
+ }
+
+ protected Class[] getAnnotatedClasses() {
+ return new Class[] {
+ Conductor.class
+ };
+ }
+}
Property changes on: core/trunk/testsuite/src/test/java/org/hibernate/test/annotations/various/OptimisticLockAnnotationTest.java
___________________________________________________________________
Name: svn:keywords
+ Id
Deleted: core/trunk/testsuite/src/test/java/org/hibernate/test/annotations/various/VersionTest.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/annotations/various/VersionTest.java 2010-09-28 16:28:30 UTC (rev 20740)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/annotations/various/VersionTest.java 2010-09-28 16:32:26 UTC (rev 20741)
@@ -1,41 +0,0 @@
-//$Id$
-package org.hibernate.test.annotations.various;
-
-import org.hibernate.Session;
-import org.hibernate.test.annotations.TestCase;
-
-/**
- * @author Emmanuel Bernard
- */
-public class VersionTest extends TestCase {
-
- public void testOptimisticLockDisabled() throws Exception {
- Conductor c = new Conductor();
- c.setName( "Bob" );
- Session s = openSession( );
- s.getTransaction().begin();
- s.persist( c );
- s.flush();
-
- s.clear();
-
- c = (Conductor) s.get( Conductor.class, c.getId() );
- Long version = c.getVersion();
- c.setName( "Don" );
- s.flush();
-
- s.clear();
-
- c = (Conductor) s.get( Conductor.class, c.getId() );
- assertEquals( version, c.getVersion() );
-
- s.getTransaction().rollback();
- s.close();
- }
-
- protected Class[] getAnnotatedClasses() {
- return new Class[] {
- Conductor.class
- };
- }
-}
13 years, 7 months