// Copyright (c) 2003-2014, Jodd Team (jodd.org). All Rights Reserved.
package jodd.db.oom.dao;
import jodd.bean.BeanUtil;
import jodd.db.DbQuery;
import jodd.db.oom.DbEntityDescriptor;
import jodd.db.oom.DbOomException;
import jodd.db.oom.DbOomManager;
import jodd.db.oom.sqlgen.DbEntitySql;
import java.util.Collection;
import java.util.List;
import static jodd.db.oom.DbOomQuery.query;
import static jodd.db.oom.sqlgen.DbEntitySql.findByColumn;
import static jodd.db.oom.sqlgen.DbEntitySql.insert;
/**
* Generic DAO. Contains many convenient wrappers.
*/
public class GenericDao {
// ---------------------------------------------------------------- config
protected boolean keysGeneratedByDatabase = true;
/**
* Returns <code>true</code> if keys are auto-generated by database.
* Otherwise, keys are generated manually.
*/
public boolean isKeysGeneratedByDatabase() {
return keysGeneratedByDatabase;
}
/**
* Specifies how primary keys are generated.
*/
public void setKeysGeneratedByDatabase(boolean keysGeneratedByDatabase) {
this.keysGeneratedByDatabase = keysGeneratedByDatabase;
}
// ---------------------------------------------------------------- store
/**
* Returns <code>true</code> if entity is persistent.
*/
protected <E> boolean isPersistent(DbEntityDescriptor<E> ded, E entity) {
Object key = ded.getIdValue(entity);
if (key == null) {
return false;
}
if (key instanceof Number) {
long value = ((Number)key).longValue();
if (value == 0) {
return false;
}
}
return true;
}
/**
* Sets new ID value for entity.
*/
protected <E> void setEntityId(DbEntityDescriptor<E> ded, E entity, long newValue) {
ded.setIdValue(entity, Long.valueOf(newValue));
}
/**
* Generates next id for given type.
*/
protected long generateNextId(DbEntityDescriptor ded) {
throw new UnsupportedOperationException("Use Joy");
}
/**
* Saves or updates entity. If ID is not <code>null</code>, entity will be updated.
* Otherwise, entity will be inserted into the database.
*/
public <E> E store(E entity) {
DbOomManager dboom = DbOomManager.getInstance();
Class type = entity.getClass();
DbEntityDescriptor ded = dboom.lookupType(type);
if (ded == null) {
throw new DbOomException("Not an entity: " + type);
}
if (isPersistent(ded, entity) == false) {
DbQuery q;
if (keysGeneratedByDatabase == true) {
q = query(insert(entity));
q.setGeneratedKey();
q.executeUpdate();
long nextId = q.getGeneratedKey();
setEntityId(ded, entity, nextId);
} else {
long nextId = generateNextId(ded);
setEntityId(ded, entity, nextId);
q = query(insert(entity));
q.executeUpdate();
}
q.close();
} else {
query(DbEntitySql.updateAll(entity)).autoClose().executeUpdate();
}
return entity;
}
/**
* Simply inserts object into the database.
*/
public void save(Object entity) {
DbQuery q = query(insert(entity));
q.autoClose().executeUpdate();
}
/**
* Inserts bunch of objects into the database.
* @see #save(Object)
*/
public void saveAll(Collection entities) {
for (Object entity: entities) {
save(entity);
}
}
// ---------------------------------------------------------------- update
/**
* Updates single entity.
*/
public void update(Object entity) {
query(DbEntitySql.updateAll(entity)).autoClose().executeUpdate();
}
/**
* Updates all entities.
* @see #update(Object)
*/
public void updateAll(Collection entities) {
for (Object entity : entities) {
update(entity);
}
}
/**
* Updates single property in database and in the bean.
*/
public <E> E updateProperty(E entity, String name, Object newValue) {
query(DbEntitySql.updateColumn(entity, name, newValue)).autoClose().executeUpdate();
BeanUtil.setDeclaredProperty(entity, name, newValue);
return entity;
}
/**
* Updates property in the database by storing the current property value.
*/
public <E> E updateProperty(E entity, String name) {
Object value = BeanUtil.getDeclaredProperty(entity, name);
query(DbEntitySql.updateColumn(entity, name, value)).autoClose().executeUpdate();
return entity;
}
// ---------------------------------------------------------------- find
/**
* Finds single entity by its id.
*/
public <E> E findById(Class<E> entityType, long id) {
return query(DbEntitySql.findById(entityType, id)).autoClose().find(entityType);
}
/**
* Finds single entity by matching property.
*/
public <E> E findOneByProperty(Class<E> entityType, String name, Object value) {
return query(findByColumn(entityType, name, value)).autoClose().find(entityType);
}
/**
* Finds one entity for given criteria.
*/
@SuppressWarnings({"unchecked"})
public <E> E findOne(Object criteria) {
return (E) query(DbEntitySql.find(criteria)).autoClose().find(criteria.getClass());
}
/**
* Finds list of entities matching given criteria.
*/
@SuppressWarnings({"unchecked"})
public <E> List<E> find(Object criteria) {
return query(DbEntitySql.find(criteria)).autoClose().list(criteria.getClass());
}
/**
* Finds list of entities matching given criteria.
*/
public <E> List<E> find(Class<E> entityType, Object criteria) {
return query(DbEntitySql.find(entityType, criteria)).autoClose().list(entityType);
}
// ---------------------------------------------------------------- delete
/**
* Deleted single entity by its id.
*/
public void deleteById(Class entityType, long id) {
query(DbEntitySql.deleteById(entityType, id)).autoClose().executeUpdate();
}
/**
* Delete single object by its id. Resets ID value.
*/
public void deleteById(Object entity) {
if (entity != null) {
int result = query(DbEntitySql.deleteById(entity)).autoClose().executeUpdate();
if (result != 0) {
// now reset the ID value
DbOomManager dboom = DbOomManager.getInstance();
Class type = entity.getClass();
DbEntityDescriptor ded = dboom.lookupType(type);
setEntityId(ded, entity, 0);
}
}
}
/**
* Deletes all objects by their id.
*/
public void deleteAllById(Collection objects) {
for (Object entity : objects) {
deleteById(entity);
}
}
// ---------------------------------------------------------------- count
/**
* Counts number of all entities.
*/
public long count(Class entityType) {
return query(DbEntitySql.count(entityType)).autoClose().executeCount();
}
// ---------------------------------------------------------------- increase
/**
* Increases a property.
*/
public void increaseProperty(Class entityType, long id, String name, Number delta) {
query(DbEntitySql.increaseColumn(entityType, id, name, delta, true)).autoClose().executeUpdate();
}
/**
* Decreases a property.
*/
public void decreaseProperty(Class entityType, long id, String name, Number delta) {
query(DbEntitySql.increaseColumn(entityType, id, name, delta, false)).autoClose().executeUpdate();
}
// ---------------------------------------------------------------- related
/**
* Finds related entity.
*/
public <E> List<E> findRelated(Class<E> target, Object source) {
return query(DbEntitySql.findForeign(target, source)).autoClose().list(target);
}
// ---------------------------------------------------------------- list
/**
* List all entities.
*/
public <E> List<E> listAll(Class<E> target) {
return query(DbEntitySql.from(target)).autoClose().list(target);
}
}