📄 basicentitypersister.java
字号:
*/ protected String generateInsertString(boolean identityInsert, boolean[] includeProperty, int j) { Insert insert = new Insert( getFactory().getDialect() ) .setTableName( getTableName( j ) ); // add normal properties for ( int i = 0; i < entityMetamodel.getPropertySpan(); i++ ) { if ( includeProperty[i] && isPropertyOfTable( i, j ) ) { // this property belongs on the table and is to be inserted insert.addColumns( getPropertyColumnNames(i), propertyColumnInsertable[i] ); } } // add the discriminator if ( j == 0 ) addDiscriminatorToInsert( insert ); // add the primary key if ( j == 0 && identityInsert ) { insert.addIdentityColumn( getKeyColumns( 0 )[0] ); } else { insert.addColumns( getKeyColumns( j ) ); } if ( getFactory().getSettings().isCommentsEnabled() ) { insert.setComment( "insert " + getEntityName() ); } String result = insert.toStatementString(); // append the SQL to return the generated identifier if ( j == 0 && identityInsert && useInsertSelectIdentity() ) { //TODO: suck into Insert result = getFactory().getDialect().appendIdentitySelectToInsert( result ); } return result; } /** * Generate the SQL that deletes a row by id (and version) */ protected String generateDeleteString(int j) { Delete delete = new Delete() .setTableName( getTableName( j ) ) .setPrimaryKeyColumnNames( getKeyColumns( j ) ); if ( j == 0 ) delete.setVersionColumnName( getVersionColumnName() ); if ( getFactory().getSettings().isCommentsEnabled() ) { delete.setComment( "delete " + getEntityName() ); } return delete.toStatementString(); } protected int dehydrate( Serializable id, Object[] fields, boolean[] includeProperty, boolean[][] includeColumns, int j, PreparedStatement st, SessionImplementor session) throws HibernateException, SQLException { return dehydrate( id, fields, null, includeProperty, includeColumns, j, st, session, 1 ); } /** * Marshall the fields of a persistent instance to a prepared statement */ protected int dehydrate(final Serializable id, final Object[] fields, final Object rowId, final boolean[] includeProperty, final boolean[][] includeColumns, final int j, final PreparedStatement ps, final SessionImplementor session, int index) throws SQLException, HibernateException { if ( log.isTraceEnabled() ) { log.trace( "Dehydrating entity: " + MessageHelper.infoString( this, id, getFactory() ) ); } for ( int i = 0; i < entityMetamodel.getPropertySpan(); i++ ) { 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 ( rowId != null ) { ps.setObject( index, rowId ); index += 1; } else if ( id != null ) { getIdentifierType().nullSafeSet( ps, id, index, session ); index += getIdentifierColumnSpan(); } return index; } /** * Unmarshall the fields of a persistent instance from a result set, * without resolving associations or collections. Question: should * this really be here, or should it be sent back to Loader? */ public Object[] hydrate(final ResultSet rs, final Serializable id, final Object object, final Loadable rootLoadable, final SessionImplementor session, final String[][] suffixedPropertyColumns, final boolean allProperties) throws SQLException, HibernateException { if ( log.isTraceEnabled() ) { log.trace( "Hydrating entity: " + MessageHelper.infoString( this, id, getFactory() ) ); } final BasicEntityPersister rootPersister = (BasicEntityPersister) rootLoadable; final boolean hasDeferred = rootPersister.hasSequentialSelect(); PreparedStatement sequentialSelect = null; ResultSet sequentialResultSet = null; try { if ( hasDeferred ) { final String sql = rootPersister.getSequentialSelect( getEntityName() ); if ( sql != null ) { //TODO: I am not so sure about the exception handling in this bit! sequentialSelect = session.getBatcher().prepareSelectStatement( sql ); rootPersister.getIdentifierType().nullSafeSet( sequentialSelect, id, 1, session ); sequentialResultSet = sequentialSelect.executeQuery(); sequentialResultSet.next(); } } final String[] propNames = getPropertyNames(); final Type[] types = getPropertyTypes(); final Object[] values = new Object[types.length]; final boolean[] laziness = getPropertyLaziness(); final String[] propSubclassNames = getSubclassPropertySubclassNameClosure(); for ( int i = 0; i < types.length; i++ ) { if ( !propertySelectable[i] ) { values[i] = BackrefPropertyAccessor.UNKNOWN; } else if ( allProperties || !laziness[i] ) { //decide which ResultSet to get the property value from: final boolean propertyIsDeferred = hasDeferred && rootPersister.isSubclassPropertyDeferred( propNames[i], propSubclassNames[i] ); final ResultSet propertyResultSet = propertyIsDeferred ? sequentialResultSet : rs; final String[] cols = propertyIsDeferred ? propertyColumnAliases[i] : suffixedPropertyColumns[i]; values[i] = types[i].hydrate( propertyResultSet, cols, session, object ); } else { values[i] = LazyPropertyInitializer.UNFETCHED_PROPERTY; } } if ( sequentialResultSet != null ) sequentialResultSet.close(); return values; } finally { if ( sequentialSelect != null ) { session.getBatcher().closeStatement( sequentialSelect ); } } } protected boolean useInsertSelectIdentity() { return !useGetGeneratedKeys() && getFactory().getDialect().supportsInsertSelectIdentity(); } protected boolean useGetGeneratedKeys() { return getFactory().getSettings().isGetGeneratedKeysEnabled(); } protected String getSequentialSelect(String entityName) { throw new UnsupportedOperationException("no sequential selects"); } /** * Perform an SQL INSERT, and then retrieve a generated identifier */ protected Serializable insert(final Object[] fields, final boolean[] notNull, String sql, final Object object, final SessionImplementor session) throws HibernateException { if ( log.isTraceEnabled() ) { log.trace( "Inserting entity: " + getEntityName() + " (native id)" ); if ( isVersioned() ) log.trace( "Version: " + Versioning.getVersion( fields, this ) ); } try { //do the insert PreparedStatement insert = session.getBatcher().prepareStatement( sql, useGetGeneratedKeys() ); try { dehydrate( null, fields, notNull, propertyColumnInsertable, 0, insert, session ); if ( useInsertSelectIdentity() ) { if ( !insert.execute() ) { while ( !insert.getMoreResults() && insert.getUpdateCount() != -1 ) { continue; // Do nothing (but stop checkstyle from complaining). } } //note early exit! ResultSet rs = insert.getResultSet(); try { return IdentifierGeneratorFactory.getGeneratedIdentity( rs, getIdentifierType() ); } finally { rs.close(); } } else if ( useGetGeneratedKeys() ) { insert.executeUpdate(); //note early exit! return IdentifierGeneratorFactory.getGeneratedIdentity( GetGeneratedKeysHelper.getGeneratedKey(insert), getIdentifierType() ); } else { insert.executeUpdate(); } } finally { session.getBatcher().closeStatement( insert ); } } catch ( SQLException sqle ) { throw JDBCExceptionHelper.convert( getFactory().getSQLExceptionConverter(), sqle, "could not insert: " + MessageHelper.infoString(this), sql ); } return ( (PostInsertIdentifierGenerator) getIdentifierGenerator() ).getGenerated(session, object, this); } public String getIdentitySelectString() { //TODO: cache this in an instvar return getFactory().getDialect().getIdentitySelectString( getTableName(0), getKeyColumns(0)[0], getIdentifierType().sqlTypes( getFactory() )[0] ); } public String getSelectByUniqueKeyString(String propertyName) { return new SimpleSelect( getFactory().getDialect() ) .setTableName( getTableName(0) ) .addColumns( getKeyColumns(0) ) .addCondition( getPropertyColumnNames(propertyName), "=?" ) .toStatementString(); } /** * Perform an SQL INSERT */ protected void insert(final Serializable id, final Object[] fields, final boolean[] notNull, final int j, final String sql, final Object object, final SessionImplementor session) throws HibernateException { if ( isInverseTable( j ) ) return; //note: it is conceptually possible that a UserType could map null to // a non-null value, so the following is arguable: if ( isNullableTable( j ) && isAllNull( fields, j ) ) return; if ( log.isTraceEnabled() ) { log.trace( "Inserting entity: " + MessageHelper.infoString( this, id, getFactory() ) ); if ( j == 0 && isVersioned() ) log.trace( "Version: " + Versioning.getVersion( fields, this ) ); } boolean callable = isInsertCallable( j ); final boolean useBatch = j == 0 && !callable; //we can't batch joined inserts, *especially* not if it is an identity insert try { // Render the SQL query final PreparedStatement insert; if ( callable ) { insert = session.getBatcher().prepareCallableStatement( sql ); } else if ( useBatch ) { insert = session.getBatcher().prepareBatchStatement( sql ); } else { insert = session.getBatcher().prepareStatement( sql ); } try { // 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, notNull, propertyColumnInsertable, j, insert, session ); if ( useBatch ) { session.getBatcher().addToBatch( 1 ); } else { insert.executeUpdate(); } } catch ( SQLException sqle ) { if ( useBatch ) session.getBatcher().abortBatch( sqle ); throw sqle; } finally { if ( !useBatch ) session.getBatcher().closeStatement( insert ); } } catch ( SQLException sqle ) { throw JDBCExceptionHelper.convert( getFactory().getSQLExceptionConverter(), sqle, "could not insert: " + MessageHelper.infoString( this ), sql ); } } /** * Perform an SQL UPDATE or SQL INSERT */ protected void updateOrInsert(final Serializable id, final Object[] fields, final Object[] oldFields, final Object rowId, final boolean[] includeProperty, final int j, final Object oldVersion, final Object object, final String sql, final SessionImplementor session) throws HibernateException { if ( !isInverseTable( j ) ) { final boolean isRowToUpdate; if ( isNullableTable( j ) && oldFields != null && isAllNull( oldFields, j ) ) { //don't bother trying to update, we know there is no row there yet isRowToUpdate = false; } else if ( isNullableTable( j ) && isAllNull( fields, j ) ) { //if all fields are null, we might need to delete existing row isRowToUpdate = true; delete( id, oldVersion, j, object, getSQLDeleteStrings()[j], session ); } else { //there is probably a row there, so try to update //if no rows were updated, we will find out isRowToUpdate = update( id, fields, oldFields, rowId, includeProperty, j, oldVersion, object, sql, session ); } if ( !isRowToUpdate && !isAl
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -