Author: steve.ebersole(a)jboss.com
Date: 2007-01-19 07:51:31 -0500 (Fri, 19 Jan 2007)
New Revision: 11060
Added:
trunk/Hibernate3/src/org/hibernate/engine/ValueInclusion.java
trunk/Hibernate3/test/org/hibernate/test/generated/ComponentOwner.hbm.xml
trunk/Hibernate3/test/org/hibernate/test/generated/ComponentOwner.java
trunk/Hibernate3/test/org/hibernate/test/generated/PartiallyGeneratedComponentTest.java
Modified:
trunk/Hibernate3/src/org/hibernate/id/SelectGenerator.java
trunk/Hibernate3/src/org/hibernate/mapping/PropertyGeneration.java
trunk/Hibernate3/src/org/hibernate/persister/entity/AbstractEntityPersister.java
trunk/Hibernate3/src/org/hibernate/persister/entity/EntityPersister.java
trunk/Hibernate3/src/org/hibernate/tuple/entity/EntityMetamodel.java
trunk/Hibernate3/test/org/hibernate/test/generated/GeneratedPropertySuite.java
trunk/Hibernate3/test/org/hibernate/test/legacy/CustomPersister.java
Log:
HHH-1471 : components + partial generation
Added: trunk/Hibernate3/src/org/hibernate/engine/ValueInclusion.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/engine/ValueInclusion.java
(rev 0)
+++ trunk/Hibernate3/src/org/hibernate/engine/ValueInclusion.java 2007-01-19 12:51:31 UTC
(rev 11060)
@@ -0,0 +1,51 @@
+package org.hibernate.engine;
+
+import java.io.Serializable;
+import java.io.ObjectStreamException;
+import java.io.StreamCorruptedException;
+
+/**
+ * An enum of the different ways a value might be "included".
+ * <p/>
+ * This is really an expanded true/false notion with "PARTIAL" being the
+ * expansion. PARTIAL deals with components in the cases where
+ * parts of the referenced component might define inclusion, but the
+ * component overall does not.
+ *
+ * @author Steve Ebersole
+ */
+public class ValueInclusion implements Serializable {
+
+ public static final ValueInclusion NONE = new ValueInclusion( "none" );
+ public static final ValueInclusion FULL = new ValueInclusion( "full" );
+ public static final ValueInclusion PARTIAL = new ValueInclusion( "partial" );
+
+ private final String name;
+
+ public ValueInclusion(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String toString() {
+ return "ValueInclusion[" + name + "]";
+ }
+
+ private Object readResolve() throws ObjectStreamException {
+ if ( name.equals( NONE.name ) ) {
+ return NONE;
+ }
+ else if ( name.equals( FULL.name ) ) {
+ return FULL;
+ }
+ else if ( name.equals( PARTIAL.name ) ) {
+ return PARTIAL;
+ }
+ else {
+ throw new StreamCorruptedException( "unrecognized value inclusion [" + name
+ "]" );
+ }
+ }
+}
Modified: trunk/Hibernate3/src/org/hibernate/id/SelectGenerator.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/id/SelectGenerator.java 2007-01-18 01:51:13 UTC
(rev 11059)
+++ trunk/Hibernate3/src/org/hibernate/id/SelectGenerator.java 2007-01-19 12:51:31 UTC
(rev 11060)
@@ -14,6 +14,7 @@
import org.hibernate.id.insert.AbstractSelectingDelegate;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.SessionImplementor;
+import org.hibernate.engine.ValueInclusion;
import org.hibernate.type.Type;
/**
@@ -57,7 +58,8 @@
"natural-id properties; need to specify [key] in generator parameters"
);
}
- if ( persister.getPropertyInsertGeneration() [ naturalIdPropertyIndices[0] ] ) {
+ ValueInclusion inclusion = persister.getPropertyInsertGenerationInclusions() [
naturalIdPropertyIndices[0] ];
+ if ( inclusion != ValueInclusion.NONE ) {
throw new IdentifierGenerationException(
"natural-id also defined as insert-generated; need to specify [key] " +
"in generator parameters"
Modified: trunk/Hibernate3/src/org/hibernate/mapping/PropertyGeneration.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/mapping/PropertyGeneration.java 2007-01-18 01:51:13
UTC (rev 11059)
+++ trunk/Hibernate3/src/org/hibernate/mapping/PropertyGeneration.java 2007-01-19 12:51:31
UTC (rev 11060)
@@ -6,7 +6,7 @@
* Indicates whether given properties are generated by the database and, if
* so, at what time(s) they are generated.
*
- * @author <a href="mailto:steve@hibernate.org">Steve Ebersole
</a>
+ * @author Steve Ebersole
*/
public class PropertyGeneration implements Serializable {
Modified:
trunk/Hibernate3/src/org/hibernate/persister/entity/AbstractEntityPersister.java
===================================================================
---
trunk/Hibernate3/src/org/hibernate/persister/entity/AbstractEntityPersister.java 2007-01-18
01:51:13 UTC (rev 11059)
+++
trunk/Hibernate3/src/org/hibernate/persister/entity/AbstractEntityPersister.java 2007-01-19
12:51:31 UTC (rev 11060)
@@ -44,6 +44,7 @@
import org.hibernate.engine.Versioning;
import org.hibernate.engine.ExecuteUpdateResultCheckStyle;
import org.hibernate.engine.EntityKey;
+import org.hibernate.engine.ValueInclusion;
import org.hibernate.exception.JDBCExceptionHelper;
import org.hibernate.id.IdentifierGenerator;
import org.hibernate.id.PostInsertIdentifierGenerator;
@@ -301,9 +302,7 @@
}
String[] result = new String[getTableSpan()];
result[0] = sqlUpdateByRowIdString;
- for ( int i = 1; i < getTableSpan(); i++ ) {
- result[i] = sqlUpdateStrings[i];
- }
+ System.arraycopy( sqlUpdateStrings, 1, result, 1, getTableSpan() );
return result;
}
@@ -345,6 +344,8 @@
/**
* The query that inserts a row, letting the database generate an id
+ *
+ * @return The IDENTITY-based insertion query.
*/
protected String getSQLIdentityInsertString() {
return sqlIdentityInsertString;
@@ -379,7 +380,15 @@
}
/**
- * Decide which tables need to be updated
+ * Decide which tables need to be updated.
+ * <p/>
+ * The return here is an array of boolean values with each index corresponding
+ * to a given table in the scope of this persister.
+ *
+ * @param dirtyProperties The indices of all the entity properties considered dirty.
+ * @param hasDirtyCollection Whether any collections owned by the entity which were
considered dirty.
+ *
+ * @return Array of booleans indicating which table require updating.
*/
protected boolean[] getTableUpdateNeeded(final int[] dirtyProperties, boolean
hasDirtyCollection) {
@@ -583,8 +592,8 @@
names.add( prop.getName() );
classes.add( prop.getPersistentClass().getEntityName() );
boolean isDefinedBySubclass = !thisClassProperties.contains( prop );
- definedBySubclass.add( new Boolean(isDefinedBySubclass) );
- propNullables.add( new Boolean( prop.isOptional() || isDefinedBySubclass) ); //TODO:
is this completely correct?
+ definedBySubclass.add( Boolean.valueOf( isDefinedBySubclass ) );
+ propNullables.add( Boolean.valueOf( prop.isOptional() || isDefinedBySubclass ) );
//TODO: is this completely correct?
types.add( prop.getType() );
Iterator colIter = prop.getColumnIterator();
@@ -593,7 +602,7 @@
int[] colnos = new int[prop.getColumnSpan()];
int[] formnos = new int[prop.getColumnSpan()];
int l = 0;
- Boolean lazy = new Boolean( prop.isLazy() && lazyAvailable );
+ Boolean lazy = Boolean.valueOf( prop.isLazy() && lazyAvailable );
while ( colIter.hasNext() ) {
Selectable thing = ( Selectable ) colIter.next();
if ( thing.isFormula() ) {
@@ -614,7 +623,7 @@
cols[l] = colName;
aliases.add( thing.getAlias( factory.getDialect(), prop.getValue().getTable() ) );
columnsLazy.add( lazy );
- columnSelectables.add( new Boolean( prop.isSelectable() ) );
+ columnSelectables.add( Boolean.valueOf( prop.isSelectable() ) );
}
l++;
}
@@ -1066,14 +1075,14 @@
}
protected String generateInsertGeneratedValuesSelectString() {
- return generateGeneratedValuesSelectString( getPropertyInsertGeneration() );
+ return generateGeneratedValuesSelectString( getPropertyInsertGenerationInclusions() );
}
protected String generateUpdateGeneratedValuesSelectString() {
- return generateGeneratedValuesSelectString( getPropertyUpdateGeneration() );
+ return generateGeneratedValuesSelectString( getPropertyUpdateGenerationInclusions() );
}
- private String generateGeneratedValuesSelectString(boolean[] inclusions) {
+ private String generateGeneratedValuesSelectString(ValueInclusion[] inclusions) {
Select select = new Select( getFactory().getDialect() );
if ( getFactory().getSettings().isCommentsEnabled() ) {
@@ -1082,6 +1091,9 @@
String[] aliasedIdColumns = StringHelper.qualify( getRootAlias(),
getIdentifierColumnNames() );
+ // Here we render the select column list based on the properties defined as being
generated.
+ // For partial component generation, we currently just re-select the whole component
+ // rather than trying to handle the individual generated portions.
String selectClause = concretePropertySelectFragment( getRootAlias(), inclusions );
selectClause = selectClause.substring( 2 );
@@ -1101,22 +1113,52 @@
.toStatementString();
}
- protected String concretePropertySelectFragment(String alias, boolean[] includeProperty)
{
+ protected static interface InclusionChecker {
+ public boolean includeProperty(int propertyNumber);
+ }
+
+ protected String concretePropertySelectFragment(String alias, final ValueInclusion[]
inclusions) {
+ return concretePropertySelectFragment(
+ alias,
+ new InclusionChecker() {
+ // TODO : currently we really do not handle ValueInclusion.PARTIAL...
+ // ValueInclusion.PARTIAL would indicate parts of a component need to
+ // be included in the select; currently we then just render the entire
+ // component into the select clause in that case.
+ public boolean includeProperty(int propertyNumber) {
+ return inclusions[propertyNumber] != ValueInclusion.NONE;
+ }
+ }
+ );
+ }
+
+ protected String concretePropertySelectFragment(String alias, final boolean[]
includeProperty) {
+ return concretePropertySelectFragment(
+ alias,
+ new InclusionChecker() {
+ public boolean includeProperty(int propertyNumber) {
+ return includeProperty[propertyNumber];
+ }
+ }
+ );
+ }
+
+ protected String concretePropertySelectFragment(String alias, InclusionChecker
inclusionChecker) {
int propertyCount = getPropertyNames().length;
int[] propertyTableNumbers = getPropertyTableNumbersInSelect();
SelectFragment frag = new SelectFragment();
for ( int i = 0; i < propertyCount; i++ ) {
- if ( includeProperty[i] ) { //ie. updateable, not a formula
+ if ( inclusionChecker.includeProperty( i ) ) {
frag.addColumns(
generateTableAlias( alias, propertyTableNumbers[i] ),
propertyColumnNames[i],
propertyColumnAliases[i]
- );
+ );
frag.addFormulas(
generateTableAlias( alias, propertyTableNumbers[i] ),
propertyColumnFormulaTemplates[i],
propertyColumnAliases[i]
- );
+ );
}
}
return frag.toFragmentString();
@@ -1810,9 +1852,8 @@
}
private boolean checkVersion(final boolean[] includeProperty) {
- boolean checkVersion = includeProperty[ getVersionProperty() ] ||
- entityMetamodel.getPropertyUpdateGeneration()[ getVersionProperty() ];
- return checkVersion;
+ return includeProperty[ getVersionProperty() ] ||
+ entityMetamodel.getPropertyUpdateGenerationInclusions()[ getVersionProperty() ] !=
ValueInclusion.NONE;
}
protected String generateInsertString(boolean[] includeProperty, int j) {
@@ -3430,15 +3471,15 @@
}
public boolean hasInsertGeneratedProperties() {
- return !ArrayHelper.isAllFalse( getPropertyInsertGeneration() );
+ return entityMetamodel.hasInsertGeneratedValues();
}
public boolean hasUpdateGeneratedProperties() {
- return !ArrayHelper.isAllFalse( getPropertyUpdateGeneration() );
+ return entityMetamodel.hasUpdateGeneratedValues();
}
public boolean isVersionPropertyGenerated() {
- return isVersioned() && getPropertyUpdateGeneration() [ getVersionProperty()
];
+ return isVersioned() && ( getPropertyUpdateGenerationInclusions() [
getVersionProperty() ] != ValueInclusion.NONE );
}
public boolean isVersionPropertyInsertable() {
@@ -3477,12 +3518,12 @@
return entityMetamodel.getPropertyInsertability();
}
- public boolean[] getPropertyInsertGeneration() {
- return entityMetamodel.getPropertyInsertGeneration();
+ public ValueInclusion[] getPropertyInsertGenerationInclusions() {
+ return entityMetamodel.getPropertyInsertGenerationInclusions();
}
- public boolean[] getPropertyUpdateGeneration() {
- return entityMetamodel.getPropertyUpdateGeneration();
+ public ValueInclusion[] getPropertyUpdateGenerationInclusions() {
+ return entityMetamodel.getPropertyUpdateGenerationInclusions();
}
public boolean[] getPropertyNullability() {
@@ -3625,14 +3666,14 @@
if ( !hasInsertGeneratedProperties() ) {
throw new AssertionFailure("no insert-generated properties");
}
- processGeneratedProperties( id, entity, state, session,
sqlInsertGeneratedValuesSelectString, getPropertyInsertGeneration() );
+ processGeneratedProperties( id, entity, state, session,
sqlInsertGeneratedValuesSelectString, getPropertyInsertGenerationInclusions() );
}
public void processUpdateGeneratedProperties(Serializable id, Object entity, Object[]
state, SessionImplementor session) {
if ( !hasInsertGeneratedProperties() ) {
throw new AssertionFailure("no update-generated properties");
}
- processGeneratedProperties( id, entity, state, session,
sqlUpdateGeneratedValuesSelectString, getPropertyUpdateGeneration() );
+ processGeneratedProperties( id, entity, state, session,
sqlUpdateGeneratedValuesSelectString, getPropertyUpdateGenerationInclusions() );
}
private void processGeneratedProperties(
@@ -3641,7 +3682,7 @@
Object[] state,
SessionImplementor session,
String selectionSQL,
- boolean[] included ) {
+ ValueInclusion[] includeds) {
session.getBatcher().executeBatch(); //force immediate execution of the insert
@@ -3658,8 +3699,9 @@
);
}
for ( int i = 0; i < getPropertySpan(); i++ ) {
- if ( included[i] ) {
- state[i] = getPropertyTypes()[i].hydrate( rs, getPropertyAliases( "", i
), session, entity );
+ if ( includeds[i] != ValueInclusion.NONE ) {
+ Object hydratedState = getPropertyTypes()[i].hydrate( rs, getPropertyAliases(
"", i ), session, entity );
+ state[i] = getPropertyTypes()[i].resolve( hydratedState, session, entity );
setPropertyValue( entity, i, state[i], session.getEntityMode() );
}
}
Modified: trunk/Hibernate3/src/org/hibernate/persister/entity/EntityPersister.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/persister/entity/EntityPersister.java 2007-01-18
01:51:13 UTC (rev 11059)
+++ trunk/Hibernate3/src/org/hibernate/persister/entity/EntityPersister.java 2007-01-19
12:51:31 UTC (rev 11060)
@@ -15,6 +15,7 @@
import org.hibernate.engine.CascadeStyle;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.engine.SessionImplementor;
+import org.hibernate.engine.ValueInclusion;
import org.hibernate.id.IdentifierGenerator;
import org.hibernate.metadata.ClassMetadata;
import org.hibernate.type.Type;
@@ -361,12 +362,12 @@
/**
* Which of the properties of this class are database generated values on insert?
*/
- public boolean[] getPropertyInsertGeneration();
+ public ValueInclusion[] getPropertyInsertGenerationInclusions();
/**
* Which of the properties of this class are database generated values on update?
*/
- public boolean[] getPropertyUpdateGeneration();
+ public ValueInclusion[] getPropertyUpdateGenerationInclusions();
/**
* Get the "updateability" of the properties of this class
Modified: trunk/Hibernate3/src/org/hibernate/tuple/entity/EntityMetamodel.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/tuple/entity/EntityMetamodel.java 2007-01-18
01:51:13 UTC (rev 11059)
+++ trunk/Hibernate3/src/org/hibernate/tuple/entity/EntityMetamodel.java 2007-01-19
12:51:31 UTC (rev 11060)
@@ -23,9 +23,11 @@
import org.hibernate.engine.CascadeStyle;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.engine.Versioning;
+import org.hibernate.engine.ValueInclusion;
import org.hibernate.mapping.Component;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Property;
+import org.hibernate.mapping.PropertyGeneration;
import org.hibernate.type.AbstractComponentType;
import org.hibernate.type.AssociationType;
import org.hibernate.type.EntityType;
@@ -65,11 +67,13 @@
private final boolean[] nonlazyPropertyUpdateability;
private final boolean[] propertyCheckability;
private final boolean[] propertyInsertability;
- private final boolean[] propertyInsertGeneration;
- private final boolean[] propertyUpdateGeneration;
+ private final ValueInclusion[] insertInclusions;
+ private final ValueInclusion[] updateInclusions;
private final boolean[] propertyNullability;
private final boolean[] propertyVersionability;
private final CascadeStyle[] cascadeStyles;
+ private final boolean hasInsertGeneratedValues;
+ private final boolean hasUpdateGeneratedValues;
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
private final Map propertyIndexes = new HashMap();
private final boolean hasCollections;
@@ -135,8 +139,8 @@
propertyTypes = new Type[propertySpan];
propertyUpdateability = new boolean[propertySpan];
propertyInsertability = new boolean[propertySpan];
- propertyInsertGeneration = new boolean[propertySpan];
- propertyUpdateGeneration = new boolean[propertySpan];
+ insertInclusions = new ValueInclusion[propertySpan];
+ updateInclusions = new ValueInclusion[propertySpan];
nonlazyPropertyUpdateability = new boolean[propertySpan];
propertyCheckability = new boolean[propertySpan];
propertyNullability = new boolean[propertySpan];
@@ -153,6 +157,8 @@
boolean foundCollection = false;
boolean foundMutable = false;
boolean foundNonIdentifierPropertyNamedId = false;
+ boolean foundInsertGeneratedValue = false;
+ boolean foundUpdateGeneratedValue = false;
while ( iter.hasNext() ) {
Property prop = ( Property ) iter.next();
@@ -183,8 +189,8 @@
propertyNullability[i] = properties[i].isNullable();
propertyUpdateability[i] = properties[i].isUpdateable();
propertyInsertability[i] = properties[i].isInsertable();
- propertyInsertGeneration[i] = properties[i].isInsertGenerated();
- propertyUpdateGeneration[i] = properties[i].isUpdateGenerated();
+ insertInclusions[i] = determineInsertValueGenerationType( prop, properties[i] );
+ updateInclusions[i] = determineUpdateValueGenerationType( prop, properties[i] );
propertyVersionability[i] = properties[i].isVersionable();
nonlazyPropertyUpdateability[i] = properties[i].isUpdateable() && !lazy;
propertyCheckability[i] = propertyUpdateability[i] ||
@@ -209,6 +215,14 @@
foundMutable = true;
}
+ if ( insertInclusions[i] != ValueInclusion.NONE ) {
+ foundInsertGeneratedValue = true;
+ }
+
+ if ( updateInclusions[i] != ValueInclusion.NONE ) {
+ foundUpdateGeneratedValue = true;
+ }
+
mapPropertyToIndex(prop, i);
i++;
}
@@ -220,6 +234,9 @@
naturalIdPropertyNumbers = ArrayHelper.toIntArray(naturalIdNumbers);
}
+ hasInsertGeneratedValues = foundInsertGeneratedValue;
+ hasUpdateGeneratedValues = foundUpdateGeneratedValue;
+
hasCascades = foundCascade;
hasNonIdentifierPropertyNamedId = foundNonIdentifierPropertyNamedId;
versionPropertyIndex = tempVersionProperty;
@@ -232,7 +249,7 @@
// TODO: this disables laziness even in non-pojo entity modes:
!persistentClass.hasPojoRepresentation() ||
!ReflectHelper.isFinalClass( persistentClass.getProxyInterface() )
- );
+ );
mutable = persistentClass.isMutable();
if ( persistentClass.isAbstract() == null ) {
// legacy behavior (with no abstract attribute specified)
@@ -278,6 +295,62 @@
tuplizerMapping = new EntityEntityModeToTuplizerMapping( persistentClass, this );
}
+ private ValueInclusion determineInsertValueGenerationType(Property mappingProperty,
StandardProperty runtimeProperty) {
+ if ( runtimeProperty.isInsertGenerated() ) {
+ return ValueInclusion.FULL;
+ }
+ else if ( mappingProperty.getValue() instanceof Component ) {
+ if ( hasPartialInsertComponentGeneration( ( Component ) mappingProperty.getValue() ) )
{
+ return ValueInclusion.PARTIAL;
+ }
+ }
+ return ValueInclusion.NONE;
+ }
+
+ private boolean hasPartialInsertComponentGeneration(Component component) {
+ Iterator subProperties = component.getPropertyIterator();
+ while ( subProperties.hasNext() ) {
+ Property prop = ( Property ) subProperties.next();
+ if ( prop.getGeneration() == PropertyGeneration.ALWAYS || prop.getGeneration() ==
PropertyGeneration.INSERT ) {
+ return true;
+ }
+ else if ( prop.getValue() instanceof Component ) {
+ if ( hasPartialInsertComponentGeneration( ( Component ) prop.getValue() ) ) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private ValueInclusion determineUpdateValueGenerationType(Property mappingProperty,
StandardProperty runtimeProperty) {
+ if ( runtimeProperty.isUpdateGenerated() ) {
+ return ValueInclusion.FULL;
+ }
+ else if ( mappingProperty.getValue() instanceof Component ) {
+ if ( hasPartialUpdateComponentGeneration( ( Component ) mappingProperty.getValue() ) )
{
+ return ValueInclusion.PARTIAL;
+ }
+ }
+ return ValueInclusion.NONE;
+ }
+
+ private boolean hasPartialUpdateComponentGeneration(Component component) {
+ Iterator subProperties = component.getPropertyIterator();
+ while ( subProperties.hasNext() ) {
+ Property prop = ( Property ) subProperties.next();
+ if ( prop.getGeneration() == PropertyGeneration.ALWAYS ) {
+ return true;
+ }
+ else if ( prop.getValue() instanceof Component ) {
+ if ( hasPartialUpdateComponentGeneration( ( Component ) prop.getValue() ) ) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
private void mapPropertyToIndex(Property prop, int i) {
propertyIndexes.put( prop.getName(), new Integer(i) );
if ( prop.getValue() instanceof Component ) {
@@ -481,12 +554,12 @@
return propertyInsertability;
}
- public boolean[] getPropertyInsertGeneration() {
- return propertyInsertGeneration;
+ public ValueInclusion[] getPropertyInsertGenerationInclusions() {
+ return insertInclusions;
}
- public boolean[] getPropertyUpdateGeneration() {
- return propertyUpdateGeneration;
+ public ValueInclusion[] getPropertyUpdateGenerationInclusions() {
+ return updateInclusions;
}
public boolean[] getPropertyNullability() {
@@ -500,5 +573,14 @@
public CascadeStyle[] getCascadeStyles() {
return cascadeStyles;
}
+
+ public boolean hasInsertGeneratedValues() {
+ return hasInsertGeneratedValues;
+ }
+
+ public boolean hasUpdateGeneratedValues() {
+ return hasUpdateGeneratedValues;
+ }
+
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
}
Added: trunk/Hibernate3/test/org/hibernate/test/generated/ComponentOwner.hbm.xml
===================================================================
--- trunk/Hibernate3/test/org/hibernate/test/generated/ComponentOwner.hbm.xml
(rev 0)
+++ trunk/Hibernate3/test/org/hibernate/test/generated/ComponentOwner.hbm.xml 2007-01-19
12:51:31 UTC (rev 11060)
@@ -0,0 +1,38 @@
+<?xml version="1.0"?>
+<!DOCTYPE hibernate-mapping PUBLIC
+ "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
+ "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
+
+<hibernate-mapping package="org.hibernate.test.generated">
+
+ <class name="ComponentOwner" table="part_gen_comp">
+ <id name="id">
+ <generator class="increment"/>
+ </id>
+ <property name="name" />
+ <component name="component"
class="ComponentOwner$Component">
+ <property name="generated" type="int"
generated="always" column="GENED"/>
+ </component>
+ </class>
+
+ <database-object>
+ <create>
+ <![CDATA[CREATE OR REPLACE TRIGGER t_iu_part_gen_comp
+ BEFORE INSERT OR UPDATE ON part_gen_comp
+ FOR EACH ROW
+ BEGIN
+ IF INSERTING THEN
+ :new.gened := 1;
+ ELSE
+ :new.gened := :old.gened + 1;
+ END IF;
+ END;]]>
+ </create>
+ <drop>
+ <![CDATA[DROP TRIGGER t_iu_part_gen_comp]]>
+ </drop>
+ <dialect-scope name="org.hibernate.dialect.Oracle9Dialect"/>
+ <dialect-scope name="org.hibernate.dialect.OracleDialect"/>
+ </database-object>
+
+</hibernate-mapping>
\ No newline at end of file
Added: trunk/Hibernate3/test/org/hibernate/test/generated/ComponentOwner.java
===================================================================
--- trunk/Hibernate3/test/org/hibernate/test/generated/ComponentOwner.java
(rev 0)
+++ trunk/Hibernate3/test/org/hibernate/test/generated/ComponentOwner.java 2007-01-19
12:51:31 UTC (rev 11060)
@@ -0,0 +1,55 @@
+package org.hibernate.test.generated;
+
+/**
+ * {@inheritDoc}
+ *
+ * @author Steve Ebersole
+ */
+public class ComponentOwner {
+ private Long id;
+ private String name;
+ private Component component;
+
+ public ComponentOwner() {
+ }
+
+ public ComponentOwner(String name) {
+ this.name = name;
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public Component getComponent() {
+ return component;
+ }
+
+ public void setComponent(Component component) {
+ this.component = component;
+ }
+
+ public static class Component {
+ private int generated;
+
+ public int getGenerated() {
+ return generated;
+ }
+
+ public void setGenerated(int generated) {
+ this.generated = generated;
+ }
+ }
+}
Modified: trunk/Hibernate3/test/org/hibernate/test/generated/GeneratedPropertySuite.java
===================================================================
---
trunk/Hibernate3/test/org/hibernate/test/generated/GeneratedPropertySuite.java 2007-01-18
01:51:13 UTC (rev 11059)
+++
trunk/Hibernate3/test/org/hibernate/test/generated/GeneratedPropertySuite.java 2007-01-19
12:51:31 UTC (rev 11060)
@@ -14,6 +14,7 @@
suite.addTest( TimestampGeneratedValuesWithCachingTest.suite() );
suite.addTest( TriggerGeneratedValuesWithCachingTest.suite() );
suite.addTest( TriggerGeneratedValuesWithoutCachingTest.suite() );
+ suite.addTest( PartiallyGeneratedComponentTest.suite() );
return suite;
}
}
Added:
trunk/Hibernate3/test/org/hibernate/test/generated/PartiallyGeneratedComponentTest.java
===================================================================
---
trunk/Hibernate3/test/org/hibernate/test/generated/PartiallyGeneratedComponentTest.java
(rev 0)
+++
trunk/Hibernate3/test/org/hibernate/test/generated/PartiallyGeneratedComponentTest.java 2007-01-19
12:51:31 UTC (rev 11060)
@@ -0,0 +1,64 @@
+package org.hibernate.test.generated;
+
+import junit.framework.Test;
+
+import org.hibernate.junit.functional.DatabaseSpecificFunctionalTestCase;
+import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
+import org.hibernate.dialect.Dialect;
+import org.hibernate.dialect.Oracle9Dialect;
+import org.hibernate.Session;
+
+/**
+ * {@inheritDoc}
+ *
+ * @author Steve Ebersole
+ */
+public class PartiallyGeneratedComponentTest extends DatabaseSpecificFunctionalTestCase
{
+ public PartiallyGeneratedComponentTest(String string) {
+ super( string );
+ }
+
+ public String[] getMappings() {
+ return new String[] { "generated/ComponentOwner.hbm.xml" };
+ }
+
+ public static Test suite() {
+ return new FunctionalTestClassTestSuite( PartiallyGeneratedComponentTest.class );
+ }
+
+ public boolean appliesTo(Dialect dialect) {
+ return dialect instanceof Oracle9Dialect;
+ }
+
+ public void testPartialComponentGeneration() {
+ ComponentOwner owner = new ComponentOwner( "initial" );
+ Session s = openSession();
+ s.beginTransaction();
+ s.save( owner );
+ s.getTransaction().commit();
+ s.close();
+
+ assertNotNull( "expecting insert value generation", owner.getComponent() );
+ int previousValue = owner.getComponent().getGenerated();
+ assertFalse( "expecting insert value generation", 0 == previousValue );
+
+ s = openSession();
+ s.beginTransaction();
+ owner = ( ComponentOwner ) s.get( ComponentOwner.class, owner.getId() );
+ assertEquals( "expecting insert value generation", previousValue,
owner.getComponent().getGenerated() );
+ owner.setName( "subsequent" );
+ s.getTransaction().commit();
+ s.close();
+
+ assertNotNull( owner.getComponent() );
+ previousValue = owner.getComponent().getGenerated();
+
+ s = openSession();
+ s.beginTransaction();
+ owner = ( ComponentOwner ) s.get( ComponentOwner.class, owner.getId() );
+ assertEquals( "expecting update value generation", previousValue,
owner.getComponent().getGenerated() );
+ s.delete( owner );
+ s.getTransaction().commit();
+ s.close();
+ }
+}
Modified: trunk/Hibernate3/test/org/hibernate/test/legacy/CustomPersister.java
===================================================================
--- trunk/Hibernate3/test/org/hibernate/test/legacy/CustomPersister.java 2007-01-18
01:51:13 UTC (rev 11059)
+++ trunk/Hibernate3/test/org/hibernate/test/legacy/CustomPersister.java 2007-01-19
12:51:31 UTC (rev 11060)
@@ -21,6 +21,7 @@
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.engine.TwoPhaseLoad;
+import org.hibernate.engine.ValueInclusion;
import org.hibernate.event.EventSource;
import org.hibernate.event.PostLoadEvent;
import org.hibernate.event.PreLoadEvent;
@@ -471,12 +472,12 @@
return MUTABILITY;
}
- public boolean[] getPropertyInsertGeneration() {
- return new boolean[0];
+ public ValueInclusion[] getPropertyInsertGenerationInclusions() {
+ return new ValueInclusion[0];
}
- public boolean[] getPropertyUpdateGeneration() {
- return new boolean[0];
+ public ValueInclusion[] getPropertyUpdateGenerationInclusions() {
+ return new ValueInclusion[0];
}