[hibernate-commits] Hibernate SVN: r20728 - in core/trunk: core/src/main/java/org/hibernate/cfg and 3 other directories.

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Mon Sep 27 18:07:45 EDT 2010


Author: epbernard
Date: 2010-09-27 18:07:44 -0400 (Mon, 27 Sep 2010)
New Revision: 20728

Added:
   core/trunk/core/src/main/java/org/hibernate/annotations/ReadExpression.java
   core/trunk/core/src/main/java/org/hibernate/annotations/ReadExpressions.java
   core/trunk/core/src/main/java/org/hibernate/annotations/WriteExpression.java
   core/trunk/core/src/main/java/org/hibernate/annotations/WriteExpressions.java
   core/trunk/testsuite/src/test/java/org/hibernate/test/annotations/various/readwriteexpression/
   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
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
Log:
HHH-4510 Add support for column-levle custom read/write expression

Added: core/trunk/core/src/main/java/org/hibernate/annotations/ReadExpression.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/annotations/ReadExpression.java	                        (rev 0)
+++ core/trunk/core/src/main/java/org/hibernate/annotations/ReadExpression.java	2010-09-27 22:07:44 UTC (rev 20728)
@@ -0,0 +1,51 @@
+/*
+ * 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 a column. True for direct object loading as well as queries.
+ *
+ * For example: <code>decrypt(credit_card_num)</code>
+ *  
+ * @author Emmanuel Bernard
+ */
+ at java.lang.annotation.Target({FIELD,METHOD})
+ at Retention(RUNTIME)
+public @interface ReadExpression {
+	/**
+	 * (Logical) column name for which the expression is used
+	 */
+	String forColumn();
+
+	/**
+	 * Custom SQL expression used to read from the column
+	 */
+	String expression();
+}

Added: core/trunk/core/src/main/java/org/hibernate/annotations/ReadExpressions.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/annotations/ReadExpressions.java	                        (rev 0)
+++ core/trunk/core/src/main/java/org/hibernate/annotations/ReadExpressions.java	2010-09-27 22:07:44 UTC (rev 20728)
@@ -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 @ReadExpression.
+ * Useful when more than one column is using this behavior.
+ *  
+ * @author Emmanuel Bernard
+ */
+ at java.lang.annotation.Target({FIELD,METHOD})
+ at Retention(RUNTIME)
+public @interface ReadExpressions {
+	ReadExpression[] value();
+}

Added: core/trunk/core/src/main/java/org/hibernate/annotations/WriteExpression.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/annotations/WriteExpression.java	                        (rev 0)
+++ core/trunk/core/src/main/java/org/hibernate/annotations/WriteExpression.java	2010-09-27 22:07:44 UTC (rev 20728)
@@ -0,0 +1,55 @@
+/*
+ * 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 write the value to a column. True for direct object saving as well as insert queries.
+ * The write expression must contain exactly one '?' placeholder for the value.
+ *
+ * For example: <code>encrypt(?)</code>
+ *
+ *
+ *
+ * @author Emmanuel Bernard
+ */
+ at java.lang.annotation.Target({FIELD,METHOD})
+ at Retention(RUNTIME)
+public @interface WriteExpression {
+	/**
+	 * (Logical) column name for which the expression is used
+	 */
+	String forColumn();
+
+	/**
+	 * Custom SQL expression used to write to the column.
+	 * The write expression must contain exactly one '?' placeholder for the value.
+	 */
+	String expression();
+}

Added: core/trunk/core/src/main/java/org/hibernate/annotations/WriteExpressions.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/annotations/WriteExpressions.java	                        (rev 0)
+++ core/trunk/core/src/main/java/org/hibernate/annotations/WriteExpressions.java	2010-09-27 22:07:44 UTC (rev 20728)
@@ -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 @WriteExpression.
+ * Useful when more than one column is using this behavior.
+ *  
+ * @author Emmanuel Bernard
+ */
+ at java.lang.annotation.Target({FIELD,METHOD})
+ at Retention(RUNTIME)
+public @interface WriteExpressions {
+	WriteExpression[] 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-27 17:33:29 UTC (rev 20727)
+++ core/trunk/core/src/main/java/org/hibernate/cfg/Ejb3Column.java	2010-09-27 22:07:44 UTC (rev 20728)
@@ -1,10 +1,10 @@
 /*
  * Hibernate, Relational Persistence for Idiomatic Java
  *
- * Copyright (c) 2010, Red Hat Inc. or third-party contributors as
+ * 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.
+ * 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
@@ -28,6 +28,11 @@
 import org.hibernate.AnnotationException;
 import org.hibernate.AssertionFailure;
 import org.hibernate.annotations.Index;
+import org.hibernate.annotations.ReadExpression;
+import org.hibernate.annotations.ReadExpressions;
+import org.hibernate.annotations.WriteExpression;
+import org.hibernate.annotations.WriteExpressions;
+import org.hibernate.annotations.common.reflection.XProperty;
 import org.hibernate.cfg.annotations.Nullability;
 import org.hibernate.mapping.Column;
 import org.hibernate.mapping.Formula;
@@ -66,6 +71,8 @@
 	private String formulaString;
 	private Formula formula;
 	private Table table;
+	private String readExpression;
+	private String writeExpression;
 
 	public void setTable(Table table) {
 		this.table = table;
@@ -213,6 +220,19 @@
 			this.mappingColumn.setNullable( nullable );
 			this.mappingColumn.setSqlType( sqlType );
 			this.mappingColumn.setUnique( unique );
+			
+			if(writeExpression != null && !writeExpression.matches("[^?]*\\?[^?]*")) {
+				throw new AnnotationException(
+						"@WriteExpression must contain exactly one value placeholder ('?') character: property ["
+								+ propertyName + "] and column [" + logicalColumnName + "]"
+				);
+			}
+			if ( readExpression != null) {
+				this.mappingColumn.setCustomRead( readExpression );
+			}
+			if ( writeExpression != null) {
+				this.mappingColumn.setCustomWrite( writeExpression );
+			}
 		}
 	}
 
@@ -451,6 +471,7 @@
 					column.setPropertyHolder( propertyHolder );
 					column.setJoins( secondaryTables );
 					column.setMappings( mappings );
+					column.extractDataFromPropertyData(inferredData);
 					column.bind();
 					columns[index] = column;
 				}
@@ -459,6 +480,45 @@
 		return columns;
 	}
 
+	//must only be called after all setters are defined and before bind
+	private void extractDataFromPropertyData(PropertyData inferredData) {
+		if ( inferredData != null ) {
+			XProperty property = inferredData.getProperty();
+			if ( property != null ) {
+				{
+					processReadExpression( property.getAnnotation( ReadExpression.class ) );
+					ReadExpressions annotations = property.getAnnotation( ReadExpressions.class );
+					if (annotations != null) {
+						for ( ReadExpression annotation : annotations.value() ) {
+							processReadExpression( annotation );
+						}
+					}
+				}
+				{
+					processWriteExpression( property.getAnnotation( WriteExpression.class ) );
+					WriteExpressions annotations = property.getAnnotation( WriteExpressions.class );
+					if (annotations != null) {
+						for ( WriteExpression annotation : annotations.value() ) {
+							processWriteExpression( annotation );
+						}
+					}
+				}
+			}
+		}
+	}
+
+	private void processReadExpression(ReadExpression annotation) {
+		if ( annotation != null && annotation.forColumn().equals( logicalColumnName ) ) {
+			readExpression = annotation.expression();
+		}
+	}
+
+	private void processWriteExpression(WriteExpression annotation) {
+		if ( annotation != null && annotation.forColumn().equals( logicalColumnName ) ) {
+			writeExpression = annotation.expression();
+		}
+	}
+
 	private static Ejb3Column[] buildImplicitColumn(
 			PropertyData inferredData,
 			String suffixForDefaultColumnName,
@@ -493,6 +553,7 @@
 		else {
 			column.setImplicit( true );
 		}
+		column.extractDataFromPropertyData( inferredData );
 		column.bind();
 		return columns;
 	}

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-27 17:33:29 UTC (rev 20727)
+++ core/trunk/documentation/manual/src/main/docbook/en-US/content/basic_mapping.xml	2010-09-27 22:07:44 UTC (rev 20728)
@@ -5066,9 +5066,9 @@
             <listitem>
               <para>a <literal>hibernate namespace</literal> is recognized
               whenever the resolver encounters a systemId starting with
-              <literal>http://www.hibernate.org/dtd/</literal>. The
-              resolver attempts to resolve these entities via the classloader
-              which loaded the Hibernate classes.</para>
+              <literal>http://www.hibernate.org/dtd/</literal>. The resolver
+              attempts to resolve these entities via the classloader which
+              loaded the Hibernate classes.</para>
             </listitem>
 
             <listitem>
@@ -5777,16 +5777,37 @@
     the values of columns mapped to <link
     linkend="mapping-declaration-property">simple properties</link>. For
     example, if your database provides a set of data encryption functions, you
-    can invoke them for individual columns like this: 
-</para>
-<programlisting
-    role="XML">&lt;property name="creditCardNumber"&gt;
+    can invoke them for individual columns like this:</para>
+
+    <programlisting role="JAVA">@Entity
+class CreditCard {
+   @Column(name="credit_card_num")
+   @ReadExpression(
+      forColumn="credit_card_num", 
+      expression="decrypt(credit_card_num)")
+   @WriteExpression(
+      forColumn="credit_card_num", 
+      expression="encrypt(?)")
+   public String getCreditCardNumber() { return creditCardNumber; }
+   public void setCreditCardNumber(String number) { this.creditCardNumber = number; }
+   private String creditCardNumber;
+}</programlisting>
+
+    <para>or in XML</para>
+
+    <programlisting role="XML">&lt;property name="creditCardNumber"&gt;
         &lt;column 
           name="credit_card_num"
           read="decrypt(credit_card_num)"
           write="encrypt(?)"/&gt;
 &lt;/property&gt;</programlisting>
 
+    <note>
+      <para>When using <classname>@ReadExpression</classname> /
+      <classname>@WriteExpression</classname> annotations, you must explicitly
+      declare the <literal>@Column.name</literal> property.</para>
+    </note>
+
     <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:
@@ -5803,10 +5824,6 @@
 
     <para>The <literal>write</literal> expression, if specified, must contain
     exactly one '?' placeholder for the value.</para>
-
-    <note>
-      <para>This feature is not supported in Annotations</para>
-    </note>
   </section>
 
   <section id="mapping-database-object">

Added: 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	                        (rev 0)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/annotations/various/readwriteexpression/ReadWriteExpressionTest.java	2010-09-27 22:07:44 UTC (rev 20728)
@@ -0,0 +1,88 @@
+/*
+ * 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 java.util.Date;
+
+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, 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);
+
+		// 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
+		};
+	}
+}

Added: 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	                        (rev 0)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/annotations/various/readwriteexpression/Staff.java	2010-09-27 22:07:44 UTC (rev 20728)
@@ -0,0 +1,65 @@
+/*
+ * 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 javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+import org.hibernate.annotations.ReadExpression;
+import org.hibernate.annotations.WriteExpression;
+
+/**
+ * @author Emmanuel Bernard
+ */
+ at Entity
+ at Table(name="t_staff")
+public class Staff {
+
+	public Staff(double sizeInInches, double radius, Integer id) {
+		this.sizeInInches = sizeInInches;
+		this.radiusS = radius;
+		this.id = id;
+	}
+
+	@Id
+	public Integer getId() { return id; }
+	public void setId(Integer id) {  this.id = id; }
+	private Integer id;
+
+	@Column(name="size_in_cm")
+	@ReadExpression( forColumn = "size_in_cm", expression = "size_in_cm / 2.54" )
+	@WriteExpression( forColumn = "size_in_cm", expression = "? * 2.54" )
+	public double getSizeInInches() { return sizeInInches; }
+	public void setSizeInInches(double sizeInInches) {  this.sizeInInches = sizeInInches; }
+	private double sizeInInches;
+
+	@Column(name="radiusS")
+	@ReadExpression( forColumn = "radiusS", expression = "radiusS / 2.54" )
+	@WriteExpression( forColumn = "radiusS", expression = "? * 2.54" )
+	public double getRadiusS() { return radiusS; }
+	public void setRadiusS(double radiusS) {  this.radiusS = radiusS; }
+	private double radiusS;
+}



More information about the hibernate-commits mailing list