#467 - Delete bean with unloaded version property throws OptimisticLockException - API Change, return boolean

This commit is contained in:
Robin Bygrave
2015-11-26 16:09:25 +13:00
parent a2ee0bfdbe
commit a578eda2b1
18 changed files with 150 additions and 54 deletions
+10 -2
View File
@@ -697,12 +697,20 @@ public final class Ebean {
/**
* Delete the bean.
* <p>
* This will return true if the bean was deleted successfully or JDBC batch is being used.
* </p>
* <p>
* If there is no current transaction one will be created and committed for
* you automatically.
* </p>
* <p>
* If the Bean does not have a version property (or loaded version property) and
* the bean does not exist then this returns false indicating that nothing was
* deleted. Note that, if JDBC batch mode is used then this always returns true.
* </p>
*/
public static void delete(Object bean) throws OptimisticLockException {
serverMgr.getDefaultServer().delete(bean);
public static boolean delete(Object bean) throws OptimisticLockException {
return serverMgr.getDefaultServer().delete(bean);
}
/**
+18 -2
View File
@@ -1246,16 +1246,32 @@ public interface EbeanServer {
/**
* Delete the bean.
* <p>
* This will return true if the bean was deleted successfully or JDBC batch is being used.
* </p>
* <p>
* If there is no current transaction one will be created and committed for
* you automatically.
* </p>
* <p>
* If the Bean does not have a version property (or loaded version property) and
* the bean does not exist then this returns false indicating that nothing was
* deleted. Note that, if JDBC batch mode is used then this always returns true.
* </p>
*/
void delete(Object bean) throws OptimisticLockException;
boolean delete(Object bean) throws OptimisticLockException;
/**
* Delete the bean with an explicit transaction.
* <p>
* This will return true if the bean was deleted successfully or JDBC batch is being used.
* </p>
* <p>
* If the Bean does not have a version property (or loaded version property) and
* the bean does not exist then this returns false indicating that nothing was
* deleted. However, if JDBC batch mode is used then this always returns true.
* </p>
*/
void delete(Object bean, Transaction transaction) throws OptimisticLockException;
boolean delete(Object bean, Transaction transaction) throws OptimisticLockException;
/**
* Delete the bean given its type and id.
+17 -5
View File
@@ -251,12 +251,24 @@ public abstract class Model {
}
/**
* Delete this entity.
* Delete this bean.
* <p>
* This will return true if the bean was deleted successfully or JDBC batch is being used.
* </p>
* <p>
* If there is no current transaction one will be created and committed for
* you automatically.
* </p>
* <p>
* If the Bean does not have a version property (or loaded version property) and
* the bean does not exist then this returns false indicating that nothing was
* deleted. Note that, if JDBC batch mode is used then this always returns true.
* </p>
*
* @see EbeanServer#delete(Object)
*/
public void delete() {
db().delete(this);
public boolean delete() {
return db().delete(this);
}
/**
@@ -276,8 +288,8 @@ public abstract class Model {
/**
* Perform a delete using this entity against the specified server.
*/
public void delete(String server) {
db(server).delete(this);
public boolean delete(String server) {
return db(server).delete(this);
}
/**
@@ -1867,16 +1867,16 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
/**
* Delete the bean.
*/
public void delete(Object bean) {
delete(bean, null);
public boolean delete(Object bean) {
return delete(bean, null);
}
/**
* Delete the bean with the explicit transaction.
*/
public void delete(Object bean, Transaction t) {
public boolean delete(Object bean, Transaction t) {
persister.delete(checkEntityBean(bean), t);
return persister.delete(checkEntityBean(bean), t);
}
/**
@@ -480,8 +480,7 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
return -1;
case DELETE:
persistExecute.executeDeleteBean(this);
return -1;
return persistExecute.executeDeleteBean(this);
default:
throw new RuntimeException("Invalid type " + type);
@@ -66,7 +66,7 @@ public interface Persister {
/**
* Delete the bean.
*/
void delete(EntityBean entityBean, Transaction t);
boolean delete(EntityBean entityBean, Transaction t);
/**
* Delete multiple beans given a collection of Id values.
@@ -22,6 +22,6 @@ public interface BeanPersister {
/**
* execute the delete bean request.
*/
void delete(PersistRequestBean<?> request) throws PersistenceException;
int delete(PersistRequestBean<?> request) throws PersistenceException;
}
@@ -73,15 +73,17 @@ public final class DefaultPersistExecute implements PersistExecute {
/**
* execute the bean delete request.
*/
public <T> void executeDeleteBean(PersistRequestBean<T> request) {
public <T> int executeDeleteBean(PersistRequestBean<T> request) {
BeanManager<T> mgr = request.getBeanManager();
BeanPersister persister = mgr.getBeanPersister();
BeanPersistController controller = request.getBeanController();
if (controller == null || controller.preDelete(request)) {
persister.delete(request);
return persister.delete(request);
}
// delete handled by the BeanController so return 0
return 0;
}
/**
@@ -498,24 +498,25 @@ public final class DefaultPersister implements Persister {
/**
* Delete the bean with the explicit transaction.
* Return false if the delete is executed without OCC and 0 rows were deleted.
*/
public void delete(EntityBean bean, Transaction t) {
public boolean delete(EntityBean bean, Transaction t) {
PersistRequestBean<EntityBean> request = createRequest(bean, t, Type.DELETE);
deleteRequest(request);
boolean deleted = deleteRequest(request);
if (request.isDraftable()) {
// we have just deleting a draft bean so now we need to delete the
// associated 'live' bean. This is effectively an 'automatic publish'.
try {
deleteRequest(createRequest(request.createReference(), t, Type.DELETE, true));
} catch (OptimisticLockException e) {
SUM.debug("Ignore OptimisticLockException - did not delete live row as draft not published for bean:{} id:{}", request.getFullName(), request.getBeanId());
}
deleteRequest(createRequest(request.createReference(), t, Type.DELETE, true));
}
return deleted;
}
private void deleteRequest(PersistRequestBean<?> req) {
/**
* Execute the delete request returning true if a delete occurred.
*/
private boolean deleteRequest(PersistRequestBean<?> req) {
if (req.isRegisteredForDeleteBean()) {
// skip deleting bean. Used where cascade is on
@@ -523,15 +524,17 @@ public final class DefaultPersister implements Persister {
if (logger.isDebugEnabled()) {
logger.debug("skipping delete on alreadyRegistered " + req.getBean());
}
return;
return false;
}
try {
req.initTransIfRequiredWithBatchCascade();
delete(req);
boolean deleted = delete(req);
req.commitTransIfRequired();
req.flushBatchOnCascade();
return deleted;
} catch (RuntimeException ex) {
req.rollbackTransIfRequired();
throw ex;
@@ -710,7 +713,7 @@ public final class DefaultPersister implements Persister {
* Note that preDelete fires before the deletion of children.
* </p>
*/
private void delete(PersistRequestBean<?> request) {
private boolean delete(PersistRequestBean<?> request) {
DeleteUnloadedForeignKeys unloadedForeignKeys = null;
@@ -729,7 +732,7 @@ public final class DefaultPersister implements Persister {
}
}
request.executeOrQueue();
int count = request.executeOrQueue();
if (request.isPersistCascade()) {
deleteAssocOne(request);
@@ -739,6 +742,8 @@ public final class DefaultPersister implements Persister {
}
}
// return true if using JDBC batch (as we can't tell until the batch is flushed)
return count != 0;
}
/**
@@ -33,7 +33,7 @@ public interface PersistExecute {
/**
* Execute a Bean (or MapBean) delete.
*/
<T> void executeDeleteBean(PersistRequestBean<T> request);
<T> int executeDeleteBean(PersistRequestBean<T> request);
/**
* Execute a Update.
@@ -46,9 +46,10 @@ public class DeleteHandler extends DmlHandler {
* Execute the delete non-batch.
*/
@Override
public void execute() throws SQLException, OptimisticLockException {
public int execute() throws SQLException, OptimisticLockException {
int rowCount = dataBind.executeUpdate();
checkRowCount(rowCount);
return rowCount;
}
@Override
@@ -35,10 +35,10 @@ public final class DmlBeanPersister implements BeanPersister {
/**
* execute the bean delete request.
*/
public void delete(PersistRequestBean<?> request) {
public int delete(PersistRequestBean<?> request) {
DeleteHandler delete = new DeleteHandler(request, deleteMeta);
execute(request, delete);
return execute(request, delete);
}
/**
@@ -62,15 +62,17 @@ public final class DmlBeanPersister implements BeanPersister {
/**
* execute request taking batching into account.
*/
private void execute(PersistRequestBean<?> request, PersistHandler handler) {
private int execute(PersistRequestBean<?> request, PersistHandler handler) {
boolean batched = request.isBatched();
try {
handler.bind();
if (batched) {
handler.addBatch();
return -1;
} else {
handler.execute();
return handler.execute();
}
} catch (SQLException e) {
@@ -75,7 +75,7 @@ public abstract class DmlHandler implements PersistHandler, BindableRequest {
* Execute now for non-batch execution.
*/
@Override
public abstract void execute() throws SQLException;
public abstract int execute() throws SQLException;
/**
* Check the rowCount.
@@ -125,8 +125,8 @@ public class InsertHandler extends DmlHandler {
* getGeneratedKeys if required.
*/
@Override
public void execute() throws SQLException, OptimisticLockException {
int rc = dataBind.executeUpdate();
public int execute() throws SQLException, OptimisticLockException {
int rowCount = dataBind.executeUpdate();
if (useGeneratedKeys) {
// get the auto-increment value back and set into the bean
getGeneratedKeys();
@@ -136,8 +136,9 @@ public class InsertHandler extends DmlHandler {
fetchGeneratedKeyUsingSelect();
}
checkRowCount(rc);
checkRowCount(rowCount);
executeDerivedRelationships();
return rowCount;
}
protected void executeDerivedRelationships() {
@@ -210,16 +211,14 @@ public class InsertHandler extends DmlHandler {
rset.close();
}
} catch (SQLException ex) {
String msg = "Error closing rset for fetchGeneratedKeyUsingSelect?";
logger.warn(msg, ex);
logger.warn("Error closing ResultSet for fetchGeneratedKeyUsingSelect?", ex);
}
try {
if (stmt != null) {
stmt.close();
}
} catch (SQLException ex) {
String msg = "Error closing stmt for fetchGeneratedKeyUsingSelect?";
logger.warn(msg, ex);
logger.warn("Error closing Statement for fetchGeneratedKeyUsingSelect?", ex);
}
}
}
@@ -25,7 +25,7 @@ public interface PersistHandler {
/**
* Execute now for non-batch execution.
*/
void execute() throws SQLException;
int execute() throws SQLException;
/**
* Close resources including underlying preparedStatement.
@@ -67,11 +67,13 @@ public class UpdateHandler extends DmlHandler {
* Execute the update in non-batch.
*/
@Override
public void execute() throws SQLException, OptimisticLockException {
public int execute() throws SQLException, OptimisticLockException {
if (!emptySetClause) {
int rowCount = dataBind.executeUpdate();
checkRowCount(rowCount);
return rowCount;
}
return 0;
}
@Override