package org.nutz.dao.impl;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import javax.sql.DataSource;
import org.nutz.dao.Chain;
import org.nutz.dao.Cnd;
import org.nutz.dao.Condition;
import org.nutz.dao.ConnCallback;
import org.nutz.dao.Dao;
import org.nutz.dao.DaoException;
import org.nutz.dao.FieldFilter;
import org.nutz.dao.FieldMatcher;
import org.nutz.dao.SqlManager;
import org.nutz.dao.Sqls;
import org.nutz.dao.entity.Entity;
import org.nutz.dao.entity.EntityMaker;
import org.nutz.dao.entity.LinkField;
import org.nutz.dao.entity.LinkVisitor;
import org.nutz.dao.entity.MappingField;
import org.nutz.dao.entity.Record;
import org.nutz.dao.impl.link.DoClearLinkVisitor;
import org.nutz.dao.impl.link.DoClearRelationByHostFieldLinkVisitor;
import org.nutz.dao.impl.link.DoClearRelationByLinkedFieldLinkVisitor;
import org.nutz.dao.impl.link.DoDeleteLinkVisitor;
import org.nutz.dao.impl.link.DoInsertLinkVisitor;
import org.nutz.dao.impl.link.DoInsertRelationLinkVisitor;
import org.nutz.dao.impl.link.DoUpdateLinkVisitor;
import org.nutz.dao.impl.link.DoUpdateRelationLinkVisitor;
import org.nutz.dao.impl.sql.pojo.ConditionPItem;
import org.nutz.dao.impl.sql.pojo.PojoEachEntityCallback;
import org.nutz.dao.impl.sql.pojo.PojoEachRecordCallback;
import org.nutz.dao.impl.sql.pojo.PojoFetchEntityByJoinCallback;
import org.nutz.dao.impl.sql.pojo.PojoFetchEntityCallback;
import org.nutz.dao.impl.sql.pojo.PojoFetchIntCallback;
import org.nutz.dao.impl.sql.pojo.PojoFetchObjectCallback;
import org.nutz.dao.impl.sql.pojo.PojoFetchRecordCallback;
import org.nutz.dao.impl.sql.pojo.PojoQueryEntityByJoinCallback;
import org.nutz.dao.impl.sql.pojo.PojoQueryEntityCallback;
import org.nutz.dao.impl.sql.pojo.PojoQueryRecordCallback;
import org.nutz.dao.jdbc.JdbcExpert;
import org.nutz.dao.jdbc.Jdbcs;
import org.nutz.dao.pager.Pager;
import org.nutz.dao.sql.Criteria;
import org.nutz.dao.sql.DaoStatement;
import org.nutz.dao.sql.GroupBy;
import org.nutz.dao.sql.PItem;
import org.nutz.dao.sql.Pojo;
import org.nutz.dao.sql.PojoCallback;
import org.nutz.dao.sql.Sql;
import org.nutz.dao.util.Daos;
import org.nutz.dao.util.Pojos;
import org.nutz.dao.util.cri.SqlExpressionGroup;
import org.nutz.lang.ContinueLoop;
import org.nutz.lang.Each;
import org.nutz.lang.ExitLoop;
import org.nutz.lang.Lang;
import org.nutz.lang.LoopException;
import org.nutz.lang.Strings;
import org.nutz.trans.Atom;
import org.nutz.trans.Molecule;
public class NutDao extends DaoSupport implements Dao {
private PojoCallback _pojo_queryEntity;
private PojoCallback _pojo_fetchEntity;
private PojoCallback _pojo_eachEntity;
private PojoCallback _pojo_queryRecord;
private PojoCallback _pojo_fetchRecord;
private PojoCallback _pojo_eachRecord;
private PojoCallback _pojo_fetchInt;
private PojoCallback _pojo_fetchObject;
// ==========================================================
// 下面是 3 个构造函数
public NutDao() {
super();
// 设置默认的回调
_pojo_queryEntity = new PojoQueryEntityCallback();
_pojo_fetchEntity = new PojoFetchEntityCallback();
_pojo_eachEntity = new PojoEachEntityCallback();
_pojo_fetchInt = new PojoFetchIntCallback();
_pojo_fetchObject = new PojoFetchObjectCallback();
_pojo_queryRecord = new PojoQueryRecordCallback();
_pojo_fetchRecord = new PojoFetchRecordCallback();
_pojo_eachRecord = new PojoEachRecordCallback();
}
public NutDao(DataSource dataSource) {
this();
this.setDataSource(dataSource);
}
public NutDao(DataSource dataSource, SqlManager sqlManager) {
this(dataSource);
this.setSqlManager(sqlManager);
}
public NutDao(DataSource dataSource, EntityMaker maker) {
this(dataSource);
this.holder.maker = maker;
maker.init(dataSource, expert, holder);
}
// 上面是 4 个构造函数
// ==========================================================
public <T> T getObject(Class<T> classOfT, ResultSet rs, FieldMatcher fm) {
return getObject(classOfT, rs, fm, null);
}
public <T> T getObject(Class<T> classOfT, ResultSet rs, FieldMatcher fm, String prefix) {
return holder.getEntity(classOfT).getObject(rs, fm, prefix);
}
public <T> T insert(final T obj) {
Object first = Lang.first(obj);
final EntityOperator opt = _optBy(first);
if (null == opt)
return null;
int size = Lang.length(obj);
opt.addInsert(opt.entity, first);
if (size > 1) {
if (opt.getPojoListSize() == 1) {
// 单一操作,可以转为批量插入
return fastInsert(obj);
}
Lang.each(obj, false, new Each<Object>() {
public void invoke(int i, Object ele, int length) throws ExitLoop, LoopException {
if (i != 0)
opt.addInsert(opt.entity, ele);
}
});
}
opt.exec();
return obj;
}
public <T> T insert(final T obj, FieldFilter filter) {
if (filter == null)
return insert(obj);
filter.run(new Atom() {
public void run() {
insert(obj);
}
});
return obj;
}
public void insert(String tableName, Chain chain) {
if (chain.isSpecial()) {
Daos.insertBySpecialChain(this, null, tableName, chain);
return;
}
EntityOperator opt = _optBy(chain.toEntityMap(tableName));
if (null == opt)
return;
opt.addInsert();
opt.exec();
}
public void insert(Class<?> classOfT, Chain chain) {
if (chain.isSpecial()) {
Daos.insertBySpecialChain(this, getEntity(classOfT), null, chain);
return;
}
EntityOperator opt = _opt(classOfT);
opt.myObj = chain;
opt.addInsertSelfOnly();
// insert(chain.toObject(classOfT));// TODO 这样的效率,未免太低了,需要改进
opt.exec();
}
public <T> T fastInsert(T obj) {
EntityOperator opt = _optBy(obj);
if (null == opt)
return null;
opt.addInsertSelfOnly();
opt.exec();
return obj;
}
public <T> T insertWith(T obj, String regex) {
EntityOperator opt = _optBy(obj);
if (null == opt)
return null;
final LinkVisitor one = doInsert(opt);
final boolean[] flag = new boolean[1];
// issue 889. hostField是@Id(auto=true)的时候
// 需要把相应的@One对象,押后到host对象插入之后
opt.entity.visitOne(obj, regex, new LinkVisitor() {
public void visit(Object obj, LinkField lnk) {
if (lnk.getHostField().isId()) {
flag[0] = true;
return;
}
one.visit(obj, lnk);
}
});
opt.addInsert();
opt.entity.visitMany(obj, regex, doInsert(opt));
opt.entity.visitManyMany(obj, regex, doInsert(opt));
opt.entity.visitManyMany(obj, regex, doInsertRelation(opt));
opt.exec();
if (flag[0]) {
opt = _optBy(obj);
final LinkVisitor _one = doInsert(opt);
opt.entity.visitOne(obj, regex, new LinkVisitor() {
public void visit(Object obj, LinkField lnk) {
if (!lnk.getHostField().isId())
return;
_one.visit(obj, lnk);
}
});
opt.exec();
}
return obj;
}
public <T> T insertLinks(T obj, String regex) {
// TODO 天啊,每个调用都有4个正则表达式,能快起来不?
// TODO zzh: NutEntity 会缓存正则表达式计算的结果的,会很快的
EntityOperator opt = _optBy(obj);
if (null == opt)
return null;
opt.entity.visitOne(obj, regex, doInsert(opt));
opt.entity.visitMany(obj, regex, doInsert(opt));
opt.entity.visitManyMany(obj, regex, doInsert(opt));
opt.entity.visitManyMany(obj, regex, doInsertRelation(opt));
opt.exec();
return obj;
}
public <T> T insertRelation(T obj, String regex) {
EntityOperator opt = _optBy(obj);
if (null == opt)
return null;
opt.entity.visitManyMany(obj, regex, doInsertRelation(opt));
opt.exec();
return obj;
}
public int update(Object obj) {
EntityOperator opt = _optBy(obj);
if (null == opt)
return 0;
opt.addUpdate();
opt.exec();
return opt.getUpdateCount();
}
public int update(final Object obj, String actived) {
Object first = Lang.first(obj);
if (null == first)
return 0;
if (Strings.isBlank(actived))
return update(obj);
return update(obj, FieldFilter.create(first.getClass(), actived));
}
public int update(final Object obj, String actived, String locked, boolean ignoreNull) {
Object first = Lang.first(obj);
if (null == first)
return 0;
return update(obj, FieldFilter.create(first.getClass(), actived, locked, ignoreNull));
}
public int update(final Object obj, FieldFilter fieldFilter) {
if (fieldFilter == null)
return update(obj);
return fieldFilter.run(new Molecule<Integer>() {
public void run() {
setObj(update(obj));
}
});
}
public int update(final Object obj, FieldFilter fieldFilter, final Condition cnd) {
if (fieldFilter == null)
return update(obj, cnd);
return fieldFilter.run(new Molecule<Integer>() {
public void run() {
setObj(update(obj, cnd));
}
});
}
public int update(Object obj, Condition cnd) {
if (cnd == null)
return update(obj);
EntityOperator opt = _optBy(obj);
if (null == opt)
return 0;
opt.addUpdateByPkAndCnd(cnd);
opt.exec();
return opt.getUpdateCount();
}
public int updateIgnoreNull(final Object obj) {
EntityOperator opt = _optBy(obj);
if (null == opt)
return 0;
opt.addUpdateForIgnoreNull(opt.entity, obj, FieldFilter.get(opt.entity.getType()));
opt.exec();
return opt.getUpdateCount();
}
public int update(String tableName, Chain chain, Condition cnd) {
EntityOperator opt = _optBy(chain.toEntityMap(tableName));
if (null == opt)
return 0;
opt.addUpdate(chain, cnd);
opt.exec();
return opt.getUpdateCount();
}
public int update(Class<?> classOfT, Chain chain, Condition cnd) {
EntityOperator opt = _opt(classOfT);
opt.addUpdate(chain, cnd);
opt.exec();
return opt.getUpdateCount();
}
public <T> T updateWith(T obj, final String regex) {
if (null == obj)
return null;
Lang.each(obj, false, new Each<Object>() {
public void invoke(int index, Object ele, int length) throws ExitLoop, ContinueLoop,
LoopException {
EntityOperator opt = _optBy(ele);
if (null == opt)
return;
opt.entity.visitOne(ele, regex, doUpdate(opt));
opt.addUpdate();
opt.entity.visitMany(ele, regex, doUpdate(opt));
opt.entity.visitManyMany(ele, regex, doUpdate(opt));
opt.exec();
}
});
return obj;
}
public <T> T updateLinks(T obj, final String regex) {
if (null == obj)
return null;
Lang.each(obj, false, new Each<Object>() {
public void invoke(int index, Object ele, int length) throws ExitLoop, ContinueLoop,
LoopException {
EntityOperator opt = _optBy(ele);
if (null == opt)
return;
opt.entity.visitOne(ele, regex, doUpdate(opt));
opt.entity.visitMany(ele, regex, doUpdate(opt));
opt.entity.visitManyMany(ele, regex, doUpdate(opt));
opt.exec();
}
});
return obj;
}
public int updateRelation(Class<?> classOfT, String regex, Chain chain, Condition cnd) {
if (chain.isSpecial())
throw Lang.noImplement();
EntityOperator opt = this._opt(classOfT);
opt.entity.visitManyMany(null, regex, doUpdateRelation(opt, chain, cnd));
opt.exec();
return opt.getUpdateCount();
}
public int delete(Class<?> classOfT, long id) {
Entity<?> en = holder.getEntity(classOfT);
Pojo pojo = pojoMaker.makeDelete(en).append(Pojos.Items.cndId(en, id));
pojo.addParamsBy(id);
_exec(pojo);
return pojo.getUpdateCount();
}
public int delete(Class<?> classOfT, String name) {
Entity<?> en = holder.getEntity(classOfT);
Pojo pojo = pojoMaker.makeDelete(en)
.append(Pojos.Items.cndName(en, name))
.addParamsBy(name);
_exec(pojo);
return pojo.getUpdateCount();
}
public <T> int deletex(Class<T> classOfT, Object... pks) {
Entity<T> en = holder.getEntity(classOfT);
Pojo pojo = pojoMaker.makeDelete(en).append(Pojos.Items.cndPk(en, pks));
_exec(pojo);
return pojo.getUpdateCount();
}
public int delete(Object obj) {
EntityOperator opt = _optBy(obj);
if (null == opt)
return 0;
opt.addDeleteSelfOnly();
opt.exec();
return opt.getUpdateCount();
}
public int deleteWith(Object obj, final String regex) {
if (null == obj)
return 0;
final int[] re = new int[1];
Lang.each(obj, false, new Each<Object>() {
public void invoke(int index, Object ele, int length) throws ExitLoop, ContinueLoop,
LoopException {
EntityOperator opt = _optBy(ele);
if (null == opt)
return;
opt.entity.visitMany(ele, regex, doDelete(opt));
opt.entity.visitManyMany(ele, regex, doClearRelationByLinkedField(opt));
opt.entity.visitManyMany(ele, regex, doDelete(opt));
opt.addDeleteSelfOnly();
opt.entity.visitOne(ele, regex, doDelete(opt));
re[0] += opt.exec().getUpdateCount();
}
});
return re[0];
}
public int deleteLinks(Object obj, final String regex) {
if (null == obj)
return 0;
final int[] re = new int[1];
Lang.each(obj, false, new Each<Object>() {
public void invoke(int index, Object ele, int length) throws ExitLoop, ContinueLoop,
LoopException {
EntityOperator opt = _optBy(ele);
if (null == opt)
return;
opt.entity.visitMany(ele, regex, doDelete(opt));
opt.entity.visitManyMany(ele, regex, doClearRelationByLinkedField(opt));
opt.entity.visitManyMany(ele, regex, doDelete(opt));
opt.entity.visitOne(ele, regex, doDelete(opt));
re[0] += opt.exec().getUpdateCount();
}
});
return re[0];
}
public <T> List<T> query(Class<T> classOfT, Condition cnd, Pager pager) {
Pojo pojo = pojoMaker.makeQuery(holder.getEntity(classOfT))
.append(Pojos.Items.cnd(cnd))
.addParamsBy("*")
.setPager(pager)
.setAfter(_pojo_queryEntity);
expert.formatQuery(pojo);
_exec(pojo);
return pojo.getList(classOfT);
}
public <T> List<T> query(Class<T> classOfT, Condition cnd) {
return query(classOfT, cnd, Pojos.Items.pager(cnd));
}
public <T> int each(Class<T> classOfT, Condition cnd, Pager pager, Each<T> callback) {
Pojo pojo = pojoMaker.makeQuery(holder.getEntity(classOfT))
.append(Pojos.Items.cnd(cnd))
.addParamsBy("*")
.setPager(pager)
.setAfter(_pojo_queryEntity);
expert.formatQuery(pojo);
pojo.setAfter(_pojo_eachEntity);
pojo.getContext().attr(Each.class.getName(), callback);
pojo.getContext().attr("dao-cache-skip", "true");
_exec(pojo);
return pojo.getInt();
}
public <T> int each(Class<T> classOfT, Condition cnd, Each<T> callback) {
return each(classOfT, cnd, Pojos.Items.pager(cnd), callback);
}
public List<Record> query(String tableName, Condition cnd, Pager pager) {
return query(tableName, cnd, pager, "*");
}
public List<Record> query(String tableName, Condition cnd, Pager pager, String fields) {
Pojo pojo = pojoMaker.makeQuery(tableName, fields)
.addParamsBy(fields)
.setPager(pager)
.append(Pojos.Items.cnd(cnd));
expert.formatQuery(pojo);
pojo.setAfter(_pojo_queryRecord);
_exec(pojo);
return pojo.getList(Record.class);
}
public List<Record> query(String tableName, Condition cnd) {
return query(tableName, cnd, Pojos.Items.pager(cnd));
}
public int each(String tableName, Condition cnd, Pager pager, Each<Record> callback, String fields) {
Pojo pojo = pojoMaker.makeQuery(tableName, fields)
.addParamsBy(fields)
.setPager(pager)
.append(Pojos.Items.cnd(cnd));
expert.formatQuery(pojo);
pojo.setAfter(_pojo_eachRecord);
pojo.getContext().attr(Each.class.getName(), callback);
pojo.getContext().attr("dao-cache-skip", "true");
_exec(pojo);
return pojo.getInt();
}
public int each(String tableName, Condition cnd, Pager pager, Each<Record> callback) {
return each(tableName, cnd, pager, callback, "*");
}
public int each(String tableName, Condition cnd, Each<Record> callback) {
return each(tableName, cnd, Pojos.Items.pager(cnd), callback);
}
public <T> T fetch(Class<T> classOfT, long id) {
Entity<T> en = holder.getEntity(classOfT);
if (en.getIdField() == null)
throw new DaoException("Need @Id for " + classOfT);
Pojo pojo = pojoMaker.makeQuery(en)
.append(Pojos.Items.cndId(en, id))
.addParamsBy(id)
.setAfter(_pojo_fetchEntity);
_exec(pojo);
return pojo.getObject(classOfT);
}
public <T> T fetch(Class<T> classOfT, String name) {
if (name == null)
throw new IllegalArgumentException("name MUST NOT NULL!");
Entity<T> en = holder.getEntity(classOfT);
if (en.getNameField() == null)
throw new DaoException("Need @Name for " + classOfT);
Pojo pojo = pojoMaker.makeQuery(en)
.append(Pojos.Items.cndName(en, name))
.addParamsBy(name)
.setAfter(_pojo_fetchEntity);
_exec(pojo);
return pojo.getObject(classOfT);
}
public <T> T fetchx(Class<T> classOfT, Object... pks) {
Entity<T> en = holder.getEntity(classOfT);
Pojo pojo = pojoMaker.makeQuery(en)
.append(Pojos.Items.cndPk(en, pks))
.setAfter(_pojo_fetchEntity);
_exec(pojo);
return pojo.getObject(classOfT);
}
public <T> T fetch(Class<T> classOfT, Condition cnd) {
Pojo pojo = pojoMaker.makeQuery(holder.getEntity(classOfT))
.append(Pojos.Items.cnd(cnd))
.addParamsBy("*")
.setPager(createPager(1, 1))
.setAfter(_pojo_fetchEntity);
expert.formatQuery(pojo);
_exec(pojo);
return pojo.getObject(classOfT);
}
public Record fetch(String tableName, Condition cnd) {
return fetch(tableName, cnd, "*");
}
public Record fetch(String tableName, Condition cnd, String fields) {
Pojo pojo = pojoMaker.makeQuery(tableName, fields)
.append(Pojos.Items.cnd(cnd))
.addParamsBy(fields)
.setPager(createPager(1, 1))
.setAfter(_pojo_fetchRecord);
expert.formatQuery(pojo);
_exec(pojo);
return pojo.getObject(Record.class);
}
@SuppressWarnings("unchecked")
public <T> T fetch(T obj) {
Entity<?> en = holder.getEntityBy(obj);
Pojo pojo = pojoMaker.makeQuery(en)
.append(Pojos.Items.cndAuto(en, obj))
.setAfter(_pojo_fetchEntity)
.setPager(createPager(1, 1));
_exec(pojo);
return (T) pojo.getResult();
}
public <T> T fetch(Class<T> classOfT) {
List<T> list = query(classOfT, null, createPager(1, 1));
if (null != list && !list.isEmpty())
return list.get(0);
return null;
}
public <T> T fetchLinks(T obj, final String regex) {
return fetchLinks(obj, regex, null);
}
public <T> T fetchLinks(final T obj, final String regex, final Condition cnd) {
if (null == obj)
return null;
Lang.each(obj, false, new Each<Object>() {
public void invoke(int index, Object ele, int length) {
_fetchLinks(ele, regex, true, true, true, cnd);
}
});
return obj;
}
public int clear(Class<?> classOfT, Condition cnd) {
Pojo pojo = pojoMaker.makeDelete(holder.getEntity(classOfT)).append(Pojos.Items.cnd(cnd));
_exec(pojo);
return pojo.getUpdateCount();
}
public int clear(String tableName, Condition cnd) {
Pojo pojo = pojoMaker.makeDelete(tableName).append(Pojos.Items.cnd(cnd));
_exec(pojo);
return pojo.getUpdateCount();
}
public int clear(Class<?> classOfT) {
return clear(classOfT, null);
}
public int clear(String tableName) {
return clear(tableName, null);
}
public <T> T clearLinks(T obj, final String regex) {
if (null == obj)
return null;
Lang.each(obj, false, new Each<Object>() {
public void invoke(int index, Object ele, int length) {
EntityOperator opt = _optBy(ele);
if (null == opt)
return;
opt.entity.visitMany(ele, regex, doClear(opt));
opt.entity.visitManyMany(ele, regex, doClearRelationByHostField(opt));
opt.entity.visitOne(ele, regex, doClear(opt));
opt.exec();
}
});
return obj;
}
public <T> Entity<T> getEntity(Class<T> classOfT) {
return holder.getEntity(classOfT);
}
public int count(Class<?> classOfT, Condition cnd) {
Entity<?> en = holder.getEntity(classOfT);
return _count(en, en.getViewName(), cnd);
}
public int count(Class<?> classOfT) {
Entity<?> en = holder.getEntity(classOfT);
return _count(en, en.getViewName(), null);
}
public int count(String tableName) {
return count(tableName, null);
}
public int count(String tableName, Condition cnd) {
return _count(null, tableName, cnd);
}
private int _count(Entity<?> en, String tableName, Condition cnd) {
// 如果有条件的话
if (null != cnd) {
Pojo pojo = pojoMaker.makeFunc(tableName, "COUNT", "*");
pojo.setEntity(en);
// 高级条件接口,直接得到 WHERE 子句
if (cnd instanceof Criteria) {
pojo.append(((Criteria) cnd).where());
// MySQL/PgSQL/SqlServer 与 Oracle/H2的结果会不一样,奇葩啊
GroupBy gb = ((Criteria) cnd).getGroupBy();
if (gb != null)
pojo.append(gb);
}
// 否则暴力获取 WHERE 子句
else {
String str = Pojos.formatCondition(en, cnd);
if (!Strings.isBlank(str)) {
String[] ss = str.toUpperCase().split("ORDER BY");
pojo.append(Pojos.Items.wrap(str.substring(0, ss[0].length())));
}
}
// 设置回调,并执行 SQL
pojo.setAfter(_pojo_fetchInt);
_exec(pojo);
return pojo.getInt();
}
// 没有条件,直接生成表达式
return func(tableName, "COUNT", "*");
}
public int getMaxId(Class<?> classOfT) {
Entity<?> en = holder.getEntity(classOfT);
return func(en.getViewName(), "MAX", en.getIdField().getColumnNameInSql());
}
public int func(Class<?> classOfT, String funcName, String fieldName) {
return func(classOfT, funcName, fieldName, null);
}
public int func(String tableName, String funcName, String colName) {
return func(tableName, funcName, colName, null);
}
public int func(Class<?> classOfT, String funcName, String colName, Condition cnd) {
Entity<?> en = holder.getEntity(classOfT);
if (null != en.getField(colName))
colName = en.getField(colName).getColumnNameInSql();
DaoStatement pojo = pojoMaker.makeFunc(en.getViewName(), funcName, colName)
.append(Pojos.Items.cnd(cnd))
.setAfter(_pojo_fetchInt)
.setEntity(en);
_exec(pojo);
return pojo.getInt();
}
public int func(String tableName, String funcName, String colName, Condition cnd) {
DaoStatement pojo = pojoMaker.makeFunc(tableName, funcName, colName)
.append(Pojos.Items.cnd(cnd))
.setAfter(_pojo_fetchInt);
_exec(pojo);
return pojo.getInt();
}
public Object func2(Class<?> classOfT, String func2Name, String fieldName) {
return func2(classOfT, func2Name, fieldName, null);
}
public Object func2(String tableName, String func2Name, String colName) {
return func2(tableName, func2Name, colName, null);
}
public Object func2(Class<?> classOfT, String func2Name, String colName, Condition cnd) {
Entity<?> en = holder.getEntity(classOfT);
if (null != en.getField(colName))
colName = en.getField(colName).getColumnNameInSql();
DaoStatement pojo = pojoMaker.makeFunc(en.getViewName(), func2Name, colName)
.append(Pojos.Items.cnd(cnd))
.setAfter(_pojo_fetchObject)
.setEntity(en);
_exec(pojo);
return pojo.getResult();
}
public Object func2(String tableName, String func2Name, String colName, Condition cnd) {
DaoStatement pojo = pojoMaker.makeFunc(tableName, func2Name, colName)
.append(Pojos.Items.cnd(cnd))
.setAfter(_pojo_fetchObject);
_exec(pojo);
return pojo.getResult();
}
public Pager createPager(int pageNumber, int pageSize) {
Pager pager = new Pager();
pager.setPageNumber(pageNumber);
pager.setPageSize(pageSize);
return pager;
}
public synchronized <T> Entity<T> create(Class<T> classOfT, boolean dropIfExists) {
Entity<T> en = holder.getEntity(classOfT);
if (exists(en.getTableName())) {
if (dropIfExists) {
expert.dropEntity(this, en);
} else {
expert.createRelation(this, en);
return en;
}
}
holder.remove(classOfT.getName());
final Entity<T> _en = holder.getEntity(classOfT);
expert.createEntity(this, _en);
// 最后在数据库中验证一下实体各个字段
run(new ConnCallback() {
public void invoke(Connection conn) throws Exception {
expert.setupEntityField(conn, _en);
}
});
return en;
}
public boolean drop(Class<?> classOfT) {
Entity<?> en = holder.getEntity(classOfT);
if (!exists(en.getTableName()))
return false;
return expert.dropEntity(this, en);
}
public boolean drop(String tableName) {
if (!exists(tableName))
return false;
Sql sql = Sqls.createf("DROP TABLE %s", tableName);
_exec(sql);
return true;
}
public boolean exists(Class<?> classOfT) {
return exists(getEntity(classOfT).getViewName());
}
public boolean exists(final String tableName) {
final boolean[] ee = {false};
this.run(new ConnCallback() {
public void invoke(Connection conn) {
Statement stat = null;
ResultSet rs = null;
try {
stat = conn.createStatement();
// 增加不等式,减少sql执行时间
String sql = "SELECT COUNT(1) FROM " + tableName + " where 1!=1";
rs = stat.executeQuery(sql);
if (rs.next())
ee[0] = true;
}
catch (SQLException e) {}
finally {
Daos.safeClose(stat, rs);
}
}
});
return ee[0];
}
// ==========================================================
// 下面几个是快速创建映射操作回调的帮助函数
private LinkVisitor doInsert(EntityOperator opt) {
return new DoInsertLinkVisitor().opt(opt);
}
private LinkVisitor doInsertRelation(EntityOperator opt) {
return new DoInsertRelationLinkVisitor(holder).opt(opt);
}
private LinkVisitor doUpdate(EntityOperator opt) {
return new DoUpdateLinkVisitor().opt(opt);
}
private LinkVisitor doUpdateRelation(EntityOperator opt, Chain chain, Condition cnd) {
return new DoUpdateRelationLinkVisitor(chain.toMap(), cnd).opt(opt);
}
private LinkVisitor doClearRelationByLinkedField(EntityOperator opt) {
return new DoClearRelationByLinkedFieldLinkVisitor().opt(opt);
}
private LinkVisitor doClearRelationByHostField(EntityOperator opt) {
return new DoClearRelationByHostFieldLinkVisitor().opt(opt);
}
private LinkVisitor doDelete(EntityOperator opt) {
return new DoDeleteLinkVisitor().opt(opt);
}
private LinkVisitor doClear(EntityOperator opt) {
return new DoClearLinkVisitor().opt(opt);
}
private LinkVisitor doFetch(final EntityOperator opt) {
return new LinkVisitor() {
public void visit(final Object obj, final LinkField lnk) {
Pojo pojo = opt.maker().makeQuery(lnk.getLinkedEntity());
pojo.setOperatingObject(obj);
pojo.append(Pojos.Items.cnd(lnk.createCondition(obj)));
pojo.setAfter(lnk.getCallback());
_exec(pojo);
lnk.setValue(obj, pojo.getObject(Object.class));
}
};
}
private LinkVisitor doLinkQuery(final EntityOperator opt, final Condition cnd) {
return new LinkVisitor() {
public void visit(final Object obj, final LinkField lnk) {
Pojo pojo = opt.maker().makeQuery(lnk.getLinkedEntity());
pojo.setOperatingObject(obj);
PItem[] _cndItems = Pojos.Items.cnd(lnk.createCondition(obj));
pojo.append(_cndItems);
if (cnd != null) {
if (cnd instanceof Criteria) {
Criteria cri = (Criteria) cnd;
SqlExpressionGroup seg = cri.where();
if (_cndItems.length > 0 && seg != null && !seg.isEmpty()) {
seg.setTop(false);
pojo.append(Pojos.Items.wrap(" AND "));
}
pojo.append(cri);
if (cri.getPager() != null) {
pojo.setPager(cri.getPager());
expert.formatQuery(pojo);
}
}
// 普通条件
else {
pojo.append(new ConditionPItem(cnd));
}
}
pojo.setAfter(lnk.getCallback());
pojo.setEntity(lnk.getLinkedEntity());
_exec(pojo);
lnk.setValue(obj, pojo.getResult());
}
};
}
// ==========================================================
// 下面几个是快速创建实体操作对象的帮助函数
private <T> EntityOperator _opt() {
EntityOperator opt = new EntityOperator();
opt.dao = this;
return opt;
}
<T> EntityOperator _opt(Entity<T> en) {
EntityOperator opt = _opt();
opt.entity = en;
return opt;
}
<T> EntityOperator _opt(Class<T> classOfT) {
return _opt(holder.getEntity(classOfT));
}
EntityOperator _optBy(Object obj) {
// 阻止空对象
if (null == obj)
return null;
// 对象是否有内容,这里会考虑集合与数组
Entity<?> en = holder.getEntityBy(obj);
if (null == en)
return null;
// 创建操作对象
EntityOperator re = _opt(en);
re.myObj = obj.getClass().isArray() ? Lang.array2list((Object[]) obj) : obj;
return re;
}
// ---------------------------------------------------------------
// 专属于NutDao的一些帮助方法
public void setExpert(Object obj) throws Exception {
if (obj == null)
throw new NullPointerException("expert MUST NOT NULL!!");
if (obj instanceof JdbcExpert) {
this.expert = (JdbcExpert) obj;
} else {
String name = obj.toString();
this.expert = Jdbcs.getExpert(name, "");
if (this.expert == null) {
if (name.contains(".")) {
this.expert = (JdbcExpert) Lang.loadClass(name).newInstance();
} else {
throw new DaoException("not such expert=" + obj);
}
}
}
DataSource ds = this.dataSource;
// 如果数据源比expert先设置,那么需要重新设置一次
if (ds != null) {
this.dataSource = null;
setDataSource(ds);
}
}
public Sql execute(Sql sql) {
if (sql != null)
execute(new Sql[]{sql});
return sql;
}
public <T> T insert(final T t, boolean ignoreNull, boolean ignoreZero, boolean ignoreBlankStr) {
Object obj = Lang.first(t);
Entity<?> en = getEntity(obj.getClass());
List<String> names = new ArrayList<String>();
for (MappingField mf : en.getMappingFields()) {
Object tmp = mf.getValue(obj);
if (ignoreNull && tmp == null) {
continue;
}
if (ignoreZero && (tmp == null || (tmp instanceof Number && ((Number)tmp).intValue() == 0))) {
continue;
}
if (ignoreBlankStr && (tmp instanceof CharSequence && Strings.isBlank((CharSequence)tmp)))
continue;
names.add(mf.getName());
}
FieldFilter ff = FieldFilter.create(obj.getClass(), "^("+Strings.join("|", names.toArray())+")$");
Molecule<T> m = new Molecule<T>() {
public void run() {
insert(t);
setObj(t);
}
};
return ff.run(m);
}
public <T> List<T> query(final Class<T> classOfT, final Condition cnd, final Pager pager, FieldMatcher matcher) {
if (matcher == null)
return query(classOfT, cnd, pager);
FieldFilter ff = FieldFilter.create(classOfT, matcher);
Molecule<List<T>> m = new Molecule<List<T>>() {
public void run() {
setObj(query(classOfT, cnd, pager));
}
};
return ff.run(m);
}
public <T> List<T> query(final Class<T> classOfT, final Condition cnd, final Pager pager, String regex) {
if (regex == null)
return query(classOfT, cnd, pager);
FieldFilter ff = FieldFilter.create(classOfT, FieldMatcher.make(regex, null, false));
Molecule<List<T>> m = new Molecule<List<T>>() {
public void run() {
setObj(query(classOfT, cnd, pager));
}
};
return ff.run(m);
}
public <T> T insertOrUpdate(T t) {
return insertOrUpdate(t, null, null);
}
public <T> T insertOrUpdate(T t, FieldFilter insertFieldFilter, FieldFilter updateFieldFilter) {
if (t == null)
return null;
if (fetch(t) != null)
update(t, updateFieldFilter);
else
insert(t, insertFieldFilter);
return t;
}
public int updateAndIncrIfMatch(final Object obj, FieldFilter fieldFilter, String fieldName) {
final EntityOperator opt = _optBy(obj);
if (null == opt)
return 0;
if (fieldName == null)
fieldName = "version";
if (fieldFilter == null)
fieldFilter = FieldFilter.create(opt.entity.getType(), null, "^"+fieldName+"$", false);
else {
FieldMatcher fieldMatcher = fieldFilter.map().get(opt.entity.getType());
if (fieldMatcher == null) {
fieldMatcher = FieldMatcher.make(null, "^"+fieldName+"$", false);
fieldFilter.map().put(opt.entity.getType(), fieldMatcher);
} else {
if (fieldMatcher.getLocked() == null) {
fieldMatcher.setLocked("^"+fieldName+"$");
}
}
}
final String _fieldName = fieldName;
fieldFilter.run(new Atom() {
public void run() {
opt.addUpdateAndIncrIfMatch(opt.entity, obj, _fieldName);
opt.exec();}
});
return opt.getUpdateCount();
}
public int updateWithVersion(Object obj) {
return updateWithVersion(obj, null);
}
public int updateWithVersion(Object obj, FieldFilter fieldFilter) {
return updateAndIncrIfMatch(obj, fieldFilter, getEntity(Lang.first(obj).getClass()).getVersionField().getName());
}
public <T> T fetchByJoin(Class<T> klass, String regex, long id) {
Entity<T> en = getEntity(klass);
MappingField mf = en.getIdField();
return fetchByJoin(klass, regex, en, mf, id);
}
public <T> T fetchByJoin(Class<T> klass, String regex, String name) {
Entity<T> en = getEntity(klass);
MappingField mf = en.getNameField();
return fetchByJoin(klass, regex, en, mf, name);
}
public <T> T fetchByJoin(Class<T> klass, String regex, Entity<T> en, MappingField mf, Object value) {
String key = en.getTableName() + "." + mf.getColumnNameInSql();
T t = fetchByJoin(klass, regex, Cnd.where(key, "=", value));
if (t != null)
_fetchLinks(t, regex, false, true, true, null);
return t;
}
public <T> T fetchByJoin(Class<T> classOfT, String regex, Condition cnd) {
Pojo pojo = pojoMaker.makeQueryByJoin(holder.getEntity(classOfT), regex)
.append(Pojos.Items.cnd(cnd))
.addParamsBy("*")
.setPager(createPager(1, 1))
.setAfter(new PojoFetchEntityByJoinCallback(regex));
expert.formatQuery(pojo);
_exec(pojo);
T t = pojo.getObject(classOfT);
if (t != null)
_fetchLinks(t, regex, false, true, true, null);
return t;
}
public <T> List<T> queryByJoin(Class<T> classOfT, String regex, Condition cnd) {
Pojo pojo = pojoMaker.makeQueryByJoin(holder.getEntity(classOfT), regex)
.append(Pojos.Items.cnd(cnd))
.addParamsBy("*")
.setAfter(new PojoQueryEntityByJoinCallback(regex));
expert.formatQuery(pojo);
_exec(pojo);
List<T> list = pojo.getList(classOfT);
if (list != null && list.size() > 0)
for (T t : list) {
_fetchLinks(t, regex, false, true, true, null);
}
return list;
}
protected Object _fetchLinks(Object t, String regex, boolean visitOne, boolean visitMany, boolean visitManyMany, final Condition cnd) {
EntityOperator opt = _optBy(t);
if (null == opt)
return t;
if (visitMany)
opt.entity.visitMany(t, regex, doLinkQuery(opt, cnd));
if (visitManyMany)
opt.entity.visitManyMany(t, regex, doLinkQuery(opt, cnd));
if (visitOne)
opt.entity.visitOne(t, regex, doFetch(opt));
opt.exec();
return t;
}
public EntityHolder getEntityHolder() {
return holder;
}
}