Permalink
Browse files

HHH-4635 Oracle ORA-24816 inserting and updating data for entities

containg LOB attributes
  • Loading branch information...
brmeyer
brmeyer committed Sep 24, 2012
1 parent 563af13 commit 121f495ff8b30bfae9487e675ea8a176ec6907ba
@@ -24,10 +24,10 @@
package org.hibernate.cfg.annotations;
import java.util.Map;
+
import javax.persistence.EmbeddedId;
import javax.persistence.Id;
-
-import org.jboss.logging.Logger;
+import javax.persistence.Lob;
import org.hibernate.AnnotationException;
import org.hibernate.annotations.Generated;
@@ -57,6 +57,7 @@
import org.hibernate.mapping.SimpleValue;
import org.hibernate.mapping.ToOne;
import org.hibernate.mapping.Value;
+import org.jboss.logging.Logger;
/**
* @author Emmanuel Bernard
@@ -264,6 +265,7 @@ public Property makeProperty() {
prop.setLazy( lazy );
prop.setCascade( cascade );
prop.setPropertyAccessorName( accessType.getType() );
+
Generated ann = property != null ?
property.getAnnotation( Generated.class ) :
null;
@@ -286,6 +288,7 @@ public Property makeProperty() {
prop.setGeneration( PropertyGeneration.parse( generated.toString().toLowerCase() ) );
}
}
+
NaturalId naturalId = property != null ? property.getAnnotation( NaturalId.class ) : null;
if ( naturalId != null ) {
if ( ! entityBinder.isRootEntity() ) {
@@ -296,6 +299,11 @@ public Property makeProperty() {
}
prop.setNaturalIdentifier( true );
}
+
+ // HHH-4635 -- needed for dialect-specific property ordering
+ Lob lob = property != null ? property.getAnnotation( Lob.class ) : null;
+ prop.setLob( lob != null );
+
prop.setInsertable( insertable );
prop.setUpdateable( updatable );
@@ -2369,4 +2369,15 @@ public boolean supportsTupleDistinctCounts() {
public int getInExpressionCountLimit() {
return 0;
}
+
+ /**
+ * HHH-4635
+ * Oracle expects all Lob values to be last in inserts and updates.
+ *
+ * @return boolean True of Lob values should be last, false if it
+ * does not matter.
+ */
+ public boolean forceLobAsLastValue() {
+ return false;
+ }
}
@@ -576,5 +576,10 @@ public int getInExpressionCountLimit() {
public boolean supportsNotNullUnique() {
return false;
}
+
+ @Override
+ public boolean forceLobAsLastValue() {
+ return true;
+ }
}
@@ -62,6 +62,7 @@
private java.util.Map metaAttributes;
private PersistentClass persistentClass;
private boolean naturalIdentifier;
+ private boolean lob;
public boolean isBackRef() {
return false;
@@ -339,4 +340,12 @@ public void setNaturalIdentifier(boolean naturalIdentifier) {
this.naturalIdentifier = naturalIdentifier;
}
+ public boolean isLob() {
+ return lob;
+ }
+
+ public void setLob(boolean lob) {
+ this.lob = lob;
+ }
+
}
@@ -184,6 +184,8 @@
private final boolean[][] propertyColumnInsertable;
private final boolean[] propertyUniqueness;
private final boolean[] propertySelectable;
+
+ private final List<Integer> lobProperties = new ArrayList<Integer>();
//information about lazy properties of this class
private final String[] lazyPropertyNames;
@@ -630,6 +632,10 @@ public AbstractEntityPersister(
propertySelectable[i] = prop.isSelectable();
propertyUniqueness[i] = prop.getValue().isAlternateUniqueKey();
+
+ if (prop.isLob() && getFactory().getDialect().forceLobAsLastValue() ) {
+ lobProperties.add( i );
+ }
i++;
@@ -942,6 +948,8 @@ public AbstractEntityPersister(
propertySelectable[i] = true;
propertyUniqueness[i] = singularAttributeBinding.isAlternateUniqueKey();
+
+ // TODO: Does this need AttributeBindings wired into lobProperties? Currently in Property only.
i++;
@@ -2508,12 +2516,26 @@ protected String generateUpdateString(final boolean[] includeProperty,
boolean hasColumns = false;
for ( int i = 0; i < entityMetamodel.getPropertySpan(); i++ ) {
- if ( includeProperty[i] && isPropertyOfTable( i, j ) ) {
+ if ( includeProperty[i] && isPropertyOfTable( i, j )
+ && !lobProperties.contains( i ) ) {
// this is a property of the table, which we are updating
- update.addColumns( getPropertyColumnNames(i), propertyColumnUpdateable[i], propertyColumnWriters[i] );
+ update.addColumns( getPropertyColumnNames(i),
+ propertyColumnUpdateable[i], propertyColumnWriters[i] );
hasColumns = hasColumns || getPropertyColumnSpan( i ) > 0;
}
}
+
+ // HHH-4635
+ // Oracle expects all Lob properties to be last in inserts
+ // and updates. Insert them at the end.
+ for ( int i : lobProperties ) {
+ if ( includeProperty[i] && isPropertyOfTable( i, j ) ) {
+ // this property belongs on the table and is to be inserted
+ update.addColumns( getPropertyColumnNames(i),
+ propertyColumnUpdateable[i], propertyColumnWriters[i] );
+ hasColumns = true;
+ }
+ }
if ( j == 0 && isVersioned() && entityMetamodel.getOptimisticLockStyle() == OptimisticLockStyle.VERSION ) {
// this is the root (versioned) table, and we are using version-based
@@ -2579,7 +2601,8 @@ protected String generateInsertString(boolean identityInsert, boolean[] includeP
/**
* Generate the SQL that inserts a row
*/
- protected String generateInsertString(boolean identityInsert, boolean[] includeProperty, int j) {
+ protected String generateInsertString(boolean identityInsert,
+ boolean[] includeProperty, int j) {
// todo : remove the identityInsert param and variations;
// identity-insert strings are now generated from generateIdentityInsertString()
@@ -2589,9 +2612,13 @@ protected String generateInsertString(boolean identityInsert, boolean[] includeP
// add normal properties
for ( int i = 0; i < entityMetamodel.getPropertySpan(); i++ ) {
- if ( includeProperty[i] && isPropertyOfTable( i, j ) ) {
+
+ if ( includeProperty[i] && isPropertyOfTable( i, j )
+ && !lobProperties.contains( i ) ) {
// this property belongs on the table and is to be inserted
- insert.addColumns( getPropertyColumnNames(i), propertyColumnInsertable[i], propertyColumnWriters[i] );
+ insert.addColumns( getPropertyColumnNames(i),
+ propertyColumnInsertable[i],
+ propertyColumnWriters[i] );
}
}
@@ -2611,6 +2638,18 @@ protected String generateInsertString(boolean identityInsert, boolean[] includeP
if ( getFactory().getSettings().isCommentsEnabled() ) {
insert.setComment( "insert " + getEntityName() );
}
+
+ // HHH-4635
+ // Oracle expects all Lob properties to be last in inserts
+ // and updates. Insert them at the end.
+ for ( int i : lobProperties ) {
+ if ( includeProperty[i] && isPropertyOfTable( i, j ) ) {
+ // this property belongs on the table and is to be inserted
+ insert.addColumns( getPropertyColumnNames(i),
+ propertyColumnInsertable[i],
+ propertyColumnWriters[i] );
+ }
+ }
String result = insert.toStatementString();
@@ -2678,8 +2717,9 @@ protected int dehydrate(
boolean[][] includeColumns,
int j,
PreparedStatement st,
- SessionImplementor session) throws HibernateException, SQLException {
- return dehydrate( id, fields, null, includeProperty, includeColumns, j, st, session, 1 );
+ SessionImplementor session,
+ boolean isUpdate) throws HibernateException, SQLException {
+ return dehydrate( id, fields, null, includeProperty, includeColumns, j, st, session, 1, isUpdate );
}
/**
@@ -2694,31 +2734,57 @@ protected int dehydrate(
final int j,
final PreparedStatement ps,
final SessionImplementor session,
- int index) throws SQLException, HibernateException {
+ int index,
+ boolean isUpdate ) throws SQLException, HibernateException {
if ( LOG.isTraceEnabled() ) {
LOG.tracev( "Dehydrating entity: {0}", MessageHelper.infoString( this, id, getFactory() ) );
}
for ( int i = 0; i < entityMetamodel.getPropertySpan(); i++ ) {
+ if ( includeProperty[i] && isPropertyOfTable( i, j )
+ && !lobProperties.contains( i )) {
+ getPropertyTypes()[i].nullSafeSet( ps, fields[i], index, includeColumns[i], session );
+ index += ArrayHelper.countTrue( includeColumns[i] ); //TODO: this is kinda slow...
+ }
+ }
+
+ if ( !isUpdate ) {
+ index += dehydrateId( id, rowId, ps, session, index );
+ }
+
+ // HHH-4635
+ // Oracle expects all Lob properties to be last in inserts
+ // and updates. Insert them at the end.
+ for ( int i : lobProperties ) {
if ( includeProperty[i] && isPropertyOfTable( i, j ) ) {
getPropertyTypes()[i].nullSafeSet( ps, fields[i], index, includeColumns[i], session );
- //index += getPropertyColumnSpan( i );
index += ArrayHelper.countTrue( includeColumns[i] ); //TODO: this is kinda slow...
}
}
+
+ if ( isUpdate ) {
+ index += dehydrateId( id, rowId, ps, session, index );
+ }
+ return index;
+
+ }
+
+ private int dehydrateId(
+ final Serializable id,
+ final Object rowId,
+ final PreparedStatement ps,
+ final SessionImplementor session,
+ int index ) throws SQLException {
if ( rowId != null ) {
ps.setObject( index, rowId );
- index += 1;
- }
- else if ( id != null ) {
+ return 1;
+ } else if ( id != null ) {
getIdentifierType().nullSafeSet( ps, id, index, session );
- index += getIdentifierColumnSpan();
+ return getIdentifierColumnSpan();
}
-
- return index;
-
+ return 0;
}
/**
@@ -2860,7 +2926,7 @@ protected Serializable insert(
Binder binder = new Binder() {
public void bindValues(PreparedStatement ps) throws SQLException {
- dehydrate( null, fields, notNull, propertyColumnInsertable, 0, ps, session );
+ dehydrate( null, fields, notNull, propertyColumnInsertable, 0, ps, session, false );
}
public Object getEntity() {
return object;
@@ -2956,7 +3022,7 @@ protected void insert(
// Write the values of fields onto the prepared statement - we MUST use the state at the time the
// insert was issued (cos of foreign key constraints). Not necessarily the object's current state
- dehydrate( id, fields, null, notNull, propertyColumnInsertable, j, insert, session, index );
+ dehydrate( id, fields, null, notNull, propertyColumnInsertable, j, insert, session, index, false );
if ( useBatch ) {
session.getTransactionCoordinator().getJdbcCoordinator().getBatch( inserBatchKey ).addToBatch();
@@ -3083,7 +3149,7 @@ protected boolean update(
index+= expectation.prepare( update );
//Now write the values of fields onto the prepared statement
- index = dehydrate( id, fields, rowId, includeProperty, propertyColumnUpdateable, j, update, session, index );
+ index = dehydrate( id, fields, rowId, includeProperty, propertyColumnUpdateable, j, update, session, index, true );
// Write any appropriate versioning conditional parameters
if ( useVersion && entityMetamodel.getOptimisticLockStyle() == OptimisticLockStyle.VERSION ) {
@@ -5,6 +5,7 @@
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
+import javax.persistence.Lob;
import javax.persistence.Table;
@Entity
@@ -14,6 +15,7 @@
@Id
private Long id;
+ @Lob
private Blob lobValue;
@Column( name = "qwerty", length = 4000 )

0 comments on commit 121f495

Please sign in to comment.