package com.bimoku.persistence.dao.impl;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.Serializable;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Types;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.annotation.Resource;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Transient;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.PreparedStatementCreator;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;
import com.bimoku.persistence.bean.PageBean;
import com.bimoku.persistence.dao.BaseDao;
import com.bimoku.persistence.exception.DaoException;
import com.bimoku.util.db.BeanUtilsBean;
/**
* 基础数据操作mysql实现
* 包含:
* 批量增删改查
* 获取单一类型(int,long)类型的值
* 基本数据查询
* @date 2013-8-20
* @version v0.1.2[last version]
* @author LPM
* @param <T>
* @param <ID>
*/
public abstract class BaseDaoMysqlImpl<T, ID extends Serializable> extends
JdbcDaoSupport implements BaseDao<T, ID> {
public final Log log = LogFactory.getLog(this.getClass());
private Class<T> persistentClass;
private String tableName = "";
private String pk = "";
private GenerationType strategy;
protected List<String> transientPropertys = new ArrayList<String>();
protected BaseDaoMysqlImpl(Class<T> persistentClass) {
this.persistentClass = persistentClass;
Table table = AnnotationUtils.findAnnotation(persistentClass,
Table.class);
if (table == null) {
throw new RuntimeException(persistentClass + "没有定义@table");
}
this.tableName = table.name();
BeanInfo beanInfo = null;
try {
beanInfo = Introspector.getBeanInfo(persistentClass);
} catch (IntrospectionException e) {
log.error(e.getMessage(), e);
}
PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();
for (PropertyDescriptor pd : pds) {
Id id = AnnotationUtils
.findAnnotation(pd.getReadMethod(), Id.class);
if (pk.equals("") && id != null) {
pk = pd.getName();
GeneratedValue gv = AnnotationUtils.findAnnotation(
pd.getReadMethod(), GeneratedValue.class);
if (gv == null) {
strategy = GenerationType.IDENTITY;
} else {
strategy = gv.strategy();
}
}
Transient transient_ = AnnotationUtils.findAnnotation(
pd.getReadMethod(), Transient.class);
if (transient_ != null) {
transientPropertys.add(pd.getName());
}
}
if ("".equals(this.getPk())) {
throw new RuntimeException(persistentClass + "类型中没有在get方法上定义@Id");
}
}
protected BaseDaoMysqlImpl() {
}
@Override
public String getTableName() {
return tableName;
}
@Override
public String getPk() {
return pk;
}
@Resource(name = "jdbcTemplate")
public void setJb(JdbcTemplate jb) {
super.setJdbcTemplate(jb);
}
@Override
public List<T> getAll() {
StringBuilder sb = new StringBuilder("select * from ");
sb.append(this.getTableName());
return this.search(sb.toString(), null);
}
@Override
public List<T> search(String sql, List<Object> values) {
if (StringUtils.isEmpty(sql))
return new ArrayList<T>();
if (values == null)
values = new ArrayList<Object>();
if (log.isDebugEnabled()) {
log.debug("sql : " + sql + " values:" + values);
}
List<T> list = this.getJdbcTemplate().query(sql, values.toArray(),
new BeanPropertyRowMapper<T>(this.persistentClass));
return list == null ? new ArrayList<T>() : list;
}
@Override
public PageBean<T> search(T t, PageBean<T> pageBean) {
Map<String, Object> map;
try {
map = BeanUtilsBean.getInstance().describe(t);
for (String proterty : transientPropertys) {
map.remove(proterty);
}
} catch (Exception e) {
throw new DaoException("模型类解析异常!", e);
}
return this.search(map, pageBean);
}
@SuppressWarnings("unchecked")
protected PageBean<T> search(Map<String, Object> map, PageBean<T> pageBean) {
ID id = (ID) map.get(this.getPk());
if (map != null && id != null) {
map.remove(id);
}
List<String> removekeys = new ArrayList<String>();
for (Entry<String, Object> entry : map.entrySet()) {
if (entry.getValue() == null) {
removekeys.add(entry.getKey());
}
}
for (String key : removekeys) {
map.remove(key);
}
List<Object> values = new ArrayList<Object>();
StringBuilder sb = new StringBuilder("select * from ");
sb.append(this.getTableName());
if (map.size() != 0) {
sb.append(" where ");
for (Entry<String, Object> entry : map.entrySet()) {
sb.append(entry.getKey());
sb.append("=? ");
values.add(entry.getValue());
sb.append(" and ");
}
}
this.deleteLastStr(sb, "and");
this.search(sb.toString(), values, pageBean);
return pageBean;
}
protected List<T> search(Map<String, Object> map) {
if (map == null || map.isEmpty())
return null;
@SuppressWarnings("unchecked")
ID id = (ID) map.get(this.getPk());
if (id != null) {
map.remove(id);
}
List<String> removekeys = new ArrayList<String>();
for (Entry<String, Object> entry : map.entrySet()) {
if (entry.getValue() == null) {
removekeys.add(entry.getKey());
}
}
for (String key : removekeys) {
map.remove(key);
}
List<Object> values = new ArrayList<Object>();
StringBuilder sb = new StringBuilder("select * from ");
sb.append(this.getTableName());
if (map.size() != 0) {
sb.append(" where ");
for (Entry<String, Object> entry : map.entrySet()) {
sb.append(entry.getKey());
sb.append("=? ");
values.add(entry.getValue());
sb.append(" and ");
}
this.deleteLastStr(sb, "and");
}
return this.search(sb.toString(), values);
}
protected T searchOne(Map<String, Object> map) {
if (map == null || map.isEmpty())
return null;
@SuppressWarnings("unchecked")
ID id = (ID) map.get(this.getPk());
if (id != null) {
map.remove(id);
}
List<String> removekeys = new ArrayList<String>();
for (Entry<String, Object> entry : map.entrySet()) {
if (entry.getValue() == null) {
removekeys.add(entry.getKey());
}
}
for (String key : removekeys) {
map.remove(key);
}
List<Object> values = new ArrayList<Object>();
StringBuilder sb = new StringBuilder("select * from ");
sb.append(this.getTableName());
if (map.size() != 0) {
sb.append(" where ");
for (Entry<String, Object> entry : map.entrySet()) {
sb.append(entry.getKey());
sb.append("=? ");
values.add(entry.getValue());
sb.append(" and ");
}
this.deleteLastStr(sb, "and");
}
List<T> list = this.search(sb.toString(), values);
if (list != null && list.size() != 0) {
return list.get(0);
} else {
return null;
}
}
protected int add(String sql, List<Object> values) {
if (StringUtils.isEmpty(sql))
return 0;
if (values == null)
values = new ArrayList<Object>();
if (log.isDebugEnabled()) {
log.debug("sql : " + sql + " values:" + values);
}
return this.getJdbcTemplate().update(sql, values.toArray());
}
@Override
public ID addReturnId(final String sql, final List<Object> values) {
JdbcTemplate template = this.getJdbcTemplate();
KeyHolder keyHolder = new GeneratedKeyHolder();
if (log.isDebugEnabled()) {
log.debug("sql : " + sql + " values:" + values);
}
template.update(new PreparedStatementCreator() {
public PreparedStatement createPreparedStatement(Connection con)
throws SQLException {
int i = 0;
PreparedStatement ps = con.prepareStatement(sql,
Statement.RETURN_GENERATED_KEYS);
for (i = 0; i < values.size(); i++) {
Object value = values.get(i);
if (value != null) {
if (value instanceof java.lang.Integer) {
ps.setInt(i + 1, (Integer) value);
} else if (value instanceof java.lang.Long) {
ps.setLong(i + 1, (Long) value);
} else if (value instanceof java.util.Date) {
ps.setDate(i + 1,
new java.sql.Date(((Date) value).getTime()));
ps.setTimestamp(i + 1, new java.sql.Timestamp(
((Date) value).getTime()));
} else if (value instanceof java.lang.String) {
ps.setString(i + 1, value.toString());
} else if (value instanceof java.lang.Double) {
ps.setDouble(i + 1, (Double) value);
} else if (value instanceof java.lang.Byte) {
ps.setByte(i + 1, (Byte) value);
} else if (value instanceof java.lang.Character) {
ps.setString(i + 1, value.toString());
} else if (value instanceof java.lang.Float) {
ps.setFloat(i + 1, (Float) value);
} else if (value instanceof java.lang.Boolean) {
ps.setBoolean(i + 1, (Boolean) value);
} else if (value instanceof java.lang.Short) {
ps.setShort(i + 1, (Short) value);
} else {
ps.setObject(i + 1, value);
}
} else {
ps.setNull(i + 1, Types.NULL);
}
}
return ps;
}
}, keyHolder);
return (ID) (Integer) keyHolder.getKey().intValue();
}
@SuppressWarnings("unchecked")
protected ID addReturnId(Map<String, Object> map) {
if (map == null || map.size() == 0)
return null;
if (strategy.equals(GenerationType.IDENTITY)) {
map.remove(this.getPk());
}
StringBuilder sb = new StringBuilder("insert into ");
sb.append(this.getTableName());
List<String> columns = new ArrayList<String>();
List<Object> values = new ArrayList<Object>();
for (Entry<String, Object> e : map.entrySet()) {
columns.add(e.getKey());
values.add(e.getValue());
}
sb.append("(");
sb.append(StringUtils.join(columns, ','));
sb.append(") values(");
String[] paras = new String[values.size()];
Arrays.fill(paras, "?");
sb.append(StringUtils.join(paras, ','));
sb.append(")");
if (strategy.equals(GenerationType.IDENTITY)) {
ID id = this.addReturnId(sb.toString(), values);
return (ID) id;
} else if (strategy.equals(GenerationType.AUTO)) {
int count = this.add(sb.toString(), values);
if (count != 0) {
return (ID) map.get(this.getPk());
} else {
return null;
}
}
return null;
}
@Override
public int[] batchAdd(String sql, List<List<Object>> values) {
if (StringUtils.isEmpty(sql))
return new int[0];
if (values == null)
values = new ArrayList<List<Object>>();
if (log.isDebugEnabled()) {
log.debug("sql : " + sql + " values:" + values);
}
List<Object[]> batchArgs = new ArrayList<Object[]>();
for (List<Object> ol : values) {
batchArgs.add(ol.toArray());
}
return this.getJdbcTemplate().batchUpdate(sql, batchArgs);
}
@Override
public int update(String sql, List<Object> values) {
if (StringUtils.isEmpty(sql))
return 0;
if (values == null)
values = new ArrayList<Object>();
if (log.isDebugEnabled()) {
log.debug("sql : " + sql + " values:" + values);
}
return this.getJdbcTemplate().update(sql, values.toArray());
}
@Override
public int del(ID id) {
if (id == null)
return 0;
StringBuilder sb = new StringBuilder("delete from ");
sb.append(this.getTableName());
sb.append(" where ");
sb.append(this.getPk());
sb.append("=?");
List<Object> values = new ArrayList<Object>();
values.add(id);
return this.del(sb.toString(), values);
}
@Override
public int delByIds(List<ID> ids) {
if (ids == null || ids.isEmpty())
return 0;
StringBuilder sb = new StringBuilder("delete from ");
sb.append(this.getTableName());
sb.append(" where ");
sb.append(this.getPk());
sb.append(" in (");
Serializable[] ss = new Serializable[ids.size()];
Arrays.fill(ss, "?");
sb.append(StringUtils.join(ss, ','));
sb.append(")");
List<Object> values = new ArrayList<Object>();
values.addAll(ids);
return this.del(sb.toString(), values);
}
@Override
public int del(String sql, List<Object> values) {
if (log.isDebugEnabled()) {
log.debug("sql : " + sql + " values:" + values);
}
return this.getJdbcTemplate().update(sql, values.toArray());
}
@Override
public int getInt(String sql, List<Object> values) {
if (StringUtils.isEmpty(sql))
return 0;
if (values == null)
values = new ArrayList<Object>();
if (log.isDebugEnabled()) {
log.debug("sql : " + sql + " values:" + values);
}
return this.getJdbcTemplate().queryForInt(sql, values.toArray());
}
@Override
public long getLong(String sql, List<Object> values) {
if (StringUtils.isEmpty(sql))
return 0;
if (values == null)
values = new ArrayList<Object>();
if (log.isDebugEnabled()) {
log.debug("sql : " + sql + " values:" + values);
}
return this.getJdbcTemplate().queryForLong(sql, values.toArray());
}
@Override
public int getCount(String sql, List<Object> values) {
if (StringUtils.isEmpty(sql))
return 0;
if (values == null)
values = new ArrayList<Object>();
StringBuilder sb = new StringBuilder("select count(*) from ");
sb.append(this.getTableName());
sb.append(sql);
return this.getInt(sb.toString(), values);
}
@Override
public boolean isExit(List<String> keys, List<Object> values) {
StringBuffer sb = new StringBuffer();
String suffix1 = " =? ";
String suffix2 = " and ";
for(String s:keys){
sb.append(s);
sb.append(suffix1);
sb.append(suffix2);
}
String sql = " where "+ sb.toString().substring(0, sb.toString().lastIndexOf(suffix2));
int count = getCount(sql, values);
if(count > 0)
return true;
return false;
}
protected int[] batchAdd(List<Map<String, Object>> mapList) {
if (mapList == null || mapList.isEmpty())
return new int[0];
Map<String, Object> map = mapList.get(0);
if (map == null || map.size() == 0)
return new int[0];
if (strategy.equals(GenerationType.AUTO)) {
map.remove(this.getPk());
}
String[] columnNames = new String[map.size()];
columnNames = map.keySet().toArray(columnNames);
StringBuilder sb = new StringBuilder("insert into ");
sb.append(this.getTableName());
sb.append("(");
sb.append(StringUtils.join(columnNames, ','));
sb.append(") values(");
String[] paras = new String[columnNames.length];
Arrays.fill(paras, "?");
sb.append(StringUtils.join(paras, ','));
sb.append(")");
List<List<Object>> values = new ArrayList<List<Object>>();
for (Map<String, Object> m : mapList) {
if (m != null && !m.isEmpty()) {
List<Object> l = new ArrayList<Object>();
for (String str : columnNames) {
l.add(m.get(str));
}
values.add(l);
}
}
return this.batchAdd(sb.toString(), values);
}
protected int updateById(Map<String, Object> map) {
if (map == null || map.size() == 0)
return 0;
Serializable id = (Serializable) map.get(this.getPk());
if (id == null || "".equals(id))
return 0;
List<Object> values = new ArrayList<Object>();
StringBuilder sb = new StringBuilder("update ");
sb.append(this.getTableName());
sb.append(" set ");
map.remove(this.getPk());
for (Entry<String, Object> e : map.entrySet()) {
sb.append(e.getKey());
sb.append("=?, ");
values.add(e.getValue());
}
deleteLastStr(sb, ",");
sb.append(" where ");
sb.append(this.getPk());
sb.append("=?");
values.add(id);
map.put(this.getPk(), id);
return this.update(sb.toString(), values);
}
@Override
public PageBean<T> search(String sql, List<Object> values,
PageBean<T> pageBean) {
if (StringUtils.isEmpty(sql)) {
List<T> reList = new ArrayList<T>();
pageBean.setRowCount(0);
pageBean.setList(reList);
return pageBean;
}
if (values == null)
values = new ArrayList<Object>();
int startRow = pageBean.getStartRow();
int offset = pageBean.getPageSize();
StringBuilder sb = new StringBuilder(sql);
if (StringUtils.isNotEmpty(pageBean.getGroupby())) {
sb.append(" group by ");
sb.append(pageBean.getGroupby());
}
int count = this.getCount(sb.toString(), values);
pageBean.setRowCount(count);
if (!StringUtils.isEmpty(pageBean.getOrderBy())) {
sb.append(" order by ");
sb.append(pageBean.getOrderBy());
if (!StringUtils.isEmpty(pageBean.getOrderType())) {
sb.append(" ");
sb.append(pageBean.getOrderType());
}
}
sb.append(" limit ");
sb.append(startRow);
sb.append(",");
sb.append(offset);
pageBean.setList(this.search(sb.toString(), values));
return pageBean;
}
@Override
public T get(ID id) {
if (id == null)
return null;
StringBuilder sb = new StringBuilder("select * from ");
sb.append(this.getTableName());
sb.append(" where ");
sb.append(this.getPk());
sb.append("=?");
List<Object> values = new ArrayList<Object>();
values.add(id);
List<T> list = this.search(sb.toString(), values);
if (list == null || list.size() == 0)
return null;
else
return list.get(0);
}
@Override
public T save(T t) {
if (t == null) {
throw new DaoException("模型类内容为空!");
}
Map<String, Object> map = null;
try {
map = BeanUtilsBean.getInstance().describe(t);
} catch (Exception e) {
throw new DaoException("模型类解析异常!", e);
}
for (String proterty : transientPropertys) {
map.remove(proterty);
}
ID id = this.addReturnId(map);
if (strategy.equals(GenerationType.IDENTITY)) {
try {
BeanUtils.setProperty(t, pk, id);
} catch (Exception e) {
throw new DaoException("模型类解析异常!", e);
}
}
return t;
}
@Override
public List<T> getByIds(List<ID> ids) {
List<T> list = null;
if (ids != null && !ids.isEmpty()) {
StringBuilder sb = new StringBuilder("select * from ");
sb.append(this.getTableName());
sb.append(" where ");
sb.append(this.getPk());
sb.append(" in (");
Serializable[] ss = new Serializable[ids.size()];
Arrays.fill(ss, "?");
sb.append(StringUtils.join(ss, ','));
sb.append(")");
List<Object> values = new ArrayList<Object>();
values.addAll(ids);
list = this.search(sb.toString(), values);
} else {
list = new ArrayList<T>();
}
return list;
}
@Override
public T update(T t) {
if (t == null) {
throw new DaoException("模型类内容为空!");
}
Map<String, Object> map = null;
try {
map = BeanUtilsBean.getInstance().describe(t);
for (String proterty : transientPropertys) {
map.remove(proterty);
}
} catch (Exception e) {
throw new DaoException("模型类解析异常!", e);
}
int count = this.updateById(map);
if (count == 0) {
throw new DaoException("更新对象失败" + t);
}
return t;
}
@Override
public int[] batchSave(List<T> list) {
if (list == null) {
throw new DaoException("模型类内容为空!");
}
List<Map<String, Object>> mapList = new ArrayList<Map<String, Object>>();
for (T t : list) {
try {
Map<String, Object> map = BeanUtilsBean.getInstance().describe(
t);
for (String proterty : transientPropertys) {
map.remove(proterty);
}
mapList.add(map);
} catch (Exception e) {
throw new DaoException("模型类解析异常!", e);
}
}
return this.batchAdd(mapList);
}
@Override
public <E> List<E> search(String sql, List<Object> values, Class<E> e) {
if (StringUtils.isEmpty(sql))
return new ArrayList<E>();
if (values == null)
values = new ArrayList<Object>();
logger.info("sql : " + sql + " values:" + values);
return this.getJdbcTemplate().query(sql, values.toArray(),
new BeanPropertyRowMapper<E>(e));
}
@Override
public <E> PageBean<E> search(String sql, List<Object> values,
PageBean<E> pageBean, Class<E> e) {
if (StringUtils.isEmpty(sql)) {
List<E> reList = new ArrayList<E>();
pageBean.setRowCount(0);
pageBean.setList(reList);
return pageBean;
}
if (values == null)
values = new ArrayList<Object>();
int startRow = pageBean.getStartRow();
int offset = pageBean.getPageSize();
StringBuilder sb = new StringBuilder(sql);
if (StringUtils.isNotEmpty(pageBean.getGroupby())) {
sb.append(" group by ");
sb.append(pageBean.getGroupby());
}
int count = this.getCount(sb.toString(), values);
pageBean.setRowCount(count);
if (!StringUtils.isEmpty(pageBean.getOrderBy())) {
sb.append(" order by ");
sb.append(pageBean.getOrderBy());
if (!StringUtils.isEmpty(pageBean.getOrderType())) {
sb.append(" ");
sb.append(pageBean.getOrderType());
}
}
sb.append(" limit ");
sb.append(startRow);
sb.append(",");
sb.append(offset);
pageBean.setList(this.search(sb.toString(), values, e));
return pageBean;
}
@Override
public List<T> search(T t) {
if (t == null)
return new ArrayList<T>();
Map<String, Object> map;
try {
map = BeanUtilsBean.getInstance().describe(t);
for (String proterty : transientPropertys) {
map.remove(proterty);
}
} catch (Exception e) {
throw new DaoException("模型类解析异常!", e);
}
return this.search(map);
}
@Override
public T searchOne(T t) {
if (t == null)
return null;
Map<String, Object> map;
try {
map = BeanUtilsBean.getInstance().describe(t);
map.remove("class");
for (String proterty : transientPropertys) {
map.remove(proterty);
}
} catch (Exception e) {
throw new DaoException("模型类解析异常!", e);
}
return this.searchOne(map);
}
@Override
public List<Map<String, Object>> searchForMap(String sql,
List<Object> values) {
if (StringUtils.isEmpty(sql))
return new ArrayList<Map<String, Object>>();
if (values == null)
values = new ArrayList<Object>();
if (log.isDebugEnabled()) {
log.debug("sql : " + sql + " values:" + values);
}
return this.getJdbcTemplate().queryForList(sql, values.toArray());
}
@Override
public PageBean<Map<String, Object>> searchForMap(String sql,
List<Object> values, PageBean<Map<String, Object>> pageBean) {
if (StringUtils.isEmpty(sql)) {
List<Map<String, Object>> reList = new ArrayList<Map<String, Object>>();
pageBean.setRowCount(0);
pageBean.setList(reList);
return pageBean;
}
if (values == null)
values = new ArrayList<Object>();
int startRow = pageBean.getStartRow();
int offset = pageBean.getPageSize();
StringBuilder sb = new StringBuilder(sql);
if (StringUtils.isNotEmpty(pageBean.getGroupby())) {
sb.append(" group by ");
sb.append(pageBean.getGroupby());
}
int count = this.getCount(sb.toString(), values);
pageBean.setRowCount(count);
if (!StringUtils.isEmpty(pageBean.getOrderBy())) {
sb.append(" order by ");
sb.append(pageBean.getOrderBy());
if (!StringUtils.isEmpty(pageBean.getOrderType())) {
sb.append(" ");
sb.append(pageBean.getOrderType());
}
}
sb.append(" limit ");
sb.append(startRow);
sb.append(",");
sb.append(offset);
pageBean.setList(this.searchForMap(sb.toString(), values));
return pageBean;
}
private void deleteLastStr(StringBuilder sb, String str) {
int index = sb.lastIndexOf(str);
if (index != -1) {
sb.delete(index, index + str.length());
}
}
}