📄 abstractdomain.java
字号:
"Null argument value for aJDBCHelper was passed to "
+"AbstractDomain#validate(...)");
}
try
{
// Validate the supertype columnSpecs
Iterator columnSpecs = i_columnSpecs.iterator(); // reset iterator
while (columnSpecs.hasNext())
{
aColumnSpec = (ColumnSpec) columnSpecs.next();
// If this attribute is required and not present, throw
// MissingAttributeException.
aColumnSpec.validateRequired(aPO);
// If this attribute is unique, verify that no other rows match it.
aColumnSpec.validateUnique(aPO,
aJDBCHelper,
i_primaryKeyColumnSpec,
this.getDatabasePolicy(),
i_tableName);
} // while
// Validate all subtype columnSpecs
columnSpecs = i_subtypeColumnSpecs.iterator(); // reset iterator
while (columnSpecs.hasNext())
{
aColumnSpec = (ColumnSpec) columnSpecs.next();
// If this attribute is required and not present, throw
// MissingAttributeException.
aColumnSpec.validateRequired(aPO);
// If this attribute is unique, verify that no other rows match it.
aColumnSpec.validateUnique(aPO,
aJDBCHelper,
i_primaryKeyColumnSpec,
this.getDatabasePolicy(),
i_subtypeTableName);
} // while
}
catch (MissingAttributeException e)
{
this.quietlyRollbackAndClose(aJDBCHelper);
throw e;
}
catch (DuplicateRowException e)
{
this.quietlyRollbackAndClose(aJDBCHelper);
throw e;
}
catch (DatabaseException e)
{
this.quietlyRollbackAndClose(aJDBCHelper);
throw e;
}
} // validate(aPO, aJDBCHelper)
/**
* This is a pass-through method that adds the default JDBCHelper to the
* argument list. This method should not be overridden.
*
* @param aPO a value of type 'PersistentObject'
* @return a value of type 'PersistentObject'
* @exception ObjectHasChangedException if an error occurs
* @exception MissingAttributeException if an error occurs
* @exception DuplicateRowException if an error occurs
*/
public final PersistentObject save(PersistentObject aPO)
throws
ObjectHasChangedException,
MissingAttributeException,
DuplicateRowException
{
return this.save(aPO, this.getJDBCHelper());
} // save(aPersistentObject)
/**
* Save the PersistentObject to the database after validating the object
* with this.validate(aPO,aJDBCHelper).
*
* Note for subclasses: If you don't want an exception from the validate
* method to rollback your transaction, specifically call validate() with
* a different JDBCHelper (a clone works) before calling save().
*
* @param aPO a value of type 'PersistentObject'
* if the primary key attribute is null, then this does a SQL insert.
* @return a value of type 'PersistentObject'
* @exception ObjectHasChangedException if an error occurs
* @exception MissingAttributeException if an error occurs
* @exception DuplicateRowException if an error occurs
*/
public PersistentObject save(PersistentObject aPO,
JDBCHelper aJDBCHelper)
throws
ObjectHasChangedException,
MissingAttributeException,
DuplicateRowException
{
PersistentObject returnValue = null;
if (LOG.isDebugEnabled())
{
LOG.debug("AbstractDomain.save(" + aPO + ", " + aJDBCHelper + ")");
}
if (aPO == null)
{
throw new IllegalArgumentException(
"Null argument value for aPO was passed to "
+"AbstractDomain#save(...)");
}
if (aJDBCHelper == null)
{
throw new IllegalArgumentException(
"Null argument value for aJDBCHelper was passed to "
+"AbstractDomain#save(...)");
}
// Throw an exception if trying to resave an old instance.
if (aPO.hasDeadPersistentState())
{
throw new DatabaseException(
"This instance has persistent state of \"dead\" and cannot be saved again. "
+ "If you wish to reuse instances, set ReturnSavedObject to false. "
+ "However, be warned that you won't get updated timestamps.");
}
// We don't want to begin (or end) a "transaction" if we are already in
// one. The given JDBCHelper might already be inside a transaction if
// this method is being called from a preSave() or postSave() method of
// another domain.
boolean okToEndTransaction = false;
if (!aJDBCHelper.isInsideTransaction())
{
// Tell JDBCHelper to ignore commit and close messages until
// endTransaction() is called.
this.beginTransaction(aJDBCHelper);
okToEndTransaction = true;
}
// Clean-up and return the object if it doesn't require saving.
// This is after the potential start of the transaction to ensure
// proper clean-up of JDBCHelpers from a pool.
// This could have been done before the beginTransaction with an explicit
// check for pool usage, but this felt less error prone since this
// will follow the same steps that would have occured if an update
// did occur, and we know that works OK.
if (aPO.hasCurrentPersistentState())
{
if (i_returnSavedObject)
{
returnValue = aPO;
}
if (okToEndTransaction)
{
// Tell JDBCHelper that it's OK to commit the transaction
// and close (i.e. return to the pool if necessary) now.
this.endTransaction(aJDBCHelper);
}
return returnValue;
}
// Perform any pre-validation logic defined by subclass. This happens
// before validating so it can be made valid if needed.
this.preValidate(aPO, aJDBCHelper);
if (i_validateBeforeSaving)
{
// Throw exception if object is not valid
this.validate(aPO, aJDBCHelper);
}
// Perform any pre-save logic defined by subclass. This happens after
// validating so you can be sure the object is valid.
this.preSave(aPO, aJDBCHelper);
List columnSpecs = i_columnSpecs;
if (aPO.hasNewPersistentState()) // this is an insert
{
this.doInsert(aPO,
aJDBCHelper,
i_tableName,
i_columnSpecs);
// This block added for InstantDB, HypersonicSQL, and other
// databases that use auto-increment
if (this.getDatabasePolicy().autoIncrementIdentifier() != null &&
i_primaryKeyColumnSpec.isSequencedPrimaryKey())
{
Long tempId = null;
try
{
tempId = this.getDatabasePolicy().findAutoIncrementId(
this.getTableName(),
i_primaryKeyColumnSpec.getColumnName(),
aJDBCHelper);
}
catch (RuntimeException e)
{
this.quietlyRollbackAndClose(aJDBCHelper);
throw e;
}
if (tempId == null)
{
this.quietlyRollbackAndClose(aJDBCHelper);
throw new DatabaseException("Auto Increment Id is null");
}
i_primaryKeyColumnSpec.setValueTo(tempId, aPO);
} // if we have a sequenced primary key
// Insert into a subtype table if there is one.
if (i_subtypeColumnSpecs.size() > 0)
{ // Insert into the Subtype table.
List colSpecs = new ArrayList();
colSpecs.add(i_primaryKeyColumnSpec);
colSpecs.addAll(i_subtypeColumnSpecs);
this.doInsert(aPO,
aJDBCHelper,
i_subtypeTableName,
colSpecs);
} // if there is a subtype table
} // if this is an insert
else // this is an update
{
UpdateSQLBuilder sqlBuilder = this.getUpdateSQLBuilder();
String updateSQL = sqlBuilder.buildSQL(aPO,
this.getTableName(),
this.getColumnSpecs());
int rowCount = this.executeSQLUpdate(updateSQL, aJDBCHelper);
if (rowCount < 1)
{
this.quietlyRollbackAndClose(aJDBCHelper);
throw new ObjectHasChangedException(
this.find(aPO, aJDBCHelper));
}
// Insert to or update the subtype table if there is one.
if (i_subtypeColumnSpecs.size() > 0)
{
// Check to see if we need to do an insert or an update
// This adds an extra JDBC call, which I don't like, but there
// is no db-neutral way (that I know of) to trap a
// "row not found" error on an update. Another solution might
// be to have a subtype PersistentState in each PO.
SelectSQLBuilder selectSQLBuilder = this.getSelectSQLBuilder();
Integer i = this.findInteger(
selectSQLBuilder.buildCountSQL(i_subtypeTableName,
i_primaryKeyColumnSpec,
aPO,
this.getDatabasePolicy()));
List colSpecs = new ArrayList();
colSpecs.add(i_primaryKeyColumnSpec);
colSpecs.addAll(i_subtypeColumnSpecs);
if (i.intValue() == 0)
{ // Insert into the subtype table.
this.doInsert(aPO,
aJDBCHelper,
i_subtypeTableName,
colSpecs);
} // if we needed to insert
else
{ // Update the subtype table.
this.doUpdate(aPO,
aJDBCHelper,
i_subtypeTableName,
colSpecs);
}
}
} // else
// Perform any post-save logic defined by subclass.
this.postSave(aPO, aJDBCHelper);
// Return whatever got stored in the database. This is needed because
// timestamp and sequence columns can be changed during the JDBC call.
if (i_returnSavedObject)
{
returnValue = this.finalFind(aPO, aJDBCHelper);
aPO.forceDeadPersistentState();
}
else
{
// Assume the user knows the risks.
aPO.forceCurrentPersistentState();
}
if (okToEndTransaction)
{
// Tell JDBCHelper that it's OK to commit the transaction now.
this.endTransaction(aJDBCHelper);
}
return returnValue;
} // save(aPO, aJDBCHelper)
/** This method is here to help clean up the save() method a bit */
private void doInsert(PersistentObject aPO,
JDBCHelper aJDBCHelper,
String tableName,
List columnSpecs)
{
String insertSQL =
this.getInsertSQLBuilder().buildSQL(aPO,
aJDBCHelper,
tableName,
columnSpecs);
int rowCount = this.executeSQLUpdate(insertSQL, aJDBCHelper);
if (rowCount < 1)
{
this.quietlyRollbackAndClose(aJDBCHelper);
throw new DatabaseException(
"Insert into table (" + tableName
+ ") failed. Zero rows affected.");
}
} // doInsert(...)
/** This method is here to help clean up the save() method a bit */
private void doUpdate(PersistentObject aPO,
JDBCHelper aJDBCHelper,
String tableName,
List columnSpecs)
{
String sql =
this.getUpdateSQLBuilder().buildSQL(aPO,
tableName,
columnSpecs);
int rowCount = this.executeSQLUpdate(sql, aJDBCHelper);
if (rowCount < 1)
{
this.quietlyRollbackAndClose(aJDBCHelper);
throw new DatabaseException(
"Update of table (" + tableName
+ ") failed. Zero rows affected.");
}
} // doUpdate(...)
/**
* This is a pass-through method that adds the default JDBCHelper to the
* argument list.
*
* @param aPO a value of type 'PersistentObject'
* @return a value of type 'int'
*/
public final int delete(PersistentObject aPO)
{
return this.delete(aPO, this.getJDBCHelper());
}
/**
* Delete one row from the database. No application exceptions need to be
* declared here since the integer number of rows deleted is the return
* value.
*
* @param aPO a value of type 'PersistentObject'
* @return a value of type 'int' which is the number of rows deleted.
* This should always be zero or one, but this is not guaranteed
* if the wrong attribute is defined as the primary key.
*/
public int delete(PersistentObject aPO,
JDBCHelper aJDBCHelper)
{
if (LOG.isDebugEnabled())
{
LOG.debug(
"AbstractDomain.delete(" + aPO + ", " + aJDBCHelper + ")");
}
if (aPO == null)
{
throw new IllegalArgumentException(
"A null value argument for aPO was passed to "
+ "AbstractDomain#delete(aPO,aJDBCHelper)");
}
if (aJDBCHelper == null)
{
throw new IllegalArgumentException(
"A null value argument for aJDBCHelper was passed to "
+ "AbstractDomain#delete(aPO,aJDBCHelper)");
}
// We don't want to begin (or end) a "transaction" if we are already in
// one. We might already be inside a transaction if this method is
// being called from a preSave(), preDelete(), postSave(), or
// postDelete() method of another domain.
boolean okToEndTransaction = false;
if (!aJDBCHelper.isInsideTransaction())
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -