Hibernate SVN: r19109 - in core/trunk: core/src/main/java/org/hibernate/criterion and 6 other directories.
by hibernate-commits@lists.jboss.org
Author: stliu
Date: 2010-03-24 14:24:39 -0400 (Wed, 24 Mar 2010)
New Revision: 19109
Modified:
core/trunk/annotations/src/test/java/org/hibernate/test/annotations/cid/CompositeIdTest.java
core/trunk/core/src/main/java/org/hibernate/criterion/InExpression.java
core/trunk/core/src/main/java/org/hibernate/dialect/Oracle9iDialect.java
core/trunk/core/src/main/java/org/hibernate/hql/ast/tree/BinaryLogicOperatorNode.java
core/trunk/core/src/main/java/org/hibernate/hql/ast/tree/InLogicOperatorNode.java
core/trunk/testing/src/main/java/org/hibernate/junit/functional/FunctionalTestCase.java
core/trunk/testsuite/src/test/java/org/hibernate/test/hql/ASTParserLoadingTest.java
core/trunk/testsuite/src/test/java/org/hibernate/test/hql/HQLTest.java
core/trunk/testsuite/src/test/java/org/hibernate/test/joinedsubclass/JoinedSubclassTest.java
core/trunk/testsuite/src/test/java/org/hibernate/test/unionsubclass2/UnionSubclassTest.java
Log:
HHH-4907 Support for tuple syntax in HQL/Criteria on databases which do not support tuple syntax
Modified: core/trunk/annotations/src/test/java/org/hibernate/test/annotations/cid/CompositeIdTest.java
===================================================================
--- core/trunk/annotations/src/test/java/org/hibernate/test/annotations/cid/CompositeIdTest.java 2010-03-24 18:19:00 UTC (rev 19108)
+++ core/trunk/annotations/src/test/java/org/hibernate/test/annotations/cid/CompositeIdTest.java 2010-03-24 18:24:39 UTC (rev 19109)
@@ -11,6 +11,7 @@
import org.hibernate.Criteria;
import org.hibernate.criterion.Disjunction;
import org.hibernate.criterion.Restrictions;
+import org.hibernate.junit.FailureExpected;
import org.hibernate.junit.SkipForDialect;
import org.hibernate.test.annotations.TestCase;
@@ -253,46 +254,12 @@
s.close();
}
- @SkipForDialect(value=org.hibernate.dialect.HSQLDialect.class,
- comment = "HSQLDB does not support ((..., ...),(..., ...))")
public void testQueryInAndComposite() {
Session s = openSession( );
Transaction transaction = s.beginTransaction();
-
- SomeEntity someEntity = new SomeEntity();
- someEntity.setId( new SomeEntityId( ) );
- someEntity.getId().setId( 1 );
- someEntity.getId().setVersion( 11 );
- someEntity.setProp( "aa" );
- s.persist( someEntity );
- someEntity = new SomeEntity();
- someEntity.setId( new SomeEntityId( ) );
- someEntity.getId().setId( 1 );
- someEntity.getId().setVersion( 12 );
- someEntity.setProp( "bb" );
- s.persist( someEntity );
- someEntity = new SomeEntity();
- someEntity.setId( new SomeEntityId( ) );
- someEntity.getId().setId( 10 );
- someEntity.getId().setVersion( 21 );
- someEntity.setProp( "cc1" );
- s.persist( someEntity );
- someEntity = new SomeEntity();
- someEntity.setId( new SomeEntityId( ) );
- someEntity.getId().setId( 10 );
- someEntity.getId().setVersion( 22 );
- someEntity.setProp( "cc2" );
- s.persist( someEntity );
- someEntity = new SomeEntity();
- someEntity.setId( new SomeEntityId( ) );
- someEntity.getId().setId( 10 );
- someEntity.getId().setVersion( 23 );
- someEntity.setProp( "cc3" );
- s.persist( someEntity );
-
- s.flush();
-
+ createData( s );
+ s.flush();
List ids = new ArrayList<SomeEntityId>(2);
ids.add( new SomeEntityId(1,12) );
ids.add( new SomeEntityId(10,23) );
@@ -308,7 +275,60 @@
transaction.rollback();
s.close();
}
+ public void testQueryInAndCompositeWithHQL() {
+ Session s = openSession( );
+ Transaction transaction = s.beginTransaction();
+ createData( s );
+ s.flush();
+ List ids = new ArrayList<SomeEntityId>(2);
+ ids.add( new SomeEntityId(1,12) );
+ ids.add( new SomeEntityId(10,23) );
+ ids.add( new SomeEntityId(10,22) );
+ Query query=s.createQuery( "from SomeEntity e where e.id in (:idList)" );
+ query.setParameterList( "idList", ids );
+ List list=query.list();
+ assertEquals( 3, list.size() );
+ transaction.rollback();
+ s.close();
+ }
+
+ private void createData(Session s){
+ SomeEntity someEntity = new SomeEntity();
+ someEntity.setId( new SomeEntityId( ) );
+ someEntity.getId().setId( 1 );
+ someEntity.getId().setVersion( 11 );
+ someEntity.setProp( "aa" );
+ s.persist( someEntity );
+
+ someEntity = new SomeEntity();
+ someEntity.setId( new SomeEntityId( ) );
+ someEntity.getId().setId( 1 );
+ someEntity.getId().setVersion( 12 );
+ someEntity.setProp( "bb" );
+ s.persist( someEntity );
+
+ someEntity = new SomeEntity();
+ someEntity.setId( new SomeEntityId( ) );
+ someEntity.getId().setId( 10 );
+ someEntity.getId().setVersion( 21 );
+ someEntity.setProp( "cc1" );
+ s.persist( someEntity );
+
+ someEntity = new SomeEntity();
+ someEntity.setId( new SomeEntityId( ) );
+ someEntity.getId().setId( 10 );
+ someEntity.getId().setVersion( 22 );
+ someEntity.setProp( "cc2" );
+ s.persist( someEntity );
+
+ someEntity = new SomeEntity();
+ someEntity.setId( new SomeEntityId( ) );
+ someEntity.getId().setId( 10 );
+ someEntity.getId().setVersion( 23 );
+ someEntity.setProp( "cc3" );
+ s.persist( someEntity );
+ }
protected Class[] getAnnotatedClasses() {
return new Class[] {
Parent.class,
Modified: core/trunk/core/src/main/java/org/hibernate/criterion/InExpression.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/criterion/InExpression.java 2010-03-24 18:19:00 UTC (rev 19108)
+++ core/trunk/core/src/main/java/org/hibernate/criterion/InExpression.java 2010-03-24 18:24:39 UTC (rev 19109)
@@ -50,19 +50,35 @@
this.values = values;
}
- public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery)
- throws HibernateException {
- String[] columns = criteriaQuery.getColumnsUsingProjection(criteria, propertyName);
- String singleValueParam = StringHelper.repeat( "?, ", columns.length-1 ) + "?";
- if ( columns.length>1 ) singleValueParam = '(' + singleValueParam + ')';
- String params = values.length>0 ?
- StringHelper.repeat( singleValueParam + ", ", values.length-1 ) + singleValueParam :
- "";
- String cols = StringHelper.join(", ", columns);
- if ( columns.length>1 ) cols = '(' + cols + ')';
- return cols + " in (" + params + ')';
- }
+ public String toSqlString( Criteria criteria, CriteriaQuery criteriaQuery )
+ throws HibernateException {
+ String[] columns = criteriaQuery.getColumnsUsingProjection(
+ criteria, propertyName );
+ if ( criteriaQuery.getFactory().getDialect()
+ .supportsRowValueConstructorSyntaxInInList() || columns.length<=1) {
+ String singleValueParam = StringHelper.repeat( "?, ",
+ columns.length - 1 )
+ + "?";
+ if ( columns.length > 1 )
+ singleValueParam = '(' + singleValueParam + ')';
+ String params = values.length > 0 ? StringHelper.repeat(
+ singleValueParam + ", ", values.length - 1 )
+ + singleValueParam : "";
+ String cols = StringHelper.join( ", ", columns );
+ if ( columns.length > 1 )
+ cols = '(' + cols + ')';
+ return cols + " in (" + params + ')';
+ } else {
+ String cols = " ( " + StringHelper.join( " = ? and ", columns ) + "= ? ) ";
+ cols = values.length > 0 ? StringHelper.repeat( cols
+ + "or ", values.length - 1 )
+ + cols : "";
+ cols = " ( " + cols + " ) ";
+ return cols;
+ }
+ }
+
public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery)
throws HibernateException {
ArrayList list = new ArrayList();
Modified: core/trunk/core/src/main/java/org/hibernate/dialect/Oracle9iDialect.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/dialect/Oracle9iDialect.java 2010-03-24 18:19:00 UTC (rev 19108)
+++ core/trunk/core/src/main/java/org/hibernate/dialect/Oracle9iDialect.java 2010-03-24 18:24:39 UTC (rev 19109)
@@ -127,5 +127,12 @@
public String getReadLockString(int timeout) {
return getWriteLockString( timeout );
}
+ /**
+ * HHH-4907, I don't know if oracle 8 supports this syntax, so I'd think it is better add this
+ * method here. Reopen this issue if you found/know 8 supports it.
+ */
+ public boolean supportsRowValueConstructorSyntaxInInList() {
+ return true;
+ }
}
Modified: core/trunk/core/src/main/java/org/hibernate/hql/ast/tree/BinaryLogicOperatorNode.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/hql/ast/tree/BinaryLogicOperatorNode.java 2010-03-24 18:19:00 UTC (rev 19108)
+++ core/trunk/core/src/main/java/org/hibernate/hql/ast/tree/BinaryLogicOperatorNode.java 2010-03-24 18:24:39 UTC (rev 19109)
@@ -75,7 +75,7 @@
}
protected final void mutateRowValueConstructorSyntaxesIfNecessary(Type lhsType, Type rhsType) {
- // TODO : this really needs to be delayed unitl after we definitively know all node types
+ // TODO : this really needs to be delayed until after we definitively know all node types
// where this is currently a problem is parameters for which where we cannot unequivocally
// resolve an expected type
SessionFactoryImplementor sessionFactory = getSessionFactoryHelper().getFactory();
@@ -109,7 +109,7 @@
* @param valueElements The number of elements in the row value constructor list.
*/
private void mutateRowValueConstructorSyntax(int valueElements) {
- // mutation depends on the types of nodes invloved...
+ // mutation depends on the types of nodes involved...
int comparisonType = getType();
String comparisonText = getText();
setType( HqlSqlTokenTypes.AND );
@@ -127,8 +127,21 @@
? null
: ( ( ParameterNode ) getRightHandOperand() ).getHqlParameterSpecification();
- AST container = this;
- for ( int i = valueElements - 1; i > 0; i-- ) {
+ translate( valueElements, comparisonType, comparisonText,
+ lhsElementTexts, rhsElementTexts,
+ lhsEmbeddedCompositeParameterSpecification,
+ rhsEmbeddedCompositeParameterSpecification, this );
+ }
+ /**
+ *
+ */
+ protected void translate( int valueElements, int comparisonType,
+ String comparisonText, String[] lhsElementTexts,
+ String[] rhsElementTexts,
+ ParameterSpecification lhsEmbeddedCompositeParameterSpecification,
+ ParameterSpecification rhsEmbeddedCompositeParameterSpecification,
+ AST container ) {
+ for ( int i = valueElements - 1; i > 0; i-- ) {
if ( i == 1 ) {
AST op1 = getASTFactory().create( comparisonType, comparisonText );
AST lhs1 = getASTFactory().create( HqlSqlTokenTypes.SQL_TOKEN, lhsElementTexts[0] );
@@ -165,9 +178,9 @@
container = newContainer;
}
}
- }
+ }
- private static String[] extractMutationTexts(Node operand, int count) {
+ protected static String[] extractMutationTexts(Node operand, int count) {
if ( operand instanceof ParameterNode ) {
String[] rtn = new String[count];
for ( int i = 0; i < count; i++ ) {
Modified: core/trunk/core/src/main/java/org/hibernate/hql/ast/tree/InLogicOperatorNode.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/hql/ast/tree/InLogicOperatorNode.java 2010-03-24 18:19:00 UTC (rev 19108)
+++ core/trunk/core/src/main/java/org/hibernate/hql/ast/tree/InLogicOperatorNode.java 2010-03-24 18:24:39 UTC (rev 19109)
@@ -24,8 +24,16 @@
*/
package org.hibernate.hql.ast.tree;
+import java.util.ArrayList;
+import java.util.List;
+
import antlr.SemanticException;
import antlr.collections.AST;
+
+import org.hibernate.engine.SessionFactoryImplementor;
+import org.hibernate.hql.antlr.HqlSqlTokenTypes;
+import org.hibernate.hql.antlr.HqlTokenTypes;
+import org.hibernate.param.ParameterSpecification;
import org.hibernate.type.Type;
/**
@@ -60,5 +68,109 @@
inListChild = inListChild.getNextSibling();
}
}
+ SessionFactoryImplementor sessionFactory = getSessionFactoryHelper().getFactory();
+ if ( sessionFactory.getDialect().supportsRowValueConstructorSyntaxInInList() )
+ return;
+
+ Type lhsType = extractDataType( lhs );
+ if ( lhsType == null )
+ return;
+ int lhsColumnSpan = lhsType.getColumnSpan( sessionFactory );
+ Node rhsNode = (Node) inList.getFirstChild();
+ if ( !isNodeAcceptable( rhsNode ) )
+ return;
+ int rhsColumnSpan = 0;
+ if ( rhsNode.getType() == HqlTokenTypes.VECTOR_EXPR ) {
+ rhsColumnSpan = rhsNode.getNumberOfChildren();
+ } else {
+ Type rhsType = extractDataType( rhsNode );
+ if ( rhsType == null )
+ return;
+ rhsColumnSpan = rhsType.getColumnSpan( sessionFactory );
+ }
+ if ( lhsColumnSpan > 1 && rhsColumnSpan > 1 ) {
+ mutateRowValueConstructorSyntaxInInListSyntax( lhsColumnSpan, rhsColumnSpan );
+ }
}
+
+ /**
+ * this is possible for parameter lists and explicit lists. It is completely unreasonable for sub-queries.
+ */
+ private boolean isNodeAcceptable( Node rhsNode ) {
+ return rhsNode instanceof LiteralNode
+ || rhsNode instanceof ParameterNode
+ || rhsNode.getType() == HqlTokenTypes.VECTOR_EXPR;
+ }
+ /**
+ * Mutate the subtree relating to a row-value-constructor in "in" list to instead use
+ * a series of ORen and ANDed predicates. This allows multi-column type comparisons
+ * and explicit row-value-constructor in "in" list syntax even on databases which do
+ * not support row-value-constructor in "in" list.
+ * <p/>
+ * For example, here we'd mutate "... where (col1, col2) in ( ('val1', 'val2'), ('val3', 'val4') ) ..." to
+ * "... where (col1 = 'val1' and col2 = 'val2') or (col1 = 'val3' and val2 = 'val4') ..."
+ *
+ * @param lhsColumnSpan The number of elements in the row value constructor list.
+ */
+ private void mutateRowValueConstructorSyntaxInInListSyntax(
+ int lhsColumnSpan, int rhsColumnSpan ) {
+ String[] lhsElementTexts = extractMutationTexts( getLeftHandOperand(),
+ lhsColumnSpan );
+ Node rhsNode = (Node) getInList().getFirstChild();
+
+ ParameterSpecification lhsEmbeddedCompositeParameterSpecification = getLeftHandOperand() == null
+ || ( !ParameterNode.class.isInstance( getLeftHandOperand() ) ) ? null
+ : ( (ParameterNode) getLeftHandOperand() )
+ .getHqlParameterSpecification();
+ /**
+ * only one element in "in" cluster, e.g.
+ * <code> where (a,b) in ( (1,2) ) </code> this will be mutated to
+ * <code>where a=1 and b=2 </code>
+ */
+ if ( rhsNode != null && rhsNode.getNextSibling() == null ) {
+ String[] rhsElementTexts = extractMutationTexts( rhsNode,
+ rhsColumnSpan );
+ setType( HqlSqlTokenTypes.AND );
+ setText( "AND" );
+ ParameterSpecification rhsEmbeddedCompositeParameterSpecification = rhsNode == null
+ || ( !ParameterNode.class.isInstance( rhsNode ) ) ? null
+ : ( (ParameterNode) rhsNode )
+ .getHqlParameterSpecification();
+ translate( lhsColumnSpan, HqlSqlTokenTypes.EQ, "=", lhsElementTexts,
+ rhsElementTexts,
+ lhsEmbeddedCompositeParameterSpecification,
+ rhsEmbeddedCompositeParameterSpecification, this );
+ } else {
+ List andElementsNodeList = new ArrayList();
+ while ( rhsNode != null ) {
+ String[] rhsElementTexts = extractMutationTexts( rhsNode,
+ rhsColumnSpan );
+ AST and = getASTFactory().create( HqlSqlTokenTypes.AND, "AND" );
+ ParameterSpecification rhsEmbeddedCompositeParameterSpecification = rhsNode == null
+ || ( !ParameterNode.class.isInstance( rhsNode ) ) ? null
+ : ( (ParameterNode) rhsNode )
+ .getHqlParameterSpecification();
+ translate( lhsColumnSpan, HqlSqlTokenTypes.EQ, "=",
+ lhsElementTexts, rhsElementTexts,
+ lhsEmbeddedCompositeParameterSpecification,
+ rhsEmbeddedCompositeParameterSpecification, and );
+ andElementsNodeList.add( and );
+ rhsNode = (Node) rhsNode.getNextSibling();
+ }
+ setType( HqlSqlTokenTypes.OR );
+ setText( "OR" );
+ AST curNode = this;
+ for ( int i = andElementsNodeList.size() - 1; i > 1; i-- ) {
+ AST or = getASTFactory().create( HqlSqlTokenTypes.OR, "OR" );
+ curNode.setFirstChild( or );
+ curNode = or;
+ AST and = (AST) andElementsNodeList.get( i );
+ or.setNextSibling( and );
+ }
+ AST node0 = (AST) andElementsNodeList.get( 0 );
+ AST node1 = (AST) andElementsNodeList.get( 1 );
+ node0.setNextSibling( node1 );
+ curNode.setFirstChild( node0 );
+ }
+ }
}
Modified: core/trunk/testing/src/main/java/org/hibernate/junit/functional/FunctionalTestCase.java
===================================================================
--- core/trunk/testing/src/main/java/org/hibernate/junit/functional/FunctionalTestCase.java 2010-03-24 18:19:00 UTC (rev 19108)
+++ core/trunk/testing/src/main/java/org/hibernate/junit/functional/FunctionalTestCase.java 2010-03-24 18:24:39 UTC (rev 19109)
@@ -432,14 +432,6 @@
return false;
}
- protected boolean supportsRowValueConstructorSyntaxInInList() {
- if ( ! getDialect().supportsRowValueConstructorSyntaxInInList() ) {
- reportSkip( "Dialect does not support 'tuple' syntax as part of an IN value list", "query support" );
- return false;
- }
- return true;
- }
-
protected boolean supportsResultSetPositionQueryMethodsOnForwardOnlyCursor() {
if ( ! getDialect().supportsResultSetPositionQueryMethodsOnForwardOnlyCursor() ) {
reportSkip( "Driver does not support 'position query' methods on forward-only cursors", "query support" );
Modified: core/trunk/testsuite/src/test/java/org/hibernate/test/hql/ASTParserLoadingTest.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/hql/ASTParserLoadingTest.java 2010-03-24 18:19:00 UTC (rev 19108)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/hql/ASTParserLoadingTest.java 2010-03-24 18:24:39 UTC (rev 19109)
@@ -48,6 +48,7 @@
import org.hibernate.test.cid.LineItem;
import org.hibernate.test.cid.Order;
import org.hibernate.test.cid.Product;
+import org.hibernate.test.cid.LineItem.Id;
import org.hibernate.transform.DistinctRootEntityResultTransformer;
import org.hibernate.transform.Transformers;
import org.hibernate.type.ComponentType;
@@ -467,6 +468,48 @@
s.close();
}
+ public void testRowValueConstructorSyntaxInInList() {
+ Session s = openSession();
+ s.beginTransaction();
+ Product product = new Product();
+ product.setDescription( "My Product" );
+ product.setNumberAvailable( 10 );
+ product.setPrice( new BigDecimal( 123 ) );
+ product.setProductId( "4321" );
+ s.save( product );
+
+
+ Customer customer = new Customer();
+ customer.setCustomerId( "123456789" );
+ customer.setName( "My customer" );
+ customer.setAddress( "somewhere" );
+ s.save( customer );
+
+ Order order = customer.generateNewOrder( new BigDecimal( 1234 ) );
+ s.save( order );
+
+ LineItem li = order.generateLineItem( product, 5 );
+ s.save( li );
+ product = new Product();
+ product.setDescription( "My Product" );
+ product.setNumberAvailable( 10 );
+ product.setPrice( new BigDecimal( 123 ) );
+ product.setProductId( "1234" );
+ s.save( product );
+ li = order.generateLineItem( product, 10 );
+ s.save( li );
+
+ s.flush();
+ Query query = s.createQuery( "from LineItem l where l.id in (:idList)" );
+ List list = new ArrayList();
+ list.add( new Id("123456789", order.getId().getOrderNumber(), "4321") );
+ list.add( new Id("123456789", order.getId().getOrderNumber(), "1234") );
+ query.setParameterList( "idList", list );
+ assertEquals( 2, query.list().size() );
+ s.getTransaction().commit();
+ s.close();
+
+ }
private void checkCounts(String hql, int expected, String testCondition) {
Session s = openSession();
s.beginTransaction();
Modified: core/trunk/testsuite/src/test/java/org/hibernate/test/hql/HQLTest.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/hql/HQLTest.java 2010-03-24 18:19:00 UTC (rev 19108)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/hql/HQLTest.java 2010-03-24 18:24:39 UTC (rev 19109)
@@ -9,7 +9,6 @@
import java.util.List;
import java.util.Map;
-import antlr.RecognitionException;
import junit.framework.Test;
import org.hibernate.Hibernate;
@@ -30,6 +29,7 @@
import org.hibernate.engine.query.ReturnMetadata;
import org.hibernate.hql.QueryTranslator;
import org.hibernate.hql.QueryTranslatorFactory;
+import org.hibernate.hql.antlr.HqlTokenTypes;
import org.hibernate.hql.ast.ASTQueryTranslatorFactory;
import org.hibernate.hql.ast.DetailedSemanticException;
import org.hibernate.hql.ast.QuerySyntaxException;
@@ -39,9 +39,14 @@
import org.hibernate.hql.ast.tree.DotNode;
import org.hibernate.hql.ast.tree.FromReferenceNode;
import org.hibernate.hql.ast.tree.IndexNode;
+import org.hibernate.hql.ast.tree.QueryNode;
import org.hibernate.hql.ast.tree.SelectClause;
+import org.hibernate.hql.ast.util.ASTUtil;
import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
+import antlr.RecognitionException;
+import antlr.collections.AST;
+
/**
* Tests cases where the AST based query translator and the 'classic' query translator generate identical SQL.
*
@@ -94,7 +99,35 @@
assertTranslation( "from Animal a where a.offspring.description = 'xyz'" );
assertTranslation( "from Animal a where a.offspring.father.description = 'xyz'" );
}
+
+ /**
+ * ClassicQueryTranslatorFactory does not support translate tuple with "in" syntax to "and/or" clause
+ */
+ public void testRowValueConstructorSyntaxInInListFailureExpected() {
+ assertTranslation( "from LineItem l where l.id in (:idList)" );
+ }
+ public void testRowValueConstructorSyntaxInInList() {
+ if (!getDialect().supportsRowValueConstructorSyntaxInInList())
+ return;
+ QueryTranslatorImpl translator = createNewQueryTranslator("from LineItem l where l.id in (?)");
+ assertInExist("'in' should be translated to 'and'", false, translator);
+ translator = createNewQueryTranslator("from LineItem l where l.id in (('a1',1,'b1'),('a2',2,'b2'))");
+ assertInExist("'in' should be translated to 'and'", false, translator);
+ translator = createNewQueryTranslator("from Animal a where a.id in (?)");
+ assertInExist("only translate tuple with 'in' syntax", true, translator);
+ translator = createNewQueryTranslator("from LineItem l where l.id in (select a1 from Animal a1 left join a1.offspring o where a1.id = 1)");
+ assertInExist("do not translate subqueries", true, translator);
+
+ }
+
+ private void assertInExist( String message, boolean expected, QueryTranslatorImpl translator ) {
+ AST ast = translator.getSqlAST().getWalker().getAST();
+ QueryNode queryNode = (QueryNode) ast;
+ AST inNode = ASTUtil.findTypeInChildren( queryNode, HqlTokenTypes.IN );
+ assertEquals( message, expected, inNode != null );
+ }
+
public void testSubComponentReferences() {
assertTranslation( "select c.address.zip.code from ComponentContainer c" );
assertTranslation( "select c.address.zip from ComponentContainer c" );
Modified: core/trunk/testsuite/src/test/java/org/hibernate/test/joinedsubclass/JoinedSubclassTest.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/joinedsubclass/JoinedSubclassTest.java 2010-03-24 18:19:00 UTC (rev 19108)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/joinedsubclass/JoinedSubclassTest.java 2010-03-24 18:24:39 UTC (rev 19109)
@@ -92,15 +92,12 @@
joe = (Customer) s.get( Customer.class, new Long( joe.getId() ) );
mark.setZip("30306");
- assertEquals( s.createQuery("from Person p where p.address.zip = '30306'").list().size(), 1 );
+ assertEquals( s.createQuery("from Person p where p.address.zip = '30306'" ).list().size(),1 );
- if ( supportsRowValueConstructorSyntaxInInList() ) {
- s.createCriteria(Person.class).add(
- Restrictions.in("address", new Address[] { mark.getAddress(), joe.getAddress() } )
- ).list();
- }
+ s.createCriteria( Person.class ).add(
+ Restrictions.in( "address", new Address[] { mark.getAddress(), joe.getAddress() } ) ).list();
- s.delete(mark);
+ s.delete(mark);
s.delete(joe);
s.delete(yomomma);
assertTrue( s.createQuery("from Person").list().isEmpty() );
Modified: core/trunk/testsuite/src/test/java/org/hibernate/test/unionsubclass2/UnionSubclassTest.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/unionsubclass2/UnionSubclassTest.java 2010-03-24 18:19:00 UTC (rev 19108)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/unionsubclass2/UnionSubclassTest.java 2010-03-24 18:24:39 UTC (rev 19109)
@@ -94,11 +94,9 @@
mark.setZip("30306");
assertEquals( s.createQuery("from Person p where p.address.zip = '30306'").list().size(), 1 );
- if ( supportsRowValueConstructorSyntaxInInList() ) {
- s.createCriteria(Person.class).add(
- Restrictions.in("address", new Address[] { mark.getAddress(), joe.getAddress() } )
- ).list();
- }
+ s.createCriteria( Person.class ).add(
+ Restrictions.in( "address", new Address[] { mark.getAddress(),
+ joe.getAddress() } ) ).list();
s.delete(mark);
s.delete(joe);
14 years, 8 months
Hibernate SVN: r19108 - in core/trunk/documentation/manual/src/main/docbook/en-US: content and 1 other directory.
by hibernate-commits@lists.jboss.org
Author: gbadner
Date: 2010-03-24 14:19:00 -0400 (Wed, 24 Mar 2010)
New Revision: 19108
Added:
core/trunk/documentation/manual/src/main/docbook/en-US/content/readonly.xml
Modified:
core/trunk/documentation/manual/src/main/docbook/en-US/HIBERNATE_-_Relational_Persistence_for_Idiomatic_Java.xml
Log:
HHH-4940 : Document immutable/read-only entity and immutable collection functionality
Modified: core/trunk/documentation/manual/src/main/docbook/en-US/HIBERNATE_-_Relational_Persistence_for_Idiomatic_Java.xml
===================================================================
--- core/trunk/documentation/manual/src/main/docbook/en-US/HIBERNATE_-_Relational_Persistence_for_Idiomatic_Java.xml 2010-03-24 17:14:35 UTC (rev 19107)
+++ core/trunk/documentation/manual/src/main/docbook/en-US/HIBERNATE_-_Relational_Persistence_for_Idiomatic_Java.xml 2010-03-24 18:19:00 UTC (rev 19108)
@@ -80,6 +80,7 @@
<xi:include href="content/inheritance_mapping.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="content/session_api.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
+ <xi:include href="content/readonly.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="content/transactions.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="content/events.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="content/batch.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
Added: core/trunk/documentation/manual/src/main/docbook/en-US/content/readonly.xml
===================================================================
--- core/trunk/documentation/manual/src/main/docbook/en-US/content/readonly.xml (rev 0)
+++ core/trunk/documentation/manual/src/main/docbook/en-US/content/readonly.xml 2010-03-24 18:19:00 UTC (rev 19108)
@@ -0,0 +1,859 @@
+<?xml version='1.0' encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+<!ENTITY % BOOK_ENTITIES SYSTEM "../HIBERNATE_-_Relational_Persistence_for_Idiomatic_Java.ent">
+%BOOK_ENTITIES;
+
+]>
+
+<chapter id="readonly">
+ <title>Read-only entities</title>
+
+ <important>
+ <para>
+ Hibernate's treatment of <emphasis>read-only</emphasis> entities may
+ differ from what you may have encountered elsewhere. Incorrect usage
+ may cause unexpected results.
+ </para>
+ </important>
+
+ <para>
+ When an entity is read-only:
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ Hibernate does not dirty-check the entity's simple
+ properties or single-ended associations;
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Hibernate will not update simple properties or updatable
+ single-ended associations;
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Hibernate will not update the version of the read-only
+ entity if only simple properties or single-ended
+ updatable associations are changed;
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+
+ <para>
+ In some ways, Hibernate treats read-only entities the same as entities that are
+ not read-only:
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ Hibernate cascades operations to associations as
+ defined in the entity mapping.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Hibernate updates the version if the entity has a
+ collection with changes that dirties the entity;
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ A read-only entity can be deleted.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+
+ <para>
+ Even if an entity is not read-only, its collection association can
+ be affected if it contains a read-only entity.
+ </para>
+
+ <para>
+ For details about the affect of read-only entities on different
+ property and association types, see
+ <xref linkend="readonly-proptypes"/>.
+ </para>
+
+ <para>
+ For details about how to make entities read-only, see
+ <xref linkend="readonly-api"/>
+ </para>
+
+ <para>
+ Hibernate does some optimizing for read-only entities:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ It saves execution time by not dirty-checking simple properties or
+ single-ended associations.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ It saves memory by deleting database snapshots.
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <section id="readonly-api">
+ <title>Making persistent entities read-only</title>
+
+ <para>
+ Only persistent entities can be made read-only. Transient and
+ detached entities must be put in persistent state before they
+ can be made read-only.
+ </para>
+
+ <para>
+ Hibernate provides the following ways to make persistent entities read-only:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ you can map an entity class as <emphasis>immutable</emphasis>;
+ when an entity of an immutable class is made persistent,
+ Hibernate automatically makes it read-only.
+ see <xref linkend="readonly-api-immutable"/> for details
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ you can change a default so that entities loaded
+ into the session by Hibernate are automatically
+ made read-only; see <xref linkend="readonly-api-loaddefault"/> for details
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ you can make an HQL query or criteria read-only so
+ that entities loaded when the query or criteria executes,
+ scrolls, or iterates, are automatically
+ made read-only; see <xref linkend="readonly-api-querycriteria"/> for details
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ you can make a persistent entity that is already in the
+ in the session read-only; see
+ <xref linkend="readonly-api-entity"/> for details
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <section id="readonly-api-immutable">
+ <title>Entities of immutable classes</title>
+
+ <para>
+ When an entity instance of an immutable class is made
+ persistent, Hibernate automatically makes it read-only.
+ </para>
+ <para>
+ An entity of an immutable class can created
+ and deleted the same as an entity of a mutable class.
+ </para>
+
+ <para>
+ Hibernate treats a persistent entity of an immutable
+ class the same way as a read-only persistent entity
+ of a mutable class. The only exception is that
+ Hibernate will not allow an entity of an immutable
+ class to be changed so it is not read-only.
+ </para>
+
+ </section>
+
+ <section id="readonly-api-loaddefault">
+ <title>Loading persistent entities as read-only</title>
+
+ <note>
+ <para>
+ Entities of immutable classes are automatically loaded
+ as read-only.
+ </para>
+ </note>
+
+ <para>
+ To change the default behavior so Hibernate loads entity
+ instances of mutable classes into the session and automatically
+ makes them read-only, call:
+ </para>
+ <programlisting role="Java">Session.setDefaultReadOnly( true );</programlisting>
+
+ <para>
+ To change the default back so entities loaded by Hibernate are not
+ made read-only, call:
+ </para>
+ <programlisting role="Java">Session.setDefaultReadOnly( false );</programlisting>
+
+ <para>
+ You can determine the current setting by calling:
+ </para>
+ <programlisting role="Java">Session.isDefaultReadOnly();</programlisting>
+
+ <para>
+ If Session.isDefaultReadOnly() returns true, entities loaded by
+ the following are automatically made read-only:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ Session.load()
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Session.get()
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Session.merge()
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ executing, scrolling, or iterating HQL queries and
+ criteria; to override this setting for a particular
+ HQL query or criteria see
+ <xref linkend="readonly-api-querycriteria"/>
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ Changing this default has no effect on:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ persistent entities already in the session when the
+ default was changed
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ persistent entities that are refreshed via
+ Session.refresh(); a refreshed persistent
+ entity will only be read-only if it was
+ read-only before refreshing
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ persistent entities added by the application via
+ Session.persist(), Session.save(), and Session.update()
+ Session.saveOrUpdate()
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ </section>
+
+ <section id="readonly-api-querycriteria">
+ <title>Loading read-only entities from an HQL query/criteria</title>
+
+ <note>
+ <para>
+ Entities of immutable classes are automatically loaded
+ as read-only.
+ </para>
+ </note>
+
+ <para>
+ If Session.isDefaultReadOnly() returns false (the default)
+ when an HQL query or criteria executes, then entities
+ and proxies of mutable classes loaded by the query will
+ not be read-only.
+ </para>
+
+ <para>
+ You can override this behavior so that entities and proxies loaded
+ by an HQL query or criteria are automatically made read-only.
+ </para>
+
+ <para>
+ For an HQL query, call:
+ </para>
+ <programlisting role="Java">Query.setReadOnly( true );</programlisting>
+
+ <para>
+ <literal>Query.setReadOnly( true )</literal> must be called before
+ <literal>Query.list()</literal>, <literal>Query.uniqueResult()</literal>,
+ <literal>Query.scroll()</literal>, or <literal>Query.iterate()</literal>
+ </para>
+
+ <para>
+ For an HQL criteria, call:
+ </para>
+ <programlisting role="Java">Criteria.setReadOnly( true );</programlisting>
+
+ <para>
+ <literal>Criteria.setReadOnly( true )</literal> must be called before
+ <literal>Criteria.list()</literal>, <literal>Criteria.uniqueResult()</literal>,
+ or <literal>Criteria.scroll()</literal>
+ </para>
+
+ <para>
+ Entities and proxies that exist in the session before being returned
+ by an HQL query or criteria are not affected.
+ </para>
+
+ <para>
+ Uninitialized persistent collections returned by the query are
+ not affected. Later, when the collection is initialized,
+ entities loaded into the session will be read-only if
+ Session.isDefaultReadOnly() returns true.
+ </para>
+
+ <para>
+ Using <literal>Query.setReadOnly( true )</literal> or
+ <literal>Criteria.setReadOnly( true )</literal> works well
+ when a single HQL query or criteria loads all the entities and
+ intializes all the proxies and collections that the application
+ needs to be read-only.
+ </para>
+
+ <para>
+ When it is not possible to load and initialize all
+ necessary entities in a single query or criteria,
+ you can temporarily change the session default to load
+ entities as read-only before the query is executed.
+ Then you can explicitly initialize proxies and collections
+ before restoring the session default.
+ </para>
+
+ <programlisting role="Java">
+Session session = factory.openSession();
+Transaction tx = session.beginTransaction();
+
+setDefaultReadOnly( true );
+Contract contract =
+ ( Contract ) session.createQuery(
+ "from Contract where customerName = 'Sherman'" )
+ .uniqueResult();
+Hibernate.initialize( contract.getPlan() );
+Hibernate.initialize( contract.getVariations() );
+Hibernate.initialize( contract.getNotes() );
+setDefaultReadOnly( false );
+...
+tx.commit();
+session.close();
+
+</programlisting>
+
+ <para>
+ If Session.isDefaultReadOnly() returns true, then you can
+ use Query.setReadOnly( false ) and Criteria.setReadOnly( false )
+ to override this session setting and load entities that are
+ not read-only.
+ </para>
+
+ </section>
+
+ <section id="readonly-api-entity">
+ <title>Making a persistent entity read-only</title>
+ <note>
+ <para>
+ Persistent entities of immutable classes are automatically
+ made read-only.
+ </para>
+ </note>
+
+ <para>
+ To make a persistent entity or proxy read-only, call:
+ </para>
+ <programlisting>Session.setReadOnly(entityOrProxy, true)</programlisting>
+
+ <para>
+ To change a read-only entity or proxy of a mutable class so
+ it is no longer read-only, call:
+ </para>
+ <programlisting>Session.setReadOnly(entityOrProxy, false)</programlisting>
+
+ <important>
+ <para>
+ When a read-only entity or proxy is changed so it is no longer
+ read-only, Hibernate assumes that the current state of the
+ read-only entity is consistent with its database representation.
+ If this is not true, then any non-flushed changes made before
+ or while the entity was read-only, will be ignored.
+ </para>
+ </important>
+
+ <para>
+ To throw away non-flushed changes and make the persistent entity
+ consistent with its database representation, call:
+ </para>
+ <programlisting role="Java">session.refresh( entity );</programlisting>
+
+ <para>
+ To flush changes made before or while the entity
+ was read-only and make the database representation
+ consistent with the current state of the persistent
+ entity:
+ </para>
+<programlisting role="Java">
+// evict the read-only entity so it is detached
+session.evict( entity );
+
+// make the detached entity (with the non-flushed changes) persistent
+session.update( entity );
+
+// now entity is no longer read-only and its changes can be flushed
+s.flush();
+</programlisting>
+ </section>
+ </section>
+
+ <section id="readonly-proptypes">
+ <title>Read-only affect on property type</title>
+
+ <para>
+ The following table summarizes how different property types are
+ affected by making an entity read-only.
+ </para>
+
+ <table frame="topbot" id="readonly-proptype-summary">
+ <title>Affect of read-only entity on property types</title>
+ <tgroup cols="2">
+ <colspec colwidth="1*"/>
+ <colspec colwidth="1*"/>
+ <thead>
+ <row>
+ <entry>Property/Association Type</entry>
+ <entry>Changes flushed to DB?</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ Simple
+ <para>
+ (<xref linkend="readonly-proptypes-simple"/>)
+ </para>
+ </entry>
+ <entry>no*</entry>
+ </row>
+ <row>
+ <entry>
+ <para>Unidirectional one-to-one</para>
+ <para>Unidirectional many-to-one</para>
+ <para>
+ (<xref linkend="readonly-proptypes-singleended-unidir"/>)
+ </para>
+ </entry>
+
+ <entry>
+ <para>no*</para>
+ <para>no*</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>Unidirectional one-to-many</para>
+ <para>Unidirectional many-to-many</para>
+ <para>
+ (<xref linkend="readonly-proptypes-manyended-unidir"/>)
+ </para>
+ </entry>
+ <entry>
+ <para>yes</para>
+ <para>yes</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>Bidirectional one-to-one</para>
+ <para>
+ (<xref linkend="readonly-proptypes-onetoone-bidir"/>)
+ </para>
+ </entry>
+ <entry>only if the owning entity is not read-only*</entry>
+ </row>
+ <row>
+ <entry>
+ <para>Bidirectional one-to-many/many-to-one</para>
+ <para>inverse collection</para>
+ <para>non-inverse collection</para>
+ <para>
+ (<xref linkend="readonly-proptypes-onetomany-manytoone"/>)
+ </para>
+ </entry>
+ <entry>
+ <para> </para>
+ <para>only added/removed entities that are not read-only*</para>
+ <para>yes</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>Bidirectional many-to-many</para>
+ <para>
+ (<xref linkend="readonly-proptypes-manytomany-bidir"/>)
+ </para>
+ </entry>
+ <entry>yes</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <para>
+ * Behavior is different when the entity having the property/association
+ is read-only, compared to when it is not read-only.
+ </para>
+
+ <section id="readonly-proptypes-simple">
+ <title>Simple properties</title>
+
+ <para>
+ When a persistent object is read-only, Hibernate does not
+ dirty-check simple properties.
+ </para>
+
+ <para>
+ Hibernate will not synchronize simple property state changes
+ to the database. If you have automatic versioning, Hibernate
+ will not increment the version if any simple properties change.
+ </para>
+
+ <programlisting role="Java">
+Session session = factory.openSession();
+Transaction tx = session.beginTransaction();
+
+// get a contract and make it read-only
+Contract contract = ( Contract ) session.get( Contract.class, contractId );
+session.setReadOnly( contract, true );
+
+// contract.getCustomerName() is "Sherman"
+contract.setCustomerName( "Yogi" );
+tx.commit();
+
+tx = session.beginTransaction();
+
+contract = ( Contract ) session.get( Contract.class, contractId );
+// contract.getCustomerName() is still "Sherman"
+...
+tx.commit();
+session.close();
+ </programlisting>
+
+ </section>
+
+ <section id="readonly-prop-types-unidir">
+ <title>Unidirectional associations</title>
+
+ <section id="readonly-proptypes-singleended-unidir">
+ <title>Unidirectional one-to-one and many-to-one</title>
+
+ <para>
+ Hibernate treats unidirectional one-to-one and many-to-one
+ associations in the same way when the owning entity is
+ read-only.
+ </para>
+
+ <para>
+ We use the term <emphasis>unidirectional single-ended
+ association</emphasis> when referring to functionality
+ that is common to unidirectional one-to-one and many-to-one
+ associations.
+ </para>
+
+ <para>
+ Hibernate does not dirty-check unidirectional single-ended
+ associations when the owning entity is read-only.
+ </para>
+
+ <para>
+ If you change a read-only entity's reference to a
+ unidirectional single-ended association to null,
+ or to refer to a different entity, that change
+ will not be flushed to the database.
+ </para>
+
+ <note>
+ <para>
+ If an entity is of an immutable class,
+ then its references to unidirectional single-ended
+ associations must be assigned when that
+ entity is first created. Because the entity is
+ automatically made read-only, these references can
+ not be updated.
+ </para>
+ </note>
+
+ <para>
+ If automatic versioning is used, Hibernate will not
+ increment the version due to local changes to
+ unidirectional single-ended associations.
+ </para>
+
+ <para>
+ In the following examples, Contract has a unidirectional
+ many-to-one association with Plan. Contract cascades save and
+ update operations to the association.
+ </para>
+
+ <para>
+ The following shows that changing a read-only entity's
+ many-to-one association reference to null has no effect
+ on the entity's database representation.
+ </para>
+
+<programlisting role="Java">// get a contract with an existing plan;
+// make the contract read-only and set its plan to null
+tx = session.beginTransaction();
+Contract contract = ( Contract ) session.get( Contract.class, contractId );
+session.setReadOnly( contract, true );
+contract.setPlan( null );
+tx.commit();
+
+// get the same contract
+tx = session.beginTransaction();
+contract = ( Contract ) session.get( Contract.class, contractId );
+
+// contract.getPlan() still refers to the original plan;
+
+tx.commit();
+session.close();</programlisting>
+
+ <para>
+ The following shows that, even though
+ an update to a read-only entity's many-to-one
+ association has no affect on the entity's
+ database representation, flush still cascades
+ the save-update operation to the locally
+ changed association.
+ </para>
+
+<programlisting role="Java">// get a contract with an existing plan;
+// make the contract read-only and change to a new plan
+tx = session.beginTransaction();
+Contract contract = ( Contract ) session.get( Contract.class, contractId );
+session.setReadOnly( contract, true );
+Plan newPlan = new Plan( "new plan"
+contract.setPlan( newPlan);
+tx.commit();
+
+// get the same contract
+tx = session.beginTransaction();
+contract = ( Contract ) session.get( Contract.class, contractId );
+newPlan = ( Contract ) session.get( Plan.class, newPlan.getId() );
+
+// contract.getPlan() still refers to the original plan;
+// newPlan is non-null because it was persisted when
+// the previous transaction was committed;
+
+tx.commit();
+session.close();</programlisting>
+
+ </section>
+
+ <section id="readonly-proptypes-manyended-unidir">
+ <title>Unidirectional one-to-many and many-to-many</title>
+
+ <para>
+ Hibernate treats unidirectional one-to-many
+ and many-to-many associations owned by a read-only
+ entity the same as when owned by an entity that is not
+ read-only.
+ </para>
+
+ <para>
+ Hibernate dirty-checks unidirectional one-to-many and
+ many-to-many associations;
+ </para>
+
+ <para>
+ The collection can contain entities that
+ are read-only, as well as entities
+ that are not read-only.
+ </para>
+
+ <para>
+ Entities can be added and removed from the
+ collection; changes are flushed to the database.
+ </para>
+
+ <para>
+ If automatic versioning is used, Hibernate will
+ update the version due to changes in the collection
+ if they dirty the owning entity.
+ </para>
+
+ </section>
+
+ </section>
+
+ <section id="readonly-proptypes-bidir">
+ <title>Bidirectional associations</title>
+
+ <section id="readonly-proptypes-onetoone-bidir">
+ <title>Bidirectional one-to-one</title>
+
+ <para>
+ If a read-only entity owns a bidirectional
+ one-to-one association:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ Hibernate does not dirty-check the association.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ updates that change the association reference
+ to null or to refer to a different entity
+ will not be flushed to the database.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ If automatic versioning is used, Hibernate will not
+ increment the version due to local changes to
+ the association.
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <note>
+ <para>
+ If an entity is of an immutable class,
+ and it owns a bidirectional one-to-one
+ association, then its reference must be
+ assigned when that entity is first created.
+ Because the entity is automatically made
+ read-only, these references cannot be updated.
+ </para>
+ </note>
+
+ <para>
+ When the owner is not read-only, Hibernate treats
+ an association with a read-only entity the same
+ as when the association is with an entity that is
+ not read-only.
+ </para>
+
+ </section>
+
+ <section id="readonly-proptypes-onetomany-manytoone">
+ <title>Bidirectional one-to-many/many-to-one</title>
+
+ <para>
+ A read-only entity has no impact on a bidirectional
+ one-to-many/many-to-one association if:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ the read-only entity is on the one-to-many side
+ using an inverse collection;
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ the read-only entity is on the one-to-many side
+ using a non-inverse collection;
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ the one-to-many side uses a non-inverse collection
+ that contains the read-only entity
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ When the one-to-many side uses an inverse collection:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ a read-only entity can only be added to the collection
+ when it is created;
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ a read-only entity can only be removed from the
+ collection by an orphan delete or by explicitly
+ deleting the entity.
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ </section>
+
+ <section id="readonly-proptypes-manytomany-bidir">
+ <title>Bidirectional many-to-many</title>
+ <para>
+ Hibernate treats bidirectional many-to-many
+ associations owned by a read-only entity the
+ same as when owned by an entity that is not
+ read-only.
+ </para>
+
+ <para>
+ Hibernate dirty-checks bidirectional many-to-many
+ associations.
+ </para>
+
+ <para>
+ The collection on either side of the association
+ can contain entities that are read-only, as well
+ as entities that are not read-only.
+ </para>
+
+ <para>
+ Entities are added and removed from both sides
+ of the collection; changes are flushed to the
+ database.
+ </para>
+
+ <para>
+ If automatic versioning is used, Hibernate will
+ update the version due to changes in both sides of
+ the collection if they dirty the entity owning the
+ respective collections.
+ </para>
+
+ </section>
+
+ </section>
+ </section>
+</chapter>
14 years, 8 months
Hibernate SVN: r19107 - core/trunk/parent.
by hibernate-commits@lists.jboss.org
Author: steve.ebersole(a)jboss.com
Date: 2010-03-24 13:14:35 -0400 (Wed, 24 Mar 2010)
New Revision: 19107
Modified:
core/trunk/parent/pom.xml
Log:
HHH-5035 - upgrade to jdocbook 2.2.3
Modified: core/trunk/parent/pom.xml
===================================================================
--- core/trunk/parent/pom.xml 2010-03-24 16:53:16 UTC (rev 19106)
+++ core/trunk/parent/pom.xml 2010-03-24 17:14:35 UTC (rev 19107)
@@ -195,7 +195,7 @@
<plugin>
<groupId>org.jboss.maven.plugins</groupId>
<artifactId>maven-jdocbook-plugin</artifactId>
- <version>2.2.2</version>
+ <version>2.2.3</version>
<extensions>true</extensions>
<dependencies>
<dependency>
14 years, 8 months
Hibernate SVN: r19106 - validator/trunk.
by hibernate-commits@lists.jboss.org
Author: hardy.ferentschik
Date: 2010-03-24 12:53:16 -0400 (Wed, 24 Mar 2010)
New Revision: 19106
Modified:
validator/trunk/pom.xml
Log:
Modified: validator/trunk/pom.xml
===================================================================
--- validator/trunk/pom.xml 2010-03-24 16:44:33 UTC (rev 19105)
+++ validator/trunk/pom.xml 2010-03-24 16:53:16 UTC (rev 19106)
@@ -221,7 +221,7 @@
<version>2.2-beta-4</version>
<configuration>
<descriptorRefs>
- <descriptorRef>project</descriptorRef>
+ <descriptorRef>dist</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
@@ -234,6 +234,7 @@
<autoVersionSubmodules>true</autoVersionSubmodules>
<allowTimestampedSnapshots>true</allowTimestampedSnapshots>
<remoteTagging>true</remoteTagging>
+ <goal>deploy</goal>
</configuration>
</plugin>
<plugin>
14 years, 8 months
Hibernate SVN: r19105 - validator/trunk.
by hibernate-commits@lists.jboss.org
Author: hardy.ferentschik
Date: 2010-03-24 12:44:33 -0400 (Wed, 24 Mar 2010)
New Revision: 19105
Modified:
validator/trunk/pom.xml
Log:
Modified: validator/trunk/pom.xml
===================================================================
--- validator/trunk/pom.xml 2010-03-24 15:26:42 UTC (rev 19104)
+++ validator/trunk/pom.xml 2010-03-24 16:44:33 UTC (rev 19105)
@@ -234,7 +234,6 @@
<autoVersionSubmodules>true</autoVersionSubmodules>
<allowTimestampedSnapshots>true</allowTimestampedSnapshots>
<remoteTagging>true</remoteTagging>
- <goals>deploy</goals>
</configuration>
</plugin>
<plugin>
14 years, 8 months
Hibernate SVN: r19104 - in validator/trunk: hibernate-validator and 4 other directories.
by hibernate-commits@lists.jboss.org
Author: hardy.ferentschik
Date: 2010-03-24 11:26:42 -0400 (Wed, 24 Mar 2010)
New Revision: 19104
Modified:
validator/trunk/hibernate-validator-annotation-processor/pom.xml
validator/trunk/hibernate-validator-archetype/pom.xml
validator/trunk/hibernate-validator-legacy/pom.xml
validator/trunk/hibernate-validator-tck-runner/pom.xml
validator/trunk/hibernate-validator/pom.xml
validator/trunk/pom.xml
Log:
[maven-release-plugin] prepare for next development iteration
Modified: validator/trunk/hibernate-validator/pom.xml
===================================================================
--- validator/trunk/hibernate-validator/pom.xml 2010-03-24 15:26:21 UTC (rev 19103)
+++ validator/trunk/hibernate-validator/pom.xml 2010-03-24 15:26:42 UTC (rev 19104)
@@ -2,7 +2,7 @@
<parent>
<artifactId>hibernate-validator-parent</artifactId>
<groupId>org.hibernate</groupId>
- <version>4.1.0.Beta1</version>
+ <version>4.1.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
Modified: validator/trunk/hibernate-validator-annotation-processor/pom.xml
===================================================================
--- validator/trunk/hibernate-validator-annotation-processor/pom.xml 2010-03-24 15:26:21 UTC (rev 19103)
+++ validator/trunk/hibernate-validator-annotation-processor/pom.xml 2010-03-24 15:26:42 UTC (rev 19104)
@@ -4,7 +4,7 @@
<parent>
<artifactId>hibernate-validator-parent</artifactId>
<groupId>org.hibernate</groupId>
- <version>4.1.0.Beta1</version>
+ <version>4.1.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>org.hibernate</groupId>
Modified: validator/trunk/hibernate-validator-archetype/pom.xml
===================================================================
--- validator/trunk/hibernate-validator-archetype/pom.xml 2010-03-24 15:26:21 UTC (rev 19103)
+++ validator/trunk/hibernate-validator-archetype/pom.xml 2010-03-24 15:26:42 UTC (rev 19104)
@@ -4,7 +4,7 @@
<parent>
<artifactId>hibernate-validator-parent</artifactId>
<groupId>org.hibernate</groupId>
- <version>4.1.0.Beta1</version>
+ <version>4.1.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>org.hibernate</groupId>
Modified: validator/trunk/hibernate-validator-legacy/pom.xml
===================================================================
--- validator/trunk/hibernate-validator-legacy/pom.xml 2010-03-24 15:26:21 UTC (rev 19103)
+++ validator/trunk/hibernate-validator-legacy/pom.xml 2010-03-24 15:26:42 UTC (rev 19104)
@@ -4,13 +4,13 @@
<parent>
<artifactId>hibernate-validator-parent</artifactId>
<groupId>org.hibernate</groupId>
- <version>4.1.0.Beta1</version>
+ <version>4.1.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>hibernate-validator-legacy</artifactId>
<packaging>jar</packaging>
<name>Hibernate Validator Legacy</name>
- <version>4.1.0.Beta1</version>
+ <version>3.1.0.GA</version>
<url>http://validator.hibernate.org</url>
<licenses>
<license>
Modified: validator/trunk/hibernate-validator-tck-runner/pom.xml
===================================================================
--- validator/trunk/hibernate-validator-tck-runner/pom.xml 2010-03-24 15:26:21 UTC (rev 19103)
+++ validator/trunk/hibernate-validator-tck-runner/pom.xml 2010-03-24 15:26:42 UTC (rev 19104)
@@ -3,7 +3,7 @@
<parent>
<artifactId>hibernate-validator-parent</artifactId>
<groupId>org.hibernate</groupId>
- <version>4.1.0.Beta1</version>
+ <version>4.1.0-SNAPSHOT</version>
</parent>
<artifactId>hibernate-validator-tck-runner</artifactId>
<name>Hibernate Validator TCK Runner</name>
Modified: validator/trunk/pom.xml
===================================================================
--- validator/trunk/pom.xml 2010-03-24 15:26:21 UTC (rev 19103)
+++ validator/trunk/pom.xml 2010-03-24 15:26:42 UTC (rev 19104)
@@ -3,7 +3,7 @@
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator-parent</artifactId>
<packaging>pom</packaging>
- <version>4.1.0.Beta1</version>
+ <version>4.1.0-SNAPSHOT</version>
<name>Hibernate Validator Aggregator</name>
<url>http://validator.hibernate.org</url>
@@ -311,8 +311,8 @@
</licenses>
<scm>
- <connection>scm:svn:https://svn.jboss.org/repos/hibernate/validator/tags/v4_1_0_Beta1</connection>
- <url>http://fisheye.jboss.org/browse/Hibernate/validator/tags/v4_1_0_Beta1</url>
+ <connection>scm:svn:https://svn.jboss.org/repos/hibernate/validator/trunk</connection>
+ <url>http://fisheye.jboss.org/browse/Hibernate/validator/trunk</url>
</scm>
<distributionManagement>
14 years, 8 months
Hibernate SVN: r19103 - validator/tags.
by hibernate-commits@lists.jboss.org
Author: hardy.ferentschik
Date: 2010-03-24 11:26:21 -0400 (Wed, 24 Mar 2010)
New Revision: 19103
Added:
validator/tags/v4_1_0_Beta1/
Log:
[maven-scm] copy for tag v4_1_0_Beta1
Copied: validator/tags/v4_1_0_Beta1 (from rev 19102, validator/trunk)
14 years, 8 months
Hibernate SVN: r19102 - in validator/trunk: hibernate-validator and 4 other directories.
by hibernate-commits@lists.jboss.org
Author: hardy.ferentschik
Date: 2010-03-24 11:25:45 -0400 (Wed, 24 Mar 2010)
New Revision: 19102
Modified:
validator/trunk/hibernate-validator-annotation-processor/pom.xml
validator/trunk/hibernate-validator-archetype/pom.xml
validator/trunk/hibernate-validator-legacy/pom.xml
validator/trunk/hibernate-validator-tck-runner/pom.xml
validator/trunk/hibernate-validator/pom.xml
validator/trunk/pom.xml
Log:
[maven-release-plugin] prepare release v4_1_0_Beta1
Modified: validator/trunk/hibernate-validator/pom.xml
===================================================================
--- validator/trunk/hibernate-validator/pom.xml 2010-03-24 15:19:32 UTC (rev 19101)
+++ validator/trunk/hibernate-validator/pom.xml 2010-03-24 15:25:45 UTC (rev 19102)
@@ -2,7 +2,7 @@
<parent>
<artifactId>hibernate-validator-parent</artifactId>
<groupId>org.hibernate</groupId>
- <version>4.1.0-SNAPSHOT</version>
+ <version>4.1.0.Beta1</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
Modified: validator/trunk/hibernate-validator-annotation-processor/pom.xml
===================================================================
--- validator/trunk/hibernate-validator-annotation-processor/pom.xml 2010-03-24 15:19:32 UTC (rev 19101)
+++ validator/trunk/hibernate-validator-annotation-processor/pom.xml 2010-03-24 15:25:45 UTC (rev 19102)
@@ -4,7 +4,7 @@
<parent>
<artifactId>hibernate-validator-parent</artifactId>
<groupId>org.hibernate</groupId>
- <version>4.1.0-SNAPSHOT</version>
+ <version>4.1.0.Beta1</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>org.hibernate</groupId>
Modified: validator/trunk/hibernate-validator-archetype/pom.xml
===================================================================
--- validator/trunk/hibernate-validator-archetype/pom.xml 2010-03-24 15:19:32 UTC (rev 19101)
+++ validator/trunk/hibernate-validator-archetype/pom.xml 2010-03-24 15:25:45 UTC (rev 19102)
@@ -4,7 +4,7 @@
<parent>
<artifactId>hibernate-validator-parent</artifactId>
<groupId>org.hibernate</groupId>
- <version>4.1.0-SNAPSHOT</version>
+ <version>4.1.0.Beta1</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>org.hibernate</groupId>
Modified: validator/trunk/hibernate-validator-legacy/pom.xml
===================================================================
--- validator/trunk/hibernate-validator-legacy/pom.xml 2010-03-24 15:19:32 UTC (rev 19101)
+++ validator/trunk/hibernate-validator-legacy/pom.xml 2010-03-24 15:25:45 UTC (rev 19102)
@@ -4,13 +4,13 @@
<parent>
<artifactId>hibernate-validator-parent</artifactId>
<groupId>org.hibernate</groupId>
- <version>4.1.0-SNAPSHOT</version>
+ <version>4.1.0.Beta1</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>hibernate-validator-legacy</artifactId>
<packaging>jar</packaging>
<name>Hibernate Validator Legacy</name>
- <version>3.1.0.GA</version>
+ <version>4.1.0.Beta1</version>
<url>http://validator.hibernate.org</url>
<licenses>
<license>
Modified: validator/trunk/hibernate-validator-tck-runner/pom.xml
===================================================================
--- validator/trunk/hibernate-validator-tck-runner/pom.xml 2010-03-24 15:19:32 UTC (rev 19101)
+++ validator/trunk/hibernate-validator-tck-runner/pom.xml 2010-03-24 15:25:45 UTC (rev 19102)
@@ -3,7 +3,7 @@
<parent>
<artifactId>hibernate-validator-parent</artifactId>
<groupId>org.hibernate</groupId>
- <version>4.1.0-SNAPSHOT</version>
+ <version>4.1.0.Beta1</version>
</parent>
<artifactId>hibernate-validator-tck-runner</artifactId>
<name>Hibernate Validator TCK Runner</name>
Modified: validator/trunk/pom.xml
===================================================================
--- validator/trunk/pom.xml 2010-03-24 15:19:32 UTC (rev 19101)
+++ validator/trunk/pom.xml 2010-03-24 15:25:45 UTC (rev 19102)
@@ -3,7 +3,7 @@
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator-parent</artifactId>
<packaging>pom</packaging>
- <version>4.1.0-SNAPSHOT</version>
+ <version>4.1.0.Beta1</version>
<name>Hibernate Validator Aggregator</name>
<url>http://validator.hibernate.org</url>
@@ -311,8 +311,8 @@
</licenses>
<scm>
- <connection>scm:svn:https://svn.jboss.org/repos/hibernate/validator/trunk</connection>
- <url>http://fisheye.jboss.org/browse/Hibernate/validator/trunk</url>
+ <connection>scm:svn:https://svn.jboss.org/repos/hibernate/validator/tags/v4_1_0_Beta1</connection>
+ <url>http://fisheye.jboss.org/browse/Hibernate/validator/tags/v4_1_0_Beta1</url>
</scm>
<distributionManagement>
14 years, 8 months
Hibernate SVN: r19100 - validator/tags.
by hibernate-commits@lists.jboss.org
Author: hardy.ferentschik
Date: 2010-03-24 11:09:47 -0400 (Wed, 24 Mar 2010)
New Revision: 19100
Removed:
validator/tags/v4_1_0_Beta1/
Log:
deleted wrong release tag
14 years, 8 months