Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/**
* Copyright (C) 2006 Robin Bygrave
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebeaninternal.server.persist;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.persistence.PersistenceException;
import com.avaje.ebean.CallableSql;
import com.avaje.ebean.Query;
import com.avaje.ebean.SqlUpdate;
import com.avaje.ebean.Transaction;
import com.avaje.ebean.Update;
import com.avaje.ebean.bean.BeanCollection;
import com.avaje.ebean.bean.BeanCollection.ModifyListenMode;
import com.avaje.ebean.bean.EntityBean;
import com.avaje.ebean.bean.EntityBeanIntercept;
import com.avaje.ebean.config.ldap.LdapContextFactory;
import com.avaje.ebeaninternal.api.SpiEbeanServer;
import com.avaje.ebeaninternal.api.SpiTransaction;
import com.avaje.ebeaninternal.api.SpiUpdate;
import com.avaje.ebeaninternal.server.core.ConcurrencyMode;
import com.avaje.ebeaninternal.server.core.Message;
import com.avaje.ebeaninternal.server.core.PersistRequest;
import com.avaje.ebeaninternal.server.core.PersistRequestBean;
import com.avaje.ebeaninternal.server.core.PersistRequestCallableSql;
import com.avaje.ebeaninternal.server.core.PersistRequestOrmUpdate;
import com.avaje.ebeaninternal.server.core.PersistRequestUpdateSql;
import com.avaje.ebeaninternal.server.core.Persister;
import com.avaje.ebeaninternal.server.core.PstmtBatch;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptorManager;
import com.avaje.ebeaninternal.server.deploy.BeanManager;
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssocMany;
import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssocOne;
import com.avaje.ebeaninternal.server.deploy.IntersectionRow;
import com.avaje.ebeaninternal.server.deploy.ManyType;
import com.avaje.ebeaninternal.server.ldap.DefaultLdapPersister;
import com.avaje.ebeaninternal.server.ldap.LdapPersistBeanRequest;
/**
* Persister implementation using DML.
*
* This object uses DmlPersistExecute to perform the actual persist execution.
*
*
* This object:
*
*
Determines insert or update for saved beans
*
Determines the concurrency mode
*
Handles cascading of save and delete
*
Handles the batching and queueing
*
*
* @see com.avaje.ebeaninternal.server.persist.DefaultPersistExecute
*/
public final class DefaultPersister implements Persister {
private static final Logger logger = Logger.getLogger(DefaultPersister.class.getName());
/**
* Actually does the persisting work.
*/
private final PersistExecute persistExecute;
private final DefaultLdapPersister ldapPersister;
private final SpiEbeanServer server;
private final BeanDescriptorManager beanDescriptorManager;
private final boolean defaultUpdateNullProperties;
private final boolean defaultDeleteMissingChildren;
public DefaultPersister(SpiEbeanServer server, boolean validate,
Binder binder, BeanDescriptorManager descMgr, PstmtBatch pstmtBatch, LdapContextFactory contextFactory) {
this.server = server;
this.beanDescriptorManager = descMgr;
this.persistExecute = new DefaultPersistExecute(validate, binder, pstmtBatch);
this.ldapPersister = new DefaultLdapPersister(contextFactory);
this.defaultUpdateNullProperties = server.isDefaultUpdateNullProperties();
this.defaultDeleteMissingChildren = server.isDefaultDeleteMissingChildren();
}
/**
* Execute the CallableSql.
*/
public int executeCallable(CallableSql callSql, Transaction t) {
PersistRequestCallableSql request = new PersistRequestCallableSql(server, callSql, (SpiTransaction) t, persistExecute);
try {
request.initTransIfRequired();
int rc = request.executeOrQueue();
request.commitTransIfRequired();
return rc;
} catch (RuntimeException e) {
request.rollbackTransIfRequired();
throw e;
}
}
/**
* Execute the orm update.
*/
public int executeOrmUpdate(Update update, Transaction t) {
SpiUpdate ormUpdate = (SpiUpdate) update;
BeanManager mgr = beanDescriptorManager.getBeanManager(ormUpdate.getBeanType());
if (mgr == null) {
String msg = "No BeanManager found for type [" + ormUpdate.getBeanType() + "]. Is it an entity?";
throw new PersistenceException(msg);
}
PersistRequestOrmUpdate request = new PersistRequestOrmUpdate(server, mgr, ormUpdate, (SpiTransaction) t, persistExecute);
try {
request.initTransIfRequired();
int rc = request.executeOrQueue();
request.commitTransIfRequired();
return rc;
} catch (RuntimeException e) {
request.rollbackTransIfRequired();
throw e;
}
}
/**
* Execute the updateSql.
*/
public int executeSqlUpdate(SqlUpdate updSql, Transaction t) {
PersistRequestUpdateSql request = new PersistRequestUpdateSql(server, updSql, (SpiTransaction) t, persistExecute);
try {
request.initTransIfRequired();
int rc = request.executeOrQueue();
request.commitTransIfRequired();
return rc;
} catch (RuntimeException e) {
request.rollbackTransIfRequired();
throw e;
}
}
/**
* Recursively delete the bean. This calls back to the EbeanServer.
*/
private void deleteRecurse(Object detailBean, Transaction t) {
// NB: a new PersistRequest is made
server.delete(detailBean, t);
}
/**
* Force an Update using the given bean.
*/
public void forceUpdate(Object bean, Set updateProps, Transaction t, boolean deleteMissingChildren, boolean updateNullProperties) {
if (bean == null) {
throw new NullPointerException(Message.msg("bean.isnull"));
}
if (updateProps == null) {
// checking to see if this is just a 'normal' update
if (bean instanceof EntityBean) {
EntityBeanIntercept ebi = ((EntityBean) bean)._ebean_getIntercept();
if (ebi.isDirty() || ebi.isLoaded()) {
// a 'normal' update using 'dirty' properties from internal bean state.
// if not dirty we still update in case any cascading save occurs
PersistRequestBean req = createRequest(bean, t, null);
try {
req.initTransIfRequired();
update(req);
req.commitTransIfRequired();
// finished a 'normal' update
return;
} catch (RuntimeException ex) {
req.rollbackTransIfRequired();
throw ex;
}
} else if (ebi.isReference()) {
// just return as no point in cascading (no modified beans/lists)
return;
}
// loadedProps set by Ebean JSON / XML Marshalling
updateProps = ebi.getLoadedProps();
}
}
BeanManager mgr = getBeanManager(bean);
if (mgr == null) {
throw new PersistenceException(errNotRegistered(bean.getClass()));
}
forceUpdateStateless(bean, t, null, mgr, updateProps, deleteMissingChildren, updateNullProperties);
}
/**
* Force a 'stateless' update determining which properties to update.
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
private void forceUpdateStateless(Object bean, Transaction t, Object parentBean, BeanManager mgr, Set updateProps,
boolean deleteMissingChildren, boolean updateNullProperties) {
BeanDescriptor descriptor = mgr.getBeanDescriptor();
// determine concurrency mode based on version property not null
ConcurrencyMode mode = descriptor.determineConcurrencyMode(bean);
if (updateProps == null) {
// determine based on null treatment (all properties updated or just the non-null ones)
updateProps = updateNullProperties ? null : descriptor.determineLoadedProperties(bean);
} else if (updateProps.isEmpty()) {
// in this case means we want to include all properties in the update
updateProps = null;
} else if (ConcurrencyMode.VERSION.equals(mode)) {
// check that the version property is included
String verName = descriptor.firstVersionProperty().getName();
if (!updateProps.contains(verName)) {
// defensively copy the updateProps and add the version property name
updateProps = new HashSet(updateProps);
updateProps.add(verName);
}
}
PersistRequestBean req;
if (descriptor.isLdapEntityType()) {
req = new LdapPersistBeanRequest(server, bean, parentBean, mgr, ldapPersister, updateProps, mode);
} else {
// special constructor for force 'stateless' Update mode ...
req = new PersistRequestBean(server, bean, parentBean, mgr, (SpiTransaction) t, persistExecute, updateProps, mode);
req.setStatelessUpdate(true, deleteMissingChildren, updateNullProperties);
}
try {
req.initTransIfRequired();
update(req);
req.commitTransIfRequired();
} catch (RuntimeException ex) {
req.rollbackTransIfRequired();
throw ex;
}
}
public void save(Object bean, Transaction t) {
saveRecurse(bean, t, null);
}
/**
* Explicitly specify to insert this bean.
*/
public void forceInsert(Object bean, Transaction t) {
PersistRequestBean req = createRequest(bean, t, null);
try {
req.initTransIfRequired();
insert(req);
req.commitTransIfRequired();
} catch (RuntimeException ex) {
req.rollbackTransIfRequired();
throw ex;
}
}
private void saveRecurse(Object bean, Transaction t, Object parentBean) {
if (bean == null) {
throw new NullPointerException(Message.msg("bean.isnull"));
}
if (bean instanceof EntityBean == false) {
saveVanillaRecurse(bean, t, parentBean);
return;
}
PersistRequestBean req = createRequest(bean, t, parentBean);
try {
req.initTransIfRequired();
saveEnhanced(req);
req.commitTransIfRequired();
} catch (RuntimeException ex) {
req.rollbackTransIfRequired();
throw ex;
}
}
/**
* Insert or update the bean depending on PersistControl and the bean state.
*/
private void saveEnhanced(PersistRequestBean request) {
EntityBeanIntercept intercept = request.getEntityBeanIntercept();
if (intercept.isReference()) {
// its a reference...
if (request.isPersistCascade()) {
// save any associated List held beans
intercept.setLoaded();
saveAssocMany(false, request);
intercept.setReference();
}
} else {
if (intercept.isLoaded()) {
// Need to call setLoaded(false) to simulate insert
update(request);
} else {
insert(request);
}
}
}
/**
* Determine if this is an Insert or update for the 'vanilla' bean.
*/
private void saveVanillaRecurse(Object bean, Transaction t, Object parentBean) {
BeanManager mgr = getBeanManager(bean);
if (mgr == null) {
throw new RuntimeException("No Mgr found for " + bean + " " + bean.getClass());
}
// use the version property to determine insert or update
if (mgr.getBeanDescriptor().isVanillaInsert(bean)) {
saveVanillaInsert(bean, t, parentBean, mgr);
} else {
// update non-null properties (no partial object knowledge with vanilla bean)
forceUpdateStateless(bean, t, parentBean, mgr, null, defaultDeleteMissingChildren, defaultUpdateNullProperties);
}
}
/**
* Perform insert on non-enhanced bean (effectively same as enhanced bean).
*/
private void saveVanillaInsert(Object bean, Transaction t, Object parentBean, BeanManager mgr) {
PersistRequestBean req = createRequest(bean, t, parentBean, mgr);
try {
req.initTransIfRequired();
insert(req);
req.commitTransIfRequired();
} catch (RuntimeException ex) {
req.rollbackTransIfRequired();
throw ex;
}
}
/**
* Insert the bean.
*/
private void insert(PersistRequestBean request) {
if (request.isRegisteredBean()){
// skip as already inserted/updated in this request (recursive cascading)
return;
}
try {
request.setType(PersistRequest.Type.INSERT);
if (request.isPersistCascade()) {
// save associated One beans recursively first
saveAssocOne(request);
}
// set the IDGenerated value if required
setIdGenValue(request);
request.executeOrQueue();
if (request.isPersistCascade()) {
// save any associated List held beans
saveAssocMany(true, request);
}
} finally {
request.unRegisterBean();
}
}
/**
* Update the bean. Return NOT_SAVED if the bean values have not changed.
*/
private void update(PersistRequestBean request) {
if (request.isRegisteredBean()){
// skip as already inserted/updated in this request (recursive cascading)
return;
}
try {
// we have determined that it is an update
request.setType(PersistRequest.Type.UPDATE);
if (request.isPersistCascade()) {
// save associated One beans recursively first
saveAssocOne(request);
}
if (request.isDirty()) {
request.executeOrQueue();
} else {
// skip validation on unchanged bean
if (logger.isLoggable(Level.FINE)) {
logger.fine(Message.msg("persist.update.skipped", request.getBean()));
}
}
if (request.isPersistCascade()) {
// save all the beans in assocMany's after
saveAssocMany(false, request);
}
} finally {
request.unRegisterBean();
}
}
/**
* Delete the bean with the explicit transaction.
*/
public void delete(Object bean, Transaction t) {
PersistRequestBean req = createRequest(bean, t, null);
if (req.isRegisteredForDeleteBean()) {
// skip deleting bean. Used where cascade is on
// both sides of a relationship
if (logger.isLoggable(Level.FINE)) {
logger.fine("skipping delete on alreadyRegistered " + bean);
}
return;
}
req.setType(PersistRequest.Type.DELETE);
try {
req.initTransIfRequired();
delete(req);
req.commitTransIfRequired();
} catch (RuntimeException ex) {
req.rollbackTransIfRequired();
throw ex;
}
}
private void deleteList(List beanList, Transaction t) {
for (int i = 0; i < beanList.size(); i++) {
Object bean = beanList.get(i);
delete(bean, t);
}
}
/**
* Delete by a List of Id's.
*/
public void deleteMany(Class beanType, Collection ids, Transaction transaction) {
if (ids == null || ids.size() == 0) {
return;
}
BeanDescriptor descriptor = beanDescriptorManager.getBeanDescriptor(beanType);
ArrayList