| Method from org.hibernate.persister.entity.AbstractEntityPersister Detail: |
protected void addDiscriminatorToInsert(Insert insert) {
}
|
protected void addDiscriminatorToSelect(SelectFragment select,
String name,
String suffix) {
}
|
public void afterInitialize(Object entity,
boolean lazyPropertiesAreUnfetched,
SessionImplementor session) {
getTuplizer( session ).afterInitialize( entity, lazyPropertiesAreUnfetched, session );
}
|
public void afterReassociate(Object entity,
SessionImplementor session) {
//if ( hasLazyProperties() ) {
if ( FieldInterceptionHelper.isInstrumented( entity ) ) {
FieldInterceptor interceptor = FieldInterceptionHelper.extractFieldInterceptor( entity );
if ( interceptor != null ) {
interceptor.setSession( session );
}
else {
FieldInterceptor fieldInterceptor = FieldInterceptionHelper.injectFieldInterceptor(
entity,
getEntityName(),
null,
session
);
fieldInterceptor.dirty();
}
}
}
|
public boolean canExtractIdOutOfEntity() {
return hasIdentifierProperty() || hasEmbeddedCompositeIdentifier() || hasIdentifierMapper();
}
|
protected boolean check(int rows,
Serializable id,
int tableNumber,
Expectation expectation,
PreparedStatement statement) throws HibernateException {
try {
expectation.verifyOutcome( rows, statement, -1 );
}
catch( StaleStateException e ) {
if ( !isNullableTable( tableNumber ) ) {
if ( getFactory().getStatistics().isStatisticsEnabled() ) {
getFactory().getStatisticsImplementor()
.optimisticFailure( getEntityName() );
}
throw new StaleObjectStateException( getEntityName(), id );
}
return false;
}
catch( TooManyRowsAffectedException e ) {
throw new HibernateException(
"Duplicate identifier in table for: " +
MessageHelper.infoString( this, id, getFactory() )
);
}
catch ( Throwable t ) {
return false;
}
return true;
}
|
protected String concretePropertySelectFragment(String alias,
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,
boolean[] includeProperty) {
return concretePropertySelectFragment(
alias,
new InclusionChecker() {
public boolean includeProperty(int propertyNumber) {
return includeProperty[propertyNumber];
}
}
);
}
|
protected String concretePropertySelectFragment(String alias,
AbstractEntityPersister.InclusionChecker inclusionChecker) {
int propertyCount = getPropertyNames().length;
int[] propertyTableNumbers = getPropertyTableNumbersInSelect();
SelectFragment frag = new SelectFragment();
for ( int i = 0; i < propertyCount; i++ ) {
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();
}
|
protected String concretePropertySelectFragmentSansLeadingComma(String alias,
boolean[] include) {
String concretePropertySelectFragment = concretePropertySelectFragment( alias, include );
int firstComma = concretePropertySelectFragment.indexOf( ", " );
if ( firstComma == 0 ) {
concretePropertySelectFragment = concretePropertySelectFragment.substring( 2 );
}
return concretePropertySelectFragment;
}
|
public boolean consumesCollectionAlias() {
return false;
}
|
public boolean consumesEntityAlias() {
return true;
}
|
public int countSubclassProperties() {
return subclassPropertyTypeClosure.length;
}
|
protected UniqueEntityLoader createEntityLoader(LockMode lockMode) throws MappingException {
return createEntityLoader( lockMode, CollectionHelper.EMPTY_MAP );
}
|
protected UniqueEntityLoader createEntityLoader(LockMode lockMode,
Map enabledFilters) throws MappingException {
//TODO: disable batch loading if lockMode > READ?
return BatchingEntityLoader.createBatchingEntityLoader( this, batchSize, lockMode, getFactory(), enabledFilters );
}
|
protected String createFrom(int tableNumber,
String alias) {
return getSubclassTableName( tableNumber ) + ' " + alias;
}
|
protected JoinFragment createJoin(int[] tableNumbers,
String drivingAlias) {
final String[] keyCols = StringHelper.qualify( drivingAlias, getSubclassTableKeyColumns( tableNumbers[0] ) );
final JoinFragment jf = getFactory().getDialect().createOuterJoinFragment();
for ( int i = 1; i < tableNumbers.length; i++ ) { //skip the driving table
final int j = tableNumbers[i];
jf.addJoin( getSubclassTableName( j ),
generateTableAlias( getRootAlias(), j ),
keyCols,
getSubclassTableKeyColumns( j ),
isInverseSubclassTable( j ) || isNullableSubclassTable( j ) ?
JoinFragment.LEFT_OUTER_JOIN :
JoinFragment.INNER_JOIN );
}
return jf;
}
|
protected JoinFragment createJoin(String name,
boolean innerJoin,
boolean includeSubclasses) {
final String[] idCols = StringHelper.qualify( name, getIdentifierColumnNames() ); //all joins join to the pk of the driving table
final JoinFragment join = getFactory().getDialect().createOuterJoinFragment();
final int tableSpan = getSubclassTableSpan();
for ( int j = 1; j < tableSpan; j++ ) { //notice that we skip the first table; it is the driving table!
final boolean joinIsIncluded = isClassOrSuperclassTable( j ) ||
( includeSubclasses && !isSubclassTableSequentialSelect( j ) && !isSubclassTableLazy( j ) );
if ( joinIsIncluded ) {
join.addJoin( getSubclassTableName( j ),
generateTableAlias( name, j ),
idCols,
getSubclassTableKeyColumns( j ),
innerJoin && isClassOrSuperclassTable( j ) && !isInverseTable( j ) && !isNullableTable( j ) ?
JoinFragment.INNER_JOIN : //we can inner join to superclass tables (the row MUST be there)
JoinFragment.LEFT_OUTER_JOIN //we can never inner join to subclass tables
);
}
}
return join;
}
|
public Object createProxy(Serializable id,
SessionImplementor session) throws HibernateException {
return entityMetamodel.getTuplizer( session.getEntityMode() )
.createProxy( id, session );
}
|
protected void createQueryLoader() {
if ( loaderName != null ) {
queryLoader = new NamedQueryLoader( loaderName, this );
}
}
|
protected SelectFragment createSelect(int[] subclassColumnNumbers,
int[] subclassFormulaNumbers) {
SelectFragment selectFragment = new SelectFragment();
int[] columnTableNumbers = getSubclassColumnTableNumberClosure();
String[] columnAliases = getSubclassColumnAliasClosure();
String[] columns = getSubclassColumnClosure();
for ( int i = 0; i < subclassColumnNumbers.length; i++ ) {
if ( subclassColumnSelectableClosure[i] ) {
int columnNumber = subclassColumnNumbers[i];
final String subalias = generateTableAlias( getRootAlias(), columnTableNumbers[columnNumber] );
selectFragment.addColumn( subalias, columns[columnNumber], columnAliases[columnNumber] );
}
}
int[] formulaTableNumbers = getSubclassFormulaTableNumberClosure();
String[] formulaTemplates = getSubclassFormulaTemplateClosure();
String[] formulaAliases = getSubclassFormulaAliasClosure();
for ( int i = 0; i < subclassFormulaNumbers.length; i++ ) {
int formulaNumber = subclassFormulaNumbers[i];
final String subalias = generateTableAlias( getRootAlias(), formulaTableNumbers[formulaNumber] );
selectFragment.addFormula( subalias, formulaTemplates[formulaNumber], formulaAliases[formulaNumber] );
}
return selectFragment;
}
|
protected void createUniqueKeyLoaders() throws MappingException {
Type[] propertyTypes = getPropertyTypes();
String[] propertyNames = getPropertyNames();
for ( int i = 0; i < entityMetamodel.getPropertySpan(); i++ ) {
if ( propertyUniqueness[i] ) {
//don't need filters for the static loaders
uniqueKeyLoaders.put(
propertyNames[i],
createUniqueKeyLoader(
propertyTypes[i],
getPropertyColumnNames( i ),
CollectionHelper.EMPTY_MAP
)
);
//TODO: create uk loaders for component properties
}
}
}
|
protected String createWhereByKey(int tableNumber,
String alias) {
//TODO: move to .sql package, and refactor with similar things!
return StringHelper.join( "=? and ",
StringHelper.qualify( alias, getSubclassTableKeyColumns( tableNumber ) ) ) + "=?";
}
|
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 );
}
|
protected int dehydrate(Serializable id,
Object[] fields,
Object rowId,
boolean[] includeProperty,
boolean[][] includeColumns,
int j,
PreparedStatement ps,
SessionImplementor session,
int index) throws HibernateException, SQLException {
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;
}
Marshall the fields of a persistent instance to a prepared statement |
public void delete(Serializable id,
Object version,
Object object,
SessionImplementor session) throws HibernateException {
final int span = getTableSpan();
boolean isImpliedOptimisticLocking = !entityMetamodel.isVersioned() && entityMetamodel.getOptimisticLockMode() > Versioning.OPTIMISTIC_LOCK_VERSION;
Object[] loadedState = null;
if ( isImpliedOptimisticLocking ) {
// need to treat this as if it where optimistic-lock="all" (dirty does *not* make sense);
// first we need to locate the "loaded" state
//
// Note, it potentially could be a proxy, so perform the location the safe way...
EntityKey key = new EntityKey( id, this, session.getEntityMode() );
Object entity = session.getPersistenceContext().getEntity( key );
if ( entity != null ) {
EntityEntry entry = session.getPersistenceContext().getEntry( entity );
loadedState = entry.getLoadedState();
}
}
final String[] deleteStrings;
if ( isImpliedOptimisticLocking && loadedState != null ) {
// we need to utilize dynamic delete statements
deleteStrings = generateSQLDeletStrings( loadedState );
}
else {
// otherwise, utilize the static delete statements
deleteStrings = getSQLDeleteStrings();
}
for ( int j = span - 1; j >= 0; j-- ) {
delete( id, version, j, object, deleteStrings[j], session, loadedState );
}
}
|
protected void delete(Serializable id,
Object version,
int j,
Object object,
String sql,
SessionImplementor session,
Object[] loadedState) throws HibernateException {
if ( isInverseTable( j ) ) {
return;
}
final boolean useVersion = j == 0 && isVersioned();
final boolean callable = isDeleteCallable( j );
final Expectation expectation = Expectations.appropriateExpectation( deleteResultCheckStyles[j] );
final boolean useBatch = j == 0 && isBatchable() && expectation.canBeBatched();
if ( log.isTraceEnabled() ) {
log.trace( "Deleting entity: " + MessageHelper.infoString( this, id, getFactory() ) );
if ( useVersion ) {
log.trace( "Version: " + version );
}
}
if ( isTableCascadeDeleteEnabled( j ) ) {
if ( log.isTraceEnabled() ) {
log.trace( "delete handled by foreign key constraint: " + getTableName( j ) );
}
return; //EARLY EXIT!
}
try {
//Render the SQL query
PreparedStatement delete;
int index = 1;
if ( useBatch ) {
if ( callable ) {
delete = session.getBatcher().prepareBatchCallableStatement( sql );
}
else {
delete = session.getBatcher().prepareBatchStatement( sql );
}
}
else {
if ( callable ) {
delete = session.getBatcher().prepareCallableStatement( sql );
}
else {
delete = session.getBatcher().prepareStatement( sql );
}
}
try {
index += expectation.prepare( delete );
// Do the key. The key is immutable so we can use the _current_ object state - not necessarily
// the state at the time the delete was issued
getIdentifierType().nullSafeSet( delete, id, index, session );
index += getIdentifierColumnSpan();
// We should use the _current_ object state (ie. after any updates that occurred during flush)
if ( useVersion ) {
getVersionType().nullSafeSet( delete, version, index, session );
}
else if ( entityMetamodel.getOptimisticLockMode() > Versioning.OPTIMISTIC_LOCK_VERSION && loadedState != null ) {
boolean[] versionability = getPropertyVersionability();
Type[] types = getPropertyTypes();
for ( int i = 0; i < entityMetamodel.getPropertySpan(); i++ ) {
if ( isPropertyOfTable( i, j ) && versionability[i] ) {
// this property belongs to the table and it is not specifically
// excluded from optimistic locking by optimistic-lock="false"
boolean[] settable = types[i].toColumnNullness( loadedState[i], getFactory() );
types[i].nullSafeSet( delete, loadedState[i], index, settable, session );
index += ArrayHelper.countTrue( settable );
}
}
}
if ( useBatch ) {
session.getBatcher().addToBatch( expectation );
}
else {
check( delete.executeUpdate(), id, j, expectation, delete );
}
}
catch ( SQLException sqle ) {
if ( useBatch ) {
session.getBatcher().abortBatch( sqle );
}
throw sqle;
}
finally {
if ( !useBatch ) {
session.getBatcher().closeStatement( delete );
}
}
}
catch ( SQLException sqle ) {
throw JDBCExceptionHelper.convert(
getFactory().getSQLExceptionConverter(),
sqle,
"could not delete: " +
MessageHelper.infoString( this, id, getFactory() ),
sql
);
}
}
|
abstract protected String filterFragment(String alias) throws MappingException
|
public String filterFragment(String alias,
Map enabledFilters) throws MappingException {
final StringBuffer sessionFilterFragment = new StringBuffer();
filterHelper.render( sessionFilterFragment, generateFilterConditionAlias( alias ), enabledFilters );
return sessionFilterFragment.append( filterFragment( alias ) ).toString();
}
|
public int[] findDirty(Object[] currentState,
Object[] previousState,
Object entity,
SessionImplementor session) throws HibernateException {
int[] props = TypeFactory.findDirty(
entityMetamodel.getProperties(),
currentState,
previousState,
propertyColumnUpdateable,
hasUninitializedLazyProperties( entity, session.getEntityMode() ),
session
);
if ( props == null ) {
return null;
}
else {
logDirtyProperties( props );
return props;
}
}
Locate the property-indices of all properties considered to be dirty. |
public int[] findModified(Object[] old,
Object[] current,
Object entity,
SessionImplementor session) throws HibernateException {
int[] props = TypeFactory.findModified(
entityMetamodel.getProperties(),
current,
old,
propertyColumnUpdateable,
hasUninitializedLazyProperties( entity, session.getEntityMode() ),
session
);
if ( props == null ) {
return null;
}
else {
logDirtyProperties( props );
return props;
}
}
Locate the property-indices of all properties considered to be dirty. |
public Object forceVersionIncrement(Serializable id,
Object currentVersion,
SessionImplementor session) {
if ( !isVersioned() ) {
throw new AssertionFailure( "cannot force version increment on non-versioned entity" );
}
if ( isVersionPropertyGenerated() ) {
// the difficulty here is exactly what do we update in order to
// force the version to be incremented in the db...
throw new HibernateException( "LockMode.FORCE is currently not supported for generated version properties" );
}
Object nextVersion = getVersionType().next( currentVersion, session );
if ( log.isTraceEnabled() ) {
log.trace(
"Forcing version increment [" + MessageHelper.infoString( this, id, getFactory() ) +
"; " + getVersionType().toLoggableString( currentVersion, getFactory() ) +
" - > " + getVersionType().toLoggableString( nextVersion, getFactory() ) + "]"
);
}
// todo : cache this sql...
String versionIncrementString = generateVersionIncrementUpdateString();
PreparedStatement st = null;
try {
try {
st = session.getBatcher().prepareStatement( versionIncrementString );
getVersionType().nullSafeSet( st, nextVersion, 1, session );
getIdentifierType().nullSafeSet( st, id, 2, session );
getVersionType().nullSafeSet( st, currentVersion, 2 + getIdentifierColumnSpan(), session );
int rows = st.executeUpdate();
if ( rows != 1 ) {
throw new StaleObjectStateException( getEntityName(), id );
}
}
finally {
session.getBatcher().closeStatement( st );
}
}
catch ( SQLException sqle ) {
throw JDBCExceptionHelper.convert(
getFactory().getSQLExceptionConverter(),
sqle,
"could not retrieve version: " +
MessageHelper.infoString( this, id, getFactory() ),
getVersionSelectString()
);
}
return nextVersion;
}
|
public String fromJoinFragment(String alias,
boolean innerJoin,
boolean includeSubclasses) {
return getSubclassTableSpan() == 1 ?
"" : //just a performance opt!
createJoin( alias, innerJoin, includeSubclasses ).toFromFragmentString();
}
|
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();
}
Generate the SQL that deletes a row by id (and version) |
public String generateFilterConditionAlias(String rootAlias) {
return rootAlias;
}
|
protected String generateIdentityInsertString(boolean[] includeProperty) {
Insert insert = identityDelegate.prepareIdentifierGeneratingInsert();
insert.setTableName( getTableName( 0 ) );
// add normal properties
for ( int i = 0; i < entityMetamodel.getPropertySpan(); i++ ) {
if ( includeProperty[i] && isPropertyOfTable( i, 0 ) ) {
// this property belongs on the table and is to be inserted
insert.addColumns( getPropertyColumnNames(i), propertyColumnInsertable[i] );
}
}
// add the discriminator
addDiscriminatorToInsert( insert );
// delegate already handles PK columns
if ( getFactory().getSettings().isCommentsEnabled() ) {
insert.setComment( "insert " + getEntityName() );
}
return insert.toStatementString();
}
Used to generate an insery statement against the root table in the
case of identifier generation strategies where the insert statement
executions actually generates the identifier value. |
protected String generateInsertGeneratedValuesSelectString() {
return generateGeneratedValuesSelectString( getPropertyInsertGenerationInclusions() );
}
|
protected String generateInsertString(boolean[] includeProperty,
int j) {
return generateInsertString( false, includeProperty, j );
}
|
protected String generateInsertString(boolean identityInsert,
boolean[] includeProperty) {
return generateInsertString( identityInsert, includeProperty, 0 );
}
|
protected String generateInsertString(boolean identityInsert,
boolean[] includeProperty,
int j) {
// todo : remove the identityInsert param and variations;
// identity-insert strings are now generated from generateIdentityInsertString()
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 inserts a row |
protected String generateLazySelectString() {
if ( !entityMetamodel.hasLazyProperties() ) {
return null;
}
HashSet tableNumbers = new HashSet();
ArrayList columnNumbers = new ArrayList();
ArrayList formulaNumbers = new ArrayList();
for ( int i = 0; i < lazyPropertyNames.length; i++ ) {
// all this only really needs to consider properties
// of this class, not its subclasses, but since we
// are reusing code used for sequential selects, we
// use the subclass closure
int propertyNumber = getSubclassPropertyIndex( lazyPropertyNames[i] );
int tableNumber = getSubclassPropertyTableNumber( propertyNumber );
tableNumbers.add( new Integer( tableNumber ) );
int[] colNumbers = subclassPropertyColumnNumberClosure[propertyNumber];
for ( int j = 0; j < colNumbers.length; j++ ) {
if ( colNumbers[j]!=-1 ) {
columnNumbers.add( new Integer( colNumbers[j] ) );
}
}
int[] formNumbers = subclassPropertyFormulaNumberClosure[propertyNumber];
for ( int j = 0; j < formNumbers.length; j++ ) {
if ( formNumbers[j]!=-1 ) {
formulaNumbers.add( new Integer( formNumbers[j] ) );
}
}
}
if ( columnNumbers.size()==0 && formulaNumbers.size()==0 ) {
// only one-to-one is lazy fetched
return null;
}
return renderSelect( ArrayHelper.toIntArray( tableNumbers ),
ArrayHelper.toIntArray( columnNumbers ),
ArrayHelper.toIntArray( formulaNumbers ) );
}
|
protected LockingStrategy generateLocker(LockMode lockMode) {
return factory.getDialect().getLockingStrategy( this, lockMode );
}
|
protected String generateSelectVersionString() {
SimpleSelect select = new SimpleSelect( getFactory().getDialect() )
.setTableName( getVersionedTableName() );
if ( isVersioned() ) {
select.addColumn( versionColumnName );
}
else {
select.addColumns( rootTableKeyColumnNames );
}
if ( getFactory().getSettings().isCommentsEnabled() ) {
select.setComment( "get version " + getEntityName() );
}
return select.addCondition( rootTableKeyColumnNames, "=?" ).toStatementString();
}
Generate the SQL that selects the version number by id |
protected String generateSnapshotSelectString() {
//TODO: should we use SELECT .. FOR UPDATE?
Select select = new Select( getFactory().getDialect() );
if ( getFactory().getSettings().isCommentsEnabled() ) {
select.setComment( "get current state " + getEntityName() );
}
String[] aliasedIdColumns = StringHelper.qualify( getRootAlias(), getIdentifierColumnNames() );
String selectClause = StringHelper.join( ", ", aliasedIdColumns ) +
concretePropertySelectFragment( getRootAlias(), getPropertyUpdateability() );
String fromClause = fromTableFragment( getRootAlias() ) +
fromJoinFragment( getRootAlias(), true, false );
String whereClause = new StringBuffer()
.append( StringHelper.join( "=? and ",
aliasedIdColumns ) )
.append( "=?" )
.append( whereJoinFragment( getRootAlias(), true, false ) )
.toString();
/*if ( isVersioned() ) {
where.append(" and ")
.append( getVersionColumnName() )
.append("=?");
}*/
return select.setSelectClause( selectClause )
.setFromClause( fromClause )
.setOuterJoins( "", "" )
.setWhereClause( whereClause )
.toStatementString();
}
|
protected String generateTableAlias(String rootAlias,
int tableNumber) {
if ( tableNumber == 0 ) {
return rootAlias;
}
StringBuffer buf = new StringBuffer().append( rootAlias );
if ( !rootAlias.endsWith( "_" ) ) {
buf.append( '_" );
}
return buf.append( tableNumber ).append( '_" ).toString();
}
|
protected String generateUpdateGeneratedValuesSelectString() {
return generateGeneratedValuesSelectString( getPropertyUpdateGenerationInclusions() );
}
|
protected String generateUpdateString(boolean[] includeProperty,
int j,
boolean useRowId) {
return generateUpdateString( includeProperty, j, null, useRowId );
}
|
protected String generateUpdateString(boolean[] includeProperty,
int j,
Object[] oldFields,
boolean useRowId) {
Update update = new Update( getFactory().getDialect() ).setTableName( getTableName( j ) );
// select the correct row by either pk or rowid
if ( useRowId ) {
update.setPrimaryKeyColumnNames( new String[]{rowIdName} ); //TODO: eventually, rowIdName[j]
}
else {
update.setPrimaryKeyColumnNames( getKeyColumns( j ) );
}
boolean hasColumns = false;
for ( int i = 0; i < entityMetamodel.getPropertySpan(); i++ ) {
if ( includeProperty[i] && isPropertyOfTable( i, j ) ) {
// this is a property of the table, which we are updating
update.addColumns( getPropertyColumnNames(i), propertyColumnUpdateable[i] );
hasColumns = hasColumns || getPropertyColumnSpan( i ) > 0;
}
}
if ( j == 0 && isVersioned() && entityMetamodel.getOptimisticLockMode() == Versioning.OPTIMISTIC_LOCK_VERSION ) {
// this is the root (versioned) table, and we are using version-based
// optimistic locking; if we are not updating the version, also don't
// check it (unless this is a "generated" version column)!
if ( checkVersion( includeProperty ) ) {
update.setVersionColumnName( getVersionColumnName() );
hasColumns = true;
}
}
else if ( entityMetamodel.getOptimisticLockMode() > Versioning.OPTIMISTIC_LOCK_VERSION && oldFields != null ) {
// we are using "all" or "dirty" property-based optimistic locking
boolean[] includeInWhere = entityMetamodel.getOptimisticLockMode() == Versioning.OPTIMISTIC_LOCK_ALL ?
getPropertyUpdateability() : //optimistic-lock="all", include all updatable properties
includeProperty; //optimistic-lock="dirty", include all properties we are updating this time
boolean[] versionability = getPropertyVersionability();
Type[] types = getPropertyTypes();
for ( int i = 0; i < entityMetamodel.getPropertySpan(); i++ ) {
boolean include = includeInWhere[i] &&
isPropertyOfTable( i, j ) &&
versionability[i];
if ( include ) {
// this property belongs to the table, and it is not specifically
// excluded from optimistic locking by optimistic-lock="false"
String[] propertyColumnNames = getPropertyColumnNames( i );
boolean[] propertyNullness = types[i].toColumnNullness( oldFields[i], getFactory() );
for ( int k=0; k< propertyNullness.length; k++ ) {
if ( propertyNullness[k] ) {
update.addWhereColumn( propertyColumnNames[k] );
}
else {
update.addWhereColumn( propertyColumnNames[k], " is null" );
}
}
}
}
}
if ( getFactory().getSettings().isCommentsEnabled() ) {
update.setComment( "update " + getEntityName() );
}
return hasColumns ? update.toStatementString() : null;
}
Generate the SQL that updates a row by id (and version) |
public EntityRegionAccessStrategy getCacheAccessStrategy() {
return cacheAccessStrategy;
}
|
public CacheEntryStructure getCacheEntryStructure() {
return cacheEntryStructure;
}
|
public CascadeStyle getCascadeStyle(int i) {
return subclassPropertyCascadeStyleClosure[i];
}
|
public ClassMetadata getClassMetadata() {
return this;
}
|
public Class getConcreteProxyClass(EntityMode entityMode) {
return getTuplizer( entityMode ).getConcreteProxyClass();
}
|
public Object getCurrentVersion(Serializable id,
SessionImplementor session) throws HibernateException {
if ( log.isTraceEnabled() ) {
log.trace( "Getting version: " + MessageHelper.infoString( this, id, getFactory() ) );
}
try {
PreparedStatement st = session.getBatcher().prepareSelectStatement( getVersionSelectString() );
try {
getIdentifierType().nullSafeSet( st, id, 1, session );
ResultSet rs = st.executeQuery();
try {
if ( !rs.next() ) {
return null;
}
if ( !isVersioned() ) {
return this;
}
return getVersionType().nullSafeGet( rs, getVersionColumnName(), session, null );
}
finally {
rs.close();
}
}
finally {
session.getBatcher().closeStatement( st );
}
}
catch ( SQLException sqle ) {
throw JDBCExceptionHelper.convert(
getFactory().getSQLExceptionConverter(),
sqle,
"could not retrieve version: " +
MessageHelper.infoString( this, id, getFactory() ),
getVersionSelectString()
);
}
}
Retrieve the version number |
public Object[] getDatabaseSnapshot(Serializable id,
SessionImplementor session) throws HibernateException {
if ( log.isTraceEnabled() ) {
log.trace( "Getting current persistent state for: " + MessageHelper.infoString( this, id, getFactory() ) );
}
try {
PreparedStatement ps = session.getBatcher().prepareSelectStatement( getSQLSnapshotSelectString() );
try {
getIdentifierType().nullSafeSet( ps, id, 1, session );
//if ( isVersioned() ) getVersionType().nullSafeSet( ps, version, getIdentifierColumnSpan()+1, session );
ResultSet rs = ps.executeQuery();
try {
//if there is no resulting row, return null
if ( !rs.next() ) {
return null;
}
//otherwise return the "hydrated" state (ie. associations are not resolved)
Type[] types = getPropertyTypes();
Object[] values = new Object[types.length];
boolean[] includeProperty = getPropertyUpdateability();
for ( int i = 0; i < types.length; i++ ) {
if ( includeProperty[i] ) {
values[i] = types[i].hydrate( rs, getPropertyAliases( "", i ), session, null ); //null owner ok??
}
}
return values;
}
finally {
rs.close();
}
}
finally {
session.getBatcher().closeStatement( ps );
}
}
catch ( SQLException sqle ) {
throw JDBCExceptionHelper.convert(
getFactory().getSQLExceptionConverter(),
sqle,
"could not retrieve snapshot: " +
MessageHelper.infoString( this, id, getFactory() ),
getSQLSnapshotSelectString()
);
}
}
|
protected String getDiscriminatorAlias() {
return DISCRIMINATOR_ALIAS;
}
|
public String getDiscriminatorAlias(String suffix) {
// NOTE: this assumes something about how propertySelectFragment is implemented by the subclass!
// was toUnqotedAliasStrings( getdiscriminatorColumnName() ) before - now tried
// to remove that unqoting and missing aliases..
return entityMetamodel.hasSubclasses() ?
new Alias( suffix ).toAliasString( getDiscriminatorAlias() ) :
null;
}
|
public String getDiscriminatorColumnName() {
return DISCRIMINATOR_ALIAS;
}
|
protected String getDiscriminatorFormulaTemplate() {
return null;
}
|
public EntityMetamodel getEntityMetamodel() {
return entityMetamodel;
}
|
public final String getEntityName() {
return entityMetamodel.getName();
}
|
public EntityType getEntityType() {
return entityMetamodel.getEntityType();
}
|
public SessionFactoryImplementor getFactory() {
return factory;
}
|
public FetchMode getFetchMode(int i) {
return subclassPropertyFetchModeClosure[i];
}
|
public Serializable getIdentifier(Object object,
EntityMode entityMode) throws HibernateException {
return getTuplizer( entityMode ).getIdentifier( object );
}
|
protected String[] getIdentifierAliases() {
return identifierAliases;
}
|
public String[] getIdentifierAliases(String suffix) {
// NOTE: this assumes something about how propertySelectFragment is implemented by the subclass!
// was toUnqotedAliasStrings( getIdentiferColumnNames() ) before - now tried
// to remove that unqoting and missing aliases..
return new Alias( suffix ).toAliasStrings( getIdentifierAliases() );
}
|
public String[] getIdentifierColumnNames() {
return rootTableKeyColumnNames;
}
|
protected int getIdentifierColumnSpan() {
return identifierColumnSpan;
}
|
public IdentifierGenerator getIdentifierGenerator() throws HibernateException {
return entityMetamodel.getIdentifierProperty().getIdentifierGenerator();
}
|
public String getIdentifierPropertyName() {
return entityMetamodel.getIdentifierProperty().getName();
}
|
public Type getIdentifierType() {
return entityMetamodel.getIdentifierProperty().getType();
}
|
public String getIdentitySelectString() {
//TODO: cache this in an instvar
return getFactory().getDialect().getIdentitySelectString(
getTableName(0),
getKeyColumns(0)[0],
getIdentifierType().sqlTypes( getFactory() )[0]
);
}
|
public String[] getKeyColumnNames() {
return getIdentifierColumnNames();
}
|
abstract protected String[] getKeyColumns(int j)
|
protected Set getLazyProperties() {
return lazyProperties;
}
|
public final Class getMappedClass(EntityMode entityMode) {
Tuplizer tup = entityMetamodel.getTuplizerOrNull(entityMode);
return tup==null ? null : tup.getMappedClass();
}
|
public String getMappedSuperclass() {
return entityMetamodel.getSuperclass();
}
|
public String getName() {
return getEntityName();
}
|
public int[] getNaturalIdentifierProperties() {
return entityMetamodel.getNaturalIdentifierProperties();
}
|
public Object[] getNaturalIdentifierSnapshot(Serializable id,
SessionImplementor session) throws HibernateException {
if ( !hasNaturalIdentifier() ) {
throw new MappingException( "persistent class did not define a natural-id : " + MessageHelper.infoString( this ) );
}
if ( log.isTraceEnabled() ) {
log.trace( "Getting current natural-id snapshot state for: " + MessageHelper.infoString( this, id, getFactory() ) );
}
int[] naturalIdPropertyIndexes = getNaturalIdentifierProperties();
int naturalIdPropertyCount = naturalIdPropertyIndexes.length;
boolean[] naturalIdMarkers = new boolean[ getPropertySpan() ];
Type[] extractionTypes = new Type[ naturalIdPropertyCount ];
for ( int i = 0; i < naturalIdPropertyCount; i++ ) {
extractionTypes[i] = getPropertyTypes()[ naturalIdPropertyIndexes[i] ];
naturalIdMarkers[ naturalIdPropertyIndexes[i] ] = true;
}
///////////////////////////////////////////////////////////////////////
// TODO : look at perhaps caching this...
Select select = new Select( getFactory().getDialect() );
if ( getFactory().getSettings().isCommentsEnabled() ) {
select.setComment( "get current natural-id state " + getEntityName() );
}
select.setSelectClause( concretePropertySelectFragmentSansLeadingComma( getRootAlias(), naturalIdMarkers ) );
select.setFromClause( fromTableFragment( getRootAlias() ) + fromJoinFragment( getRootAlias(), true, false ) );
String[] aliasedIdColumns = StringHelper.qualify( getRootAlias(), getIdentifierColumnNames() );
String whereClause = new StringBuffer()
.append( StringHelper.join( "=? and ",
aliasedIdColumns ) )
.append( "=?" )
.append( whereJoinFragment( getRootAlias(), true, false ) )
.toString();
String sql = select.setOuterJoins( "", "" )
.setWhereClause( whereClause )
.toStatementString();
///////////////////////////////////////////////////////////////////////
Object[] snapshot = new Object[ naturalIdPropertyCount ];
try {
PreparedStatement ps = session.getBatcher().prepareSelectStatement( sql );
try {
getIdentifierType().nullSafeSet( ps, id, 1, session );
ResultSet rs = ps.executeQuery();
try {
//if there is no resulting row, return null
if ( !rs.next() ) {
return null;
}
for ( int i = 0; i < naturalIdPropertyCount; i++ ) {
snapshot[i] = extractionTypes[i].hydrate( rs, getPropertyAliases( "", naturalIdPropertyIndexes[i] ), session, null );
}
return snapshot;
}
finally {
rs.close();
}
}
finally {
session.getBatcher().closeStatement( ps );
}
}
catch ( SQLException sqle ) {
throw JDBCExceptionHelper.convert(
getFactory().getSQLExceptionConverter(),
sqle,
"could not retrieve snapshot: " +
MessageHelper.infoString( this, id, getFactory() ),
sql
);
}
}
|
public boolean[] getNonLazyPropertyUpdateability() {
return entityMetamodel.getNonlazyPropertyUpdateability();
}
|
protected boolean[] getPropertiesToInsert(Object[] fields) {
boolean[] notNull = new boolean[fields.length];
boolean[] insertable = getPropertyInsertability();
for ( int i = 0; i < fields.length; i++ ) {
notNull[i] = insertable[i] && fields[i] != null;
}
return notNull;
}
Transform the array of property indexes to an array of booleans,
true when the property is insertable and non-null |
protected final boolean[] getPropertiesToUpdate(int[] dirtyProperties,
boolean hasDirtyCollection) {
final boolean[] propsToUpdate = new boolean[ entityMetamodel.getPropertySpan() ];
final boolean[] updateability = getPropertyUpdateability(); //no need to check laziness, dirty checking handles that
for ( int j = 0; j < dirtyProperties.length; j++ ) {
int property = dirtyProperties[j];
if ( updateability[property] ) {
propsToUpdate[property] = true;
}
}
if ( isVersioned() ) {
propsToUpdate[ getVersionProperty() ] =
Versioning.isVersionIncrementRequired( dirtyProperties, hasDirtyCollection, getPropertyVersionability() );
}
return propsToUpdate;
}
Transform the array of property indexes to an array of booleans,
true when the property is dirty |
public String[] getPropertyAliases(String suffix,
int i) {
// NOTE: this assumes something about how propertySelectFragment is implemented by the subclass!
return new Alias( suffix ).toUnquotedAliasStrings( propertyColumnAliases[i] );
}
|
public CascadeStyle[] getPropertyCascadeStyles() {
return entityMetamodel.getCascadeStyles();
}
|
public boolean[] getPropertyCheckability() {
return entityMetamodel.getPropertyCheckability();
}
|
public String[] getPropertyColumnNames(String propertyName) {
return propertyMapping.getColumnNames( propertyName );
}
|
public String[] getPropertyColumnNames(int i) {
return propertyColumnNames[i];
}
|
protected int getPropertyColumnSpan(int i) {
return propertyColumnSpans[i];
}
|
public int getPropertyIndex(String propertyName) {
return entityMetamodel.getPropertyIndex(propertyName);
}
|
public ValueInclusion[] getPropertyInsertGenerationInclusions() {
return entityMetamodel.getPropertyInsertGenerationInclusions();
}
|
public boolean[] getPropertyInsertability() {
return entityMetamodel.getPropertyInsertability();
}
|
public boolean[] getPropertyLaziness() {
return entityMetamodel.getPropertyLaziness();
}
|
public String[] getPropertyNames() {
return entityMetamodel.getPropertyNames();
}
|
public boolean[] getPropertyNullability() {
return entityMetamodel.getPropertyNullability();
}
|
protected int getPropertySpan() {
return entityMetamodel.getPropertySpan();
}
|
protected String[] getPropertySubclassNames() {
return propertySubclassNames;
}
|
abstract protected int[] getPropertyTableNumbers()
|
abstract protected int[] getPropertyTableNumbersInSelect()
|
public Type getPropertyType(String propertyName) throws MappingException {
return propertyMapping.toType(propertyName);
}
|
public Type[] getPropertyTypes() {
return entityMetamodel.getPropertyTypes();
}
|
public ValueInclusion[] getPropertyUpdateGenerationInclusions() {
return entityMetamodel.getPropertyUpdateGenerationInclusions();
}
|
public boolean[] getPropertyUpdateability() {
return entityMetamodel.getPropertyUpdateability();
}
|
protected boolean[] getPropertyUpdateability(Object entity,
EntityMode entityMode) {
return hasUninitializedLazyProperties( entity, entityMode ) ?
getNonLazyPropertyUpdateability() :
getPropertyUpdateability();
}
Which properties appear in the SQL update?
(Initialized, updateable ones!) |
public Object getPropertyValue(Object object,
int i,
EntityMode entityMode) throws HibernateException {
return getTuplizer( entityMode ).getPropertyValue( object , i );
}
|
public Object getPropertyValue(Object object,
String propertyName,
EntityMode entityMode) throws HibernateException {
return getTuplizer( entityMode ).getPropertyValue( object, propertyName );
}
|
public Object[] getPropertyValues(Object object,
EntityMode entityMode) throws HibernateException {
return getTuplizer( entityMode ).getPropertyValues( object );
}
|
public Object[] getPropertyValuesToInsert(Object object,
Map mergeMap,
SessionImplementor session) throws HibernateException {
return getTuplizer( session.getEntityMode() ).getPropertyValuesToInsert( object, mergeMap, session );
}
|
public boolean[] getPropertyVersionability() {
return entityMetamodel.getPropertyVersionability();
}
|
public Serializable[] getQuerySpaces() {
return getPropertySpaces();
}
|
public String getRootEntityName() {
return entityMetamodel.getRootName();
}
|
public String getRootTableAlias(String drivingAlias) {
return drivingAlias;
}
|
public String[] getRootTableIdentifierColumnNames() {
return getRootTableKeyColumnNames();
}
|
public String[] getRootTableKeyColumnNames() {
return rootTableKeyColumnNames;
}
|
public String getRootTableName() {
return getSubclassTableName( 0 );
}
|
protected String[] getSQLDeleteStrings() {
return sqlDeleteStrings;
}
|
protected String getSQLIdentityInsertString() {
return sqlIdentityInsertString;
}
The query that inserts a row, letting the database generate an id |
protected String[] getSQLInsertStrings() {
return sqlInsertStrings;
}
|
protected String getSQLLazySelectString() {
return sqlLazySelectString;
}
|
protected String[] getSQLLazyUpdateByRowIdStrings() {
if ( sqlLazyUpdateByRowIdString == null ) {
throw new AssertionFailure( "no update by row id" );
}
String[] result = new String[getTableSpan()];
result[0] = sqlLazyUpdateByRowIdString;
for ( int i = 1; i < getTableSpan(); i++ ) {
result[i] = sqlLazyUpdateStrings[i];
}
return result;
}
|
protected String[] getSQLLazyUpdateStrings() {
return sqlLazyUpdateStrings;
}
|
protected String getSQLSnapshotSelectString() {
return sqlSnapshotSelectString;
}
|
protected String[] getSQLUpdateByRowIdStrings() {
if ( sqlUpdateByRowIdString == null ) {
throw new AssertionFailure( "no update by row id" );
}
String[] result = new String[getTableSpan() + 1];
result[0] = sqlUpdateByRowIdString;
System.arraycopy( sqlUpdateStrings, 0, result, 1, getTableSpan() );
return result;
}
|
protected String[] getSQLUpdateStrings() {
return sqlUpdateStrings;
}
|
protected String getSQLWhereString(String alias) {
return StringHelper.replace( sqlWhereStringTemplate, Template.TEMPLATE, alias );
}
|
public String getSelectByUniqueKeyString(String propertyName) {
return new SimpleSelect( getFactory().getDialect() )
.setTableName( getTableName(0) )
.addColumns( getKeyColumns(0) )
.addCondition( getPropertyColumnNames(propertyName), "=?" )
.toStatementString();
}
|
protected String getSequentialSelect(String entityName) {
throw new UnsupportedOperationException("no sequential selects");
}
|
protected String[] getSubclassColumnAliasClosure() {
return subclassColumnAliasClosure;
}
|
protected String[] getSubclassColumnClosure() {
return subclassColumnClosure;
}
|
protected boolean[] getSubclassColumnLazyiness() {
return subclassColumnLazyClosure;
}
|
abstract protected int[] getSubclassColumnTableNumberClosure()
|
public EntityPersister getSubclassEntityPersister(Object instance,
SessionFactoryImplementor factory,
EntityMode entityMode) {
if ( !hasSubclasses() ) {
return this;
}
else {
// TODO : really need a way to do something like :
// getTuplizer(entityMode).determineConcreteSubclassEntityName(instance)
Class clazz = instance.getClass();
if ( clazz == getMappedClass( entityMode ) ) {
return this;
}
else {
String subclassEntityName = getSubclassEntityName( clazz );
if ( subclassEntityName == null ) {
throw new HibernateException(
"instance not of expected entity type: " + clazz.getName() +
" is not a: " + getEntityName()
);
}
else {
return factory.getEntityPersister( subclassEntityName );
}
}
}
}
|
protected String[] getSubclassFormulaAliasClosure() {
return subclassFormulaAliasClosure;
}
|
protected String[] getSubclassFormulaClosure() {
return subclassFormulaClosure;
}
|
protected boolean[] getSubclassFormulaLazyiness() {
return subclassFormulaLazyClosure;
}
|
abstract protected int[] getSubclassFormulaTableNumberClosure()
|
protected String[] getSubclassFormulaTemplateClosure() {
return subclassFormulaTemplateClosure;
}
|
public String[] getSubclassPropertyColumnAliases(String propertyName,
String suffix) {
String rawAliases[] = ( String[] ) subclassPropertyAliases.get( propertyName );
if ( rawAliases == null ) {
return null;
}
String result[] = new String[rawAliases.length];
for ( int i = 0; i < rawAliases.length; i++ ) {
result[i] = new Alias( suffix ).toUnquotedAliasString( rawAliases[i] );
}
return result;
}
|
protected String[][] getSubclassPropertyColumnNameClosure() {
return subclassPropertyColumnNameClosure;
}
|
public String[] getSubclassPropertyColumnNames(int i) {
return subclassPropertyColumnNameClosure[i];
}
|
public String[] getSubclassPropertyColumnNames(String propertyName) {
//TODO: should we allow suffixes on these ?
return ( String[] ) subclassPropertyColumnNames.get( propertyName );
}
|
public Declarer getSubclassPropertyDeclarer(String propertyPath) {
int tableIndex = getSubclassPropertyTableNumber( propertyPath );
if ( tableIndex == 0 ) {
return Declarer.CLASS;
}
else if ( isClassOrSuperclassTable( tableIndex ) ) {
return Declarer.SUPERCLASS;
}
else {
return Declarer.SUBCLASS;
}
}
|
protected String[][] getSubclassPropertyFormulaTemplateClosure() {
return subclassPropertyFormulaTemplateClosure;
}
|
public String getSubclassPropertyName(int i) {
return subclassPropertyNameClosure[i];
}
|
protected String[] getSubclassPropertyNameClosure() {
return subclassPropertyNameClosure;
}
|
protected String[] getSubclassPropertySubclassNameClosure() {
return subclassPropertySubclassNameClosure;
}
|
abstract protected int getSubclassPropertyTableNumber(int i)
|
public int getSubclassPropertyTableNumber(String propertyPath) {
String rootPropertyName = StringHelper.root(propertyPath);
Type type = propertyMapping.toType(rootPropertyName);
if ( type.isAssociationType() ) {
AssociationType assocType = ( AssociationType ) type;
if ( assocType.useLHSPrimaryKey() ) {
// performance op to avoid the array search
return 0;
}
else if ( type.isCollectionType() ) {
// properly handle property-ref-based associations
rootPropertyName = assocType.getLHSPropertyName();
}
}
//Enable for HHH-440, which we don't like:
/*if ( type.isComponentType() && !propertyName.equals(rootPropertyName) ) {
String unrooted = StringHelper.unroot(propertyName);
int idx = ArrayHelper.indexOf( getSubclassColumnClosure(), unrooted );
if ( idx != -1 ) {
return getSubclassColumnTableNumberClosure()[idx];
}
}*/
int index = ArrayHelper.indexOf( getSubclassPropertyNameClosure(), rootPropertyName); //TODO: optimize this better!
return index==-1 ? 0 : getSubclassPropertyTableNumber(index);
}
Warning:
When there are duplicated property names in the subclasses
of the class, this method may return the wrong table
number for the duplicated subclass property (note that
SingleTableEntityPersister defines an overloaded form
which takes the entity name. |
public Type getSubclassPropertyType(int i) {
return subclassPropertyTypeClosure[i];
}
|
protected Type[] getSubclassPropertyTypeClosure() {
return subclassPropertyTypeClosure;
}
|
abstract protected String[] getSubclassTableKeyColumns(int j)
|
abstract public String getSubclassTableName(int j)
|
abstract protected int getSubclassTableSpan()
|
abstract protected String getTableName(int j)
|
abstract protected int getTableSpan()
|
protected boolean[] getTableUpdateNeeded(int[] dirtyProperties,
boolean hasDirtyCollection) {
if ( dirtyProperties == null ) {
return getTableHasColumns(); // for objects that came in via update()
}
else {
boolean[] updateability = getPropertyUpdateability();
int[] propertyTableNumbers = getPropertyTableNumbers();
boolean[] tableUpdateNeeded = new boolean[ getTableSpan() ];
for ( int i = 0; i < dirtyProperties.length; i++ ) {
int property = dirtyProperties[i];
int table = propertyTableNumbers[property];
tableUpdateNeeded[table] = tableUpdateNeeded[table] ||
( getPropertyColumnSpan(property) > 0 && updateability[property] );
}
if ( isVersioned() ) {
tableUpdateNeeded[0] = tableUpdateNeeded[0] ||
Versioning.isVersionIncrementRequired( dirtyProperties, hasDirtyCollection, getPropertyVersionability() );
}
return tableUpdateNeeded;
}
}
Decide which tables need to be updated.
The return here is an array of boolean values with each index corresponding
to a given table in the scope of this persister. |
public String getTemporaryIdTableDDL() {
return temporaryIdTableDDL;
}
|
public String getTemporaryIdTableName() {
return temporaryIdTableName;
}
|
protected EntityTuplizer getTuplizer(SessionImplementor session) {
return getTuplizer( session.getEntityMode() );
}
|
protected EntityTuplizer getTuplizer(EntityMode entityMode) {
return entityMetamodel.getTuplizer( entityMode );
}
|
public Type getType() {
return entityMetamodel.getEntityType();
}
|
public Object getVersion(Object object,
EntityMode entityMode) throws HibernateException {
return getTuplizer( entityMode ).getVersion( object );
}
|
public String getVersionColumnName() {
return versionColumnName;
}
|
public Comparator getVersionComparator() {
return isVersioned() ? getVersionType().getComparator() : null;
}
|
public int getVersionProperty() {
return entityMetamodel.getVersionPropertyIndex();
}
|
protected String getVersionSelectString() {
return sqlVersionSelectString;
}
|
public VersionType getVersionType() {
return ( VersionType ) locateVersionType();
}
|
protected String getVersionedTableName() {
return getTableName( 0 );
}
|
public EntityMode guessEntityMode(Object object) {
return entityMetamodel.guessEntityMode(object);
}
|
public boolean hasCache() {
return cacheAccessStrategy != null;
}
|
public boolean hasCascades() {
return entityMetamodel.hasCascades();
}
|
public boolean hasCollections() {
return entityMetamodel.hasCollections();
}
|
protected boolean hasEmbeddedCompositeIdentifier() {
return entityMetamodel.getIdentifierProperty().isEmbedded();
}
|
protected boolean hasFormulaProperties() {
return hasFormulaProperties;
}
|
public boolean hasIdentifierProperty() {
return !entityMetamodel.getIdentifierProperty().isVirtual();
}
|
public boolean hasInsertGeneratedProperties() {
return entityMetamodel.hasInsertGeneratedValues();
}
|
public boolean hasLazyProperties() {
return entityMetamodel.hasLazyProperties();
}
|
public boolean hasMutableProperties() {
return entityMetamodel.hasMutableProperties();
}
|
public boolean hasNaturalIdentifier() {
return entityMetamodel.hasNaturalIdentifier();
}
|
public boolean hasProxy() {
return entityMetamodel.isLazy();
}
|
public boolean hasRowId() {
return rowIdName != null;
}
|
public boolean hasSequentialSelect() {
return false;
}
|
public boolean hasSubclasses() {
return entityMetamodel.hasSubclasses();
}
|
public boolean hasSubselectLoadableCollections() {
return hasSubselectLoadableCollections;
}
|
public boolean hasUninitializedLazyProperties(Object object,
EntityMode entityMode) {
return getTuplizer( entityMode ).hasUninitializedLazyProperties( object );
}
|
public boolean hasUpdateGeneratedProperties() {
return entityMetamodel.hasUpdateGeneratedValues();
}
|
protected boolean hasWhere() {
return sqlWhereString != null;
}
|
public Object[] hydrate(ResultSet rs,
Serializable id,
Object object,
Loadable rootLoadable,
String[][] suffixedPropertyColumns,
boolean allProperties,
SessionImplementor session) throws HibernateException, SQLException {
if ( log.isTraceEnabled() ) {
log.trace( "Hydrating entity: " + MessageHelper.infoString( this, id, getFactory() ) );
}
final AbstractEntityPersister rootPersister = (AbstractEntityPersister) rootLoadable;
final boolean hasDeferred = rootPersister.hasSequentialSelect();
PreparedStatement sequentialSelect = null;
ResultSet sequentialResultSet = null;
boolean sequentialSelectEmpty = false;
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();
if ( !sequentialResultSet.next() ) {
// TODO: Deal with the "optional" attribute in the < join > mapping;
// this code assumes that optional defaults to "true" because it
// doesn't actually seem to work in the fetch="join" code
//
// Note that actual proper handling of optional-ality here is actually
// more involved than this patch assumes. Remember that we might have
// multiple < join/ > mappings associated with a single entity. Really
// a couple of things need to happen to properly handle optional here:
// 1) First and foremost, when handling multiple < join/ >s, we really
// should be using the entity root table as the driving table;
// another option here would be to choose some non-optional joined
// table to use as the driving table. In all likelihood, just using
// the root table is much simplier
// 2) Need to add the FK columns corresponding to each joined table
// to the generated select list; these would then be used when
// iterating the result set to determine whether all non-optional
// data is present
// My initial thoughts on the best way to deal with this would be
// to introduce a new SequentialSelect abstraction that actually gets
// generated in the persisters (ok, SingleTable...) and utilized here.
// It would encapsulated all this required optional-ality checking...
sequentialSelectEmpty = true;
}
}
}
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] );
if ( propertyIsDeferred && sequentialSelectEmpty ) {
values[i] = null;
}
else {
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 );
}
}
}
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 String identifierSelectFragment(String name,
String suffix) {
return new SelectFragment()
.setSuffix( suffix )
.addColumns( name, getIdentifierColumnNames(), getIdentifierAliases() )
.toFragmentString()
.substring( 2 ); //strip leading ", "
}
|
public boolean implementsLifecycle(EntityMode entityMode) {
return getTuplizer( entityMode ).isLifecycleImplementor();
}
|
public boolean implementsValidatable(EntityMode entityMode) {
return getTuplizer( entityMode ).isValidatableImplementor();
}
|
protected void initLockers() {
lockers.put( LockMode.READ, generateLocker( LockMode.READ ) );
lockers.put( LockMode.UPGRADE, generateLocker( LockMode.UPGRADE ) );
lockers.put( LockMode.UPGRADE_NOWAIT, generateLocker( LockMode.UPGRADE_NOWAIT ) );
lockers.put( LockMode.FORCE, generateLocker( LockMode.FORCE ) );
}
|
protected void initPropertyPaths(Mapping mapping) throws MappingException {
initOrdinaryPropertyPaths(mapping);
initOrdinaryPropertyPaths(mapping); //do two passes, for collection property-ref!
initIdentifierPropertyPaths(mapping);
if ( entityMetamodel.isPolymorphic() ) {
initDiscriminatorPropertyPath( mapping );
}
}
|
protected void initSubclassPropertyAliasesMap(PersistentClass model) throws MappingException {
// ALIASES
internalInitSubclassPropertyAliasesMap( null, model.getSubclassPropertyClosureIterator() );
// aliases for identifier ( alias.id ); skip if the entity defines a non-id property named 'id'
if ( ! entityMetamodel.hasNonIdentifierPropertyNamedId() ) {
subclassPropertyAliases.put( ENTITY_ID, getIdentifierAliases() );
subclassPropertyColumnNames.put( ENTITY_ID, getIdentifierColumnNames() );
}
// aliases named identifier ( alias.idname )
if ( hasIdentifierProperty() ) {
subclassPropertyAliases.put( getIdentifierPropertyName(), getIdentifierAliases() );
subclassPropertyColumnNames.put( getIdentifierPropertyName(), getIdentifierColumnNames() );
}
// aliases for composite-id's
if ( getIdentifierType().isComponentType() ) {
// Fetch embedded identifiers propertynames from the "virtual" identifier component
AbstractComponentType componentId = ( AbstractComponentType ) getIdentifierType();
String[] idPropertyNames = componentId.getPropertyNames();
String[] idAliases = getIdentifierAliases();
String[] idColumnNames = getIdentifierColumnNames();
for ( int i = 0; i < idPropertyNames.length; i++ ) {
if ( entityMetamodel.hasNonIdentifierPropertyNamedId() ) {
subclassPropertyAliases.put(
ENTITY_ID + "." + idPropertyNames[i],
new String[] { idAliases[i] }
);
subclassPropertyColumnNames.put(
ENTITY_ID + "." + getIdentifierPropertyName() + "." + idPropertyNames[i],
new String[] { idColumnNames[i] }
);
}
// if (hasIdentifierProperty() && !ENTITY_ID.equals( getIdentifierPropertyName() ) ) {
if ( hasIdentifierProperty() ) {
subclassPropertyAliases.put(
getIdentifierPropertyName() + "." + idPropertyNames[i],
new String[] { idAliases[i] }
);
subclassPropertyColumnNames.put(
getIdentifierPropertyName() + "." + idPropertyNames[i],
new String[] { idColumnNames[i] }
);
}
else {
// embedded composite ids ( alias.idname1, alias.idname2 )
subclassPropertyAliases.put( idPropertyNames[i], new String[] { idAliases[i] } );
subclassPropertyColumnNames.put( idPropertyNames[i], new String[] { idColumnNames[i] } );
}
}
}
if ( entityMetamodel.isPolymorphic() ) {
subclassPropertyAliases.put( ENTITY_CLASS, new String[] { getDiscriminatorAlias() } );
subclassPropertyColumnNames.put( ENTITY_CLASS, new String[] { getDiscriminatorColumnName() } );
}
}
Must be called by subclasses, at the end of their constructors |
public Object initializeLazyProperty(String fieldName,
Object entity,
SessionImplementor session) throws HibernateException {
final Serializable id = session.getContextEntityIdentifier( entity );
final EntityEntry entry = session.getPersistenceContext().getEntry( entity );
if ( entry == null ) {
throw new HibernateException( "entity is not associated with the session: " + id );
}
if ( log.isTraceEnabled() ) {
log.trace(
"initializing lazy properties of: " +
MessageHelper.infoString( this, id, getFactory() ) +
", field access: " + fieldName
);
}
if ( hasCache() ) {
CacheKey cacheKey = new CacheKey(id, getIdentifierType(), getEntityName(), session.getEntityMode(), getFactory() );
Object ce = getCacheAccessStrategy().get( cacheKey, session.getTimestamp() );
if (ce!=null) {
CacheEntry cacheEntry = (CacheEntry) getCacheEntryStructure().destructure(ce, factory);
if ( !cacheEntry.areLazyPropertiesUnfetched() ) {
//note early exit here:
return initializeLazyPropertiesFromCache( fieldName, entity, session, entry, cacheEntry );
}
}
}
return initializeLazyPropertiesFromDatastore( fieldName, entity, session, id, entry );
}
|
public Serializable insert(Object[] fields,
Object object,
SessionImplementor session) throws HibernateException {
final int span = getTableSpan();
final Serializable id;
if ( entityMetamodel.isDynamicInsert() ) {
// For the case of dynamic-insert="true", we need to generate the INSERT SQL
boolean[] notNull = getPropertiesToInsert( fields );
id = insert( fields, notNull, generateInsertString( true, notNull ), object, session );
for ( int j = 1; j < span; j++ ) {
insert( id, fields, notNull, j, generateInsertString( notNull, j ), object, session );
}
}
else {
// For the case of dynamic-insert="false", use the static SQL
id = insert( fields, getPropertyInsertability(), getSQLIdentityInsertString(), object, session );
for ( int j = 1; j < span; j++ ) {
insert( id, fields, getPropertyInsertability(), j, getSQLInsertStrings()[j], object, session );
}
}
return id;
}
|
public void insert(Serializable id,
Object[] fields,
Object object,
SessionImplementor session) throws HibernateException {
final int span = getTableSpan();
if ( entityMetamodel.isDynamicInsert() ) {
// For the case of dynamic-insert="true", we need to generate the INSERT SQL
boolean[] notNull = getPropertiesToInsert( fields );
for ( int j = 0; j < span; j++ ) {
insert( id, fields, notNull, j, generateInsertString( notNull, j ), object, session );
}
}
else {
// For the case of dynamic-insert="false", use the static SQL
for ( int j = 0; j < span; j++ ) {
insert( id, fields, getPropertyInsertability(), j, getSQLInsertStrings()[j], object, session );
}
}
}
|
protected Serializable insert(Object[] fields,
boolean[] notNull,
String sql,
Object object,
SessionImplementor session) throws HibernateException {
if ( log.isTraceEnabled() ) {
log.trace( "Inserting entity: " + getEntityName() + " (native id)" );
if ( isVersioned() ) {
log.trace( "Version: " + Versioning.getVersion( fields, this ) );
}
}
Binder binder = new Binder() {
public void bindValues(PreparedStatement ps) throws SQLException {
dehydrate( null, fields, notNull, propertyColumnInsertable, 0, ps, session );
}
public Object getEntity() {
return object;
}
};
return identityDelegate.performInsert( sql, session, binder );
}
Perform an SQL INSERT, and then retrieve a generated identifier.
This form is used for PostInsertIdentifierGenerator-style ids (IDENTITY,
select, etc). |
protected void insert(Serializable id,
Object[] fields,
boolean[] notNull,
int j,
String sql,
Object object,
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 ) );
}
}
Expectation expectation = Expectations.appropriateExpectation( insertResultCheckStyles[j] );
boolean callable = isInsertCallable( j );
// we can't batch joined inserts, *especially* not if it is an identity insert;
// nor can we batch statements where the expectation is based on an output param
final boolean useBatch = j == 0 && expectation.canBeBatched();
try {
// Render the SQL query
final PreparedStatement insert;
if ( useBatch ) {
if ( callable ) {
insert = session.getBatcher().prepareBatchCallableStatement( sql );
}
else {
insert = session.getBatcher().prepareBatchStatement( sql );
}
}
else {
if ( callable ) {
insert = session.getBatcher().prepareCallableStatement( sql );
}
else {
insert = session.getBatcher().prepareStatement( sql );
}
}
try {
int index = 1;
index += expectation.prepare( 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 );
if ( useBatch ) {
// TODO : shouldnt inserts be Expectations.NONE?
session.getBatcher().addToBatch( expectation );
}
else {
expectation.verifyOutcome( insert.executeUpdate(), insert, -1 );
}
}
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 INSERT.
This for is used for all non-root tables as well as the root table
in cases where the identifier value is known before the insert occurs. |
public Object instantiate(Serializable id,
EntityMode entityMode) throws HibernateException {
return getTuplizer( entityMode ).instantiate( id );
}
|
public boolean isAbstract() {
return entityMetamodel.isAbstract();
}
|
public boolean isBatchLoadable() {
return batchSize > 1;
}
|
public boolean isBatchable() {
return optimisticLockMode()==Versioning.OPTIMISTIC_LOCK_NONE ||
( !isVersioned() && optimisticLockMode()==Versioning.OPTIMISTIC_LOCK_VERSION ) ||
getFactory().getSettings().isJdbcBatchVersionedData();
}
|
public boolean isCacheInvalidationRequired() {
return hasFormulaProperties() ||
( !isVersioned() && ( entityMetamodel.isDynamicUpdate() || getTableSpan() > 1 ) );
}
We can't immediately add to the cache if we have formulas
which must be evaluated, or if we have the possibility of
two concurrent updates to the same item being merged on
the database. This can happen if (a) the item is not
versioned and either (b) we have dynamic update enabled
or (c) we have multiple tables holding the state of the
item. |
abstract protected boolean isClassOrSuperclassTable(int j)
|
public boolean isCollection() {
return false;
}
|
public boolean isDefinedOnSubclass(int i) {
return propertyDefinedOnSubclass[i];
}
|
protected boolean isDeleteCallable(int j) {
return deleteCallable[j];
}
|
public boolean isExplicitPolymorphism() {
return entityMetamodel.isExplicitPolymorphism();
}
|
public boolean isIdentifierAssignedByInsert() {
return entityMetamodel.getIdentifierProperty().isIdentifierAssignedByInsert();
}
|
public boolean isInherited() {
return entityMetamodel.isInherited();
}
|
protected boolean isInsertCallable(int j) {
return insertCallable[j];
}
|
public boolean isInstance(Object object,
EntityMode entityMode) {
return getTuplizer( entityMode ).isInstance( object );
}
|
public boolean isInstrumented(EntityMode entityMode) {
EntityTuplizer tuplizer = entityMetamodel.getTuplizerOrNull(entityMode);
return tuplizer!=null && tuplizer.isInstrumented();
}
|
protected boolean isInverseSubclassTable(int j) {
return false;
}
|
protected boolean isInverseTable(int j) {
return false;
}
|
public boolean isLazyPropertiesCacheable() {
return isLazyPropertiesCacheable;
}
|
public boolean isMultiTable() {
return false;
}
|
public boolean isMutable() {
return entityMetamodel.isMutable();
}
|
protected boolean isNullableSubclassTable(int j) {
return false;
}
|
protected boolean isNullableTable(int j) {
return false;
}
|
public boolean isPolymorphic() {
return entityMetamodel.isPolymorphic();
}
|
abstract protected boolean isPropertyOfTable(int property,
int j)
|
public boolean isSelectBeforeUpdateRequired() {
return entityMetamodel.isSelectBeforeUpdate();
}
|
public boolean isSubclassEntityName(String entityName) {
return entityMetamodel.getSubclassEntityNames().contains(entityName);
}
|
protected boolean isSubclassPropertyDeferred(String propertyName,
String entityName) {
return false;
}
|
public boolean isSubclassPropertyNullable(int i) {
return subclassPropertyNullabilityClosure[i];
}
|
protected boolean isSubclassTableLazy(int j) {
return false;
}
|
protected boolean isSubclassTableSequentialSelect(int j) {
return false;
}
|
abstract protected boolean isTableCascadeDeleteEnabled(int j)
|
public Boolean isTransient(Object entity,
SessionImplementor session) throws HibernateException {
final Serializable id;
if ( canExtractIdOutOfEntity() ) {
id = getIdentifier( entity, session.getEntityMode() );
}
else {
id = null;
}
// we *always* assume an instance with a null
// identifier or no identifier property is unsaved!
if ( id == null ) {
return Boolean.TRUE;
}
// check the version unsaved-value, if appropriate
final Object version = getVersion( entity, session.getEntityMode() );
if ( isVersioned() ) {
// let this take precedence if defined, since it works for
// assigned identifiers
Boolean result = entityMetamodel.getVersionProperty()
.getUnsavedValue().isUnsaved( version );
if ( result != null ) {
return result;
}
}
// check the id unsaved-value
Boolean result = entityMetamodel.getIdentifierProperty()
.getUnsavedValue().isUnsaved( id );
if ( result != null ) {
return result;
}
// check to see if it is in the second-level cache
if ( hasCache() ) {
CacheKey ck = new CacheKey(
id,
getIdentifierType(),
getRootEntityName(),
session.getEntityMode(),
session.getFactory()
);
if ( getCacheAccessStrategy().get( ck, session.getTimestamp() ) != null ) {
return Boolean.FALSE;
}
}
return null;
}
|
protected boolean isUpdateCallable(int j) {
return updateCallable[j];
}
|
public boolean isVersionPropertyGenerated() {
return isVersioned() && ( getPropertyUpdateGenerationInclusions() [ getVersionProperty() ] != ValueInclusion.NONE );
}
|
public boolean isVersionPropertyInsertable() {
return isVersioned() && getPropertyInsertability() [ getVersionProperty() ];
}
|
public boolean isVersioned() {
return entityMetamodel.isVersioned();
}
|
public Object load(Serializable id,
Object optionalObject,
LockMode lockMode,
SessionImplementor session) throws HibernateException {
if ( log.isTraceEnabled() ) {
log.trace(
"Fetching entity: " +
MessageHelper.infoString( this, id, getFactory() )
);
}
final UniqueEntityLoader loader = getAppropriateLoader( lockMode, session );
return loader.load( id, optionalObject, session );
}
Load an instance using either the forUpdateLoader or the outer joining loader,
depending upon the value of the lock parameter |
public Object loadByUniqueKey(String propertyName,
Object uniqueKey,
SessionImplementor session) throws HibernateException {
return getAppropriateUniqueKeyLoader( propertyName, session.getEnabledFilters() )
.loadByUniqueKey( session, uniqueKey );
}
|
public void lock(Serializable id,
Object version,
Object object,
LockMode lockMode,
SessionImplementor session) throws HibernateException {
getLocker( lockMode ).lock( id, version, object, session );
}
|
protected void logStaticSQL() {
if ( log.isDebugEnabled() ) {
log.debug( "Static SQL for entity: " + getEntityName() );
if ( sqlLazySelectString != null ) {
log.debug( " Lazy select: " + sqlLazySelectString );
}
if ( sqlVersionSelectString != null ) {
log.debug( " Version select: " + sqlVersionSelectString );
}
if ( sqlSnapshotSelectString != null ) {
log.debug( " Snapshot select: " + sqlSnapshotSelectString );
}
for ( int j = 0; j < getTableSpan(); j++ ) {
log.debug( " Insert " + j + ": " + getSQLInsertStrings()[j] );
log.debug( " Update " + j + ": " + getSQLUpdateStrings()[j] );
log.debug( " Delete " + j + ": " + getSQLDeleteStrings()[j] );
}
if ( sqlIdentityInsertString != null ) {
log.debug( " Identity insert: " + sqlIdentityInsertString );
}
if ( sqlUpdateByRowIdString != null ) {
log.debug( " Update by row id (all fields): " + sqlUpdateByRowIdString );
}
if ( sqlLazyUpdateByRowIdString != null ) {
log.debug( " Update by row id (non-lazy fields): " + sqlLazyUpdateByRowIdString );
}
if ( sqlInsertGeneratedValuesSelectString != null ) {
log.debug( "Insert-generated property select: " + sqlInsertGeneratedValuesSelectString );
}
if ( sqlUpdateGeneratedValuesSelectString != null ) {
log.debug( "Update-generated property select: " + sqlUpdateGeneratedValuesSelectString );
}
}
}
|
public String oneToManyFilterFragment(String alias) throws MappingException {
return "";
}
|
protected final int optimisticLockMode() {
return entityMetamodel.getOptimisticLockMode();
}
|
protected void postConstruct(Mapping mapping) throws MappingException {
initPropertyPaths(mapping);
//insert/update/delete SQL
final int joinSpan = getTableSpan();
sqlDeleteStrings = new String[joinSpan];
sqlInsertStrings = new String[joinSpan];
sqlUpdateStrings = new String[joinSpan];
sqlLazyUpdateStrings = new String[joinSpan];
sqlUpdateByRowIdString = rowIdName == null ?
null :
generateUpdateString( getPropertyUpdateability(), 0, true );
sqlLazyUpdateByRowIdString = rowIdName == null ?
null :
generateUpdateString( getNonLazyPropertyUpdateability(), 0, true );
for ( int j = 0; j < joinSpan; j++ ) {
sqlInsertStrings[j] = customSQLInsert[j] == null ?
generateInsertString( getPropertyInsertability(), j ) :
customSQLInsert[j];
sqlUpdateStrings[j] = customSQLUpdate[j] == null ?
generateUpdateString( getPropertyUpdateability(), j, false ) :
customSQLUpdate[j];
sqlLazyUpdateStrings[j] = customSQLUpdate[j] == null ?
generateUpdateString( getNonLazyPropertyUpdateability(), j, false ) :
customSQLUpdate[j];
sqlDeleteStrings[j] = customSQLDelete[j] == null ?
generateDeleteString( j ) :
customSQLDelete[j];
}
tableHasColumns = new boolean[joinSpan];
for ( int j = 0; j < joinSpan; j++ ) {
tableHasColumns[j] = sqlUpdateStrings[j] != null;
}
//select SQL
sqlSnapshotSelectString = generateSnapshotSelectString();
sqlLazySelectString = generateLazySelectString();
sqlVersionSelectString = generateSelectVersionString();
if ( hasInsertGeneratedProperties() ) {
sqlInsertGeneratedValuesSelectString = generateInsertGeneratedValuesSelectString();
}
if ( hasUpdateGeneratedProperties() ) {
sqlUpdateGeneratedValuesSelectString = generateUpdateGeneratedValuesSelectString();
}
if ( isIdentifierAssignedByInsert() ) {
identityDelegate = ( ( PostInsertIdentifierGenerator ) getIdentifierGenerator() )
.getInsertGeneratedIdentifierDelegate( this, getFactory().getDialect(), useGetGeneratedKeys() );
sqlIdentityInsertString = customSQLInsert[0] == null
? generateIdentityInsertString( getPropertyInsertability() )
: customSQLInsert[0];
}
else {
sqlIdentityInsertString = null;
}
logStaticSQL();
}
|
public void postInstantiate() throws MappingException {
createLoaders();
createUniqueKeyLoaders();
createQueryLoader();
}
|
public void processInsertGeneratedProperties(Serializable id,
Object entity,
Object[] state,
SessionImplementor session) {
if ( !hasInsertGeneratedProperties() ) {
throw new AssertionFailure("no insert-generated properties");
}
processGeneratedProperties( id, entity, state, session, sqlInsertGeneratedValuesSelectString, getPropertyInsertGenerationInclusions() );
}
|
public void processUpdateGeneratedProperties(Serializable id,
Object entity,
Object[] state,
SessionImplementor session) {
if ( !hasUpdateGeneratedProperties() ) {
throw new AssertionFailure("no update-generated properties");
}
processGeneratedProperties( id, entity, state, session, sqlUpdateGeneratedValuesSelectString, getPropertyUpdateGenerationInclusions() );
}
|
public String propertySelectFragment(String name,
String suffix,
boolean allProperties) {
SelectFragment select = new SelectFragment()
.setSuffix( suffix )
.setUsedAliases( getIdentifierAliases() );
int[] columnTableNumbers = getSubclassColumnTableNumberClosure();
String[] columnAliases = getSubclassColumnAliasClosure();
String[] columns = getSubclassColumnClosure();
for ( int i = 0; i < getSubclassColumnClosure().length; i++ ) {
boolean selectable = ( allProperties || !subclassColumnLazyClosure[i] ) &&
!isSubclassTableSequentialSelect( columnTableNumbers[i] ) &&
subclassColumnSelectableClosure[i];
if ( selectable ) {
String subalias = generateTableAlias( name, columnTableNumbers[i] );
select.addColumn( subalias, columns[i], columnAliases[i] );
}
}
int[] formulaTableNumbers = getSubclassFormulaTableNumberClosure();
String[] formulaTemplates = getSubclassFormulaTemplateClosure();
String[] formulaAliases = getSubclassFormulaAliasClosure();
for ( int i = 0; i < getSubclassFormulaTemplateClosure().length; i++ ) {
boolean selectable = ( allProperties || !subclassFormulaLazyClosure[i] )
&& !isSubclassTableSequentialSelect( formulaTableNumbers[i] );
if ( selectable ) {
String subalias = generateTableAlias( name, formulaTableNumbers[i] );
select.addFormula( subalias, formulaTemplates[i], formulaAliases[i] );
}
}
if ( entityMetamodel.hasSubclasses() ) {
addDiscriminatorToSelect( select, name, suffix );
}
if ( hasRowId() ) {
select.addColumn( name, rowIdName, ROWID_ALIAS );
}
return select.toFragmentString();
}
|
protected String renderSelect(int[] tableNumbers,
int[] columnNumbers,
int[] formulaNumbers) {
Arrays.sort( tableNumbers ); //get 'em in the right order (not that it really matters)
//render the where and from parts
int drivingTable = tableNumbers[0];
final String drivingAlias = generateTableAlias( getRootAlias(), drivingTable ); //we *could* regerate this inside each called method!
final String where = createWhereByKey( drivingTable, drivingAlias );
final String from = createFrom( drivingTable, drivingAlias );
//now render the joins
JoinFragment jf = createJoin( tableNumbers, drivingAlias );
//now render the select clause
SelectFragment selectFragment = createSelect( columnNumbers, formulaNumbers );
//now tie it all together
Select select = new Select( getFactory().getDialect() );
select.setSelectClause( selectFragment.toFragmentString().substring( 2 ) );
select.setFromClause( from );
select.setWhereClause( where );
select.setOuterJoins( jf.toFromFragmentString(), jf.toWhereFragmentString() );
if ( getFactory().getSettings().isCommentsEnabled() ) {
select.setComment( "sequential select " + getEntityName() );
}
return select.toStatementString();
}
|
public void resetIdentifier(Object entity,
Serializable currentId,
Object currentVersion,
EntityMode entityMode) {
getTuplizer( entityMode ).resetIdentifier( entity, currentId, currentVersion );
}
|
public String selectFragment(String alias,
String suffix) {
return identifierSelectFragment( alias, suffix ) +
propertySelectFragment( alias, suffix, false );
}
|
public final String selectFragment(Joinable rhs,
String rhsAlias,
String lhsAlias,
String entitySuffix,
String collectionSuffix,
boolean includeCollectionColumns) {
return selectFragment( lhsAlias, entitySuffix );
}
|
public void setIdentifier(Object object,
Serializable id,
EntityMode entityMode) throws HibernateException {
getTuplizer( entityMode ).setIdentifier( object, id );
}
|
public void setPropertyValue(Object object,
int i,
Object value,
EntityMode entityMode) throws HibernateException {
getTuplizer( entityMode ).setPropertyValue( object, i, value );
}
|
public void setPropertyValue(Object object,
String propertyName,
Object value,
EntityMode entityMode) throws HibernateException {
getTuplizer( entityMode ).setPropertyValue( object, propertyName, value );
}
|
public void setPropertyValues(Object object,
Object[] values,
EntityMode entityMode) throws HibernateException {
getTuplizer( entityMode ).setPropertyValues( object, values );
}
|
public String[] toColumns(String propertyName) throws QueryException {
return propertyMapping.getColumnNames( propertyName );
}
|
public String[] toColumns(String alias,
String propertyName) throws QueryException {
return propertyMapping.toColumns( alias, propertyName );
}
|
public String[] toColumns(String name,
int i) {
final String alias = generateTableAlias( name, getSubclassPropertyTableNumber( i ) );
String[] cols = getSubclassPropertyColumnNames( i );
String[] templates = getSubclassPropertyFormulaTemplateClosure()[i];
String[] result = new String[cols.length];
for ( int j = 0; j < cols.length; j++ ) {
if ( cols[j] == null ) {
result[j] = StringHelper.replace( templates[j], Template.TEMPLATE, alias );
}
else {
result[j] = StringHelper.qualify( alias, cols[j] );
}
}
return result;
}
|
public String toString() {
return StringHelper.unqualify( getClass().getName() ) +
'(" + entityMetamodel.getName() + ')";
}
|
public Type toType(String propertyName) throws QueryException {
return propertyMapping.toType( propertyName );
}
|
public void update(Serializable id,
Object[] fields,
int[] dirtyFields,
boolean hasDirtyCollection,
Object[] oldFields,
Object oldVersion,
Object object,
Object rowId,
SessionImplementor session) throws HibernateException {
//note: dirtyFields==null means we had no snapshot, and we couldn't get one using select-before-update
// oldFields==null just means we had no snapshot to begin with (we might have used select-before-update to get the dirtyFields)
final boolean[] tableUpdateNeeded = getTableUpdateNeeded( dirtyFields, hasDirtyCollection );
final int span = getTableSpan();
final boolean[] propsToUpdate;
final String[] updateStrings;
if ( entityMetamodel.isDynamicUpdate() && dirtyFields != null ) {
// For the case of dynamic-update="true", we need to generate the UPDATE SQL
propsToUpdate = getPropertiesToUpdate( dirtyFields, hasDirtyCollection );
// don't need to check laziness (dirty checking algorithm handles that)
updateStrings = new String[span];
for ( int j = 0; j < span; j++ ) {
updateStrings[j] = tableUpdateNeeded[j] ?
generateUpdateString( propsToUpdate, j, oldFields, j == 0 && rowId != null ) :
null;
}
}
else {
// For the case of dynamic-update="false", or no snapshot, we use the static SQL
updateStrings = getUpdateStrings(
rowId != null,
hasUninitializedLazyProperties( object, session.getEntityMode() )
);
propsToUpdate = getPropertyUpdateability( object, session.getEntityMode() );
}
for ( int j = 0; j < span; j++ ) {
// Now update only the tables with dirty properties (and the table with the version number)
if ( tableUpdateNeeded[j] ) {
updateOrInsert(
id,
fields,
oldFields,
j == 0 ? rowId : null,
propsToUpdate,
j,
oldVersion,
object,
updateStrings[j],
session
);
}
}
}
|
protected boolean update(Serializable id,
Object[] fields,
Object[] oldFields,
Object rowId,
boolean[] includeProperty,
int j,
Object oldVersion,
Object object,
String sql,
SessionImplementor session) throws HibernateException {
final boolean useVersion = j == 0 && isVersioned();
final Expectation expectation = Expectations.appropriateExpectation( updateResultCheckStyles[j] );
final boolean callable = isUpdateCallable( j );
final boolean useBatch = j == 0 && expectation.canBeBatched() && isBatchable(); //note: updates to joined tables can't be batched...
if ( log.isTraceEnabled() ) {
log.trace( "Updating entity: " + MessageHelper.infoString( this, id, getFactory() ) );
if ( useVersion ) {
log.trace( "Existing version: " + oldVersion + " - > New version: " + fields[getVersionProperty()] );
}
}
try {
int index = 1; // starting index
final PreparedStatement update;
if ( useBatch ) {
if ( callable ) {
update = session.getBatcher().prepareBatchCallableStatement( sql );
}
else {
update = session.getBatcher().prepareBatchStatement( sql );
}
}
else {
if ( callable ) {
update = session.getBatcher().prepareCallableStatement( sql );
}
else {
update = session.getBatcher().prepareStatement( sql );
}
}
try {
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 );
// Write any appropriate versioning conditional parameters
if ( useVersion && Versioning.OPTIMISTIC_LOCK_VERSION == entityMetamodel.getOptimisticLockMode() ) {
if ( checkVersion( includeProperty ) ) {
getVersionType().nullSafeSet( update, oldVersion, index, session );
}
}
else if ( entityMetamodel.getOptimisticLockMode() > Versioning.OPTIMISTIC_LOCK_VERSION && oldFields != null ) {
boolean[] versionability = getPropertyVersionability(); //TODO: is this really necessary????
boolean[] includeOldField = entityMetamodel.getOptimisticLockMode() == Versioning.OPTIMISTIC_LOCK_ALL ?
getPropertyUpdateability() : includeProperty;
Type[] types = getPropertyTypes();
for ( int i = 0; i < entityMetamodel.getPropertySpan(); i++ ) {
boolean include = includeOldField[i] &&
isPropertyOfTable( i, j ) &&
versionability[i]; //TODO: is this really necessary????
if ( include ) {
boolean[] settable = types[i].toColumnNullness( oldFields[i], getFactory() );
types[i].nullSafeSet(
update,
oldFields[i],
index,
settable,
session
);
index += ArrayHelper.countTrue(settable);
}
}
}
if ( useBatch ) {
session.getBatcher().addToBatch( expectation );
return true;
}
else {
return check( update.executeUpdate(), id, j, expectation, update );
}
}
catch ( SQLException sqle ) {
if ( useBatch ) {
session.getBatcher().abortBatch( sqle );
}
throw sqle;
}
finally {
if ( !useBatch ) {
session.getBatcher().closeStatement( update );
}
}
}
catch ( SQLException sqle ) {
throw JDBCExceptionHelper.convert(
getFactory().getSQLExceptionConverter(),
sqle,
"could not update: " + MessageHelper.infoString( this, id, getFactory() ),
sql
);
}
}
|
protected void updateOrInsert(Serializable id,
Object[] fields,
Object[] oldFields,
Object rowId,
boolean[] includeProperty,
int j,
Object oldVersion,
Object object,
String sql,
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, null );
}
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 && !isAllNull( fields, j ) ) {
// assume that the row was not there since it previously had only null
// values, so do an INSERT instead
//TODO: does not respect dynamic-insert
insert( id, fields, getPropertyInsertability(), j, getSQLInsertStrings()[j], object, session );
}
}
}
Perform an SQL UPDATE or SQL INSERT |
protected boolean useDynamicInsert() {
return entityMetamodel.isDynamicInsert();
}
|
protected boolean useDynamicUpdate() {
return entityMetamodel.isDynamicUpdate();
}
|
protected boolean useGetGeneratedKeys() {
return getFactory().getSettings().isGetGeneratedKeysEnabled();
}
|
protected boolean useInsertSelectIdentity() {
return !useGetGeneratedKeys() && getFactory().getDialect().supportsInsertSelectIdentity();
}
|
public String whereJoinFragment(String alias,
boolean innerJoin,
boolean includeSubclasses) {
return getSubclassTableSpan() == 1 ?
"" : //just a performance opt!
createJoin( alias, innerJoin, includeSubclasses ).toWhereFragmentString();
}
|