package my.db;
import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import my.cache.CacheManager;
import my.util.Inflector;
import net.oschina.beans.User;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.dbutils.DbUtils;
* 数据库对象的基类
* @author Winter Lau
* @date 2010-1-22 上午11:33:56
*/
public class POJO implements Serializable {
protected final static transient char OBJ_COUNT_CACHE_KEY = '#';
private long ___key_id;
public long getId() { return ___key_id; }
public void setId(long id) { this.___key_id = id; }
private String __this_table_name;
public static void evictCache(String cache, Serializable key) {
CacheManager.evict(cache, key);
}
public static void setCache(String cache, Serializable key, Serializable value) {
CacheManager.set(cache, key, value);
public static Object getCache(String cache, Serializable key) {
return CacheManager.get(cache, key);
* 分页列出所有对象
* @param page
* @param size
* @return
public List extends POJO> List(int page, int size) {
String sql = "SELECT * FROM " + TableName() + " ORDER BY id DESC";
return QueryHelper.query_slice(getClass(), sql, page, size);
public List extends POJO> Filter(String filter, int page, int size) {
String sql = "SELECT * FROM " + TableName() + " WHERE " + filter + " ORDER BY id DESC";
return QueryHelper.query_slice(getClass(), sql, page, size);
* 统计此对象的总记录数
* @return
*/
public int TotalCount(String filter) {
return (int)QueryHelper.stat("SELECT COUNT(*) FROM " + TableName() + " WHERE " + filter);
* 返回默认的对象对应的表名
* @return
protected String TableName() {
if(__this_table_name == null)
__this_table_name = "osc_" + Inflector.getInstance().tableize(getClass());
return __this_table_name;
* 返回对象对应的缓存区域名
* @return
public String CacheRegion() { return this.getClass().getSimpleName(); }
* 是否根据ID缓存对象,此方法对Get(long id)有效
* @return
protected boolean IsObjectCachedByID() { return false; }
* 插入对象到数据库表中
* @return
*/
public long Save() {
if(getId() > 0)
_InsertObject(this);
else
setId(_InsertObject(this));
if(this.IsObjectCachedByID())
CacheManager.evict(CacheRegion(), OBJ_COUNT_CACHE_KEY);
return getId();
* 根据id主键删除对象
* @return
*/
public boolean Delete() {
boolean dr = Evict(QueryHelper.update("DELETE FROM " + TableName() + " WHERE id=?", getId()) == 1);
if(dr)
CacheManager.evict(CacheRegion(), OBJ_COUNT_CACHE_KEY);
return dr;
* 根据条件决定是否清除对象缓存
* @param er
* @return
*/
public boolean Evict(boolean er) {
if(er && IsObjectCachedByID())
CacheManager.evict(CacheRegion(), getId());
return er;
* 清除指定主键的对象缓存
* @param obj_id
*/
protected void Evict(long obj_id) {
CacheManager.evict(CacheRegion(), obj_id);
}
public POJO Get(java.math.BigInteger id) {
if(id == null) return null;
return Get(id.longValue());
}
/**
* 根据主键读取对象详细资料,根据预设方法自动判别是否需要缓存
* @param id
* @return
*/
@SuppressWarnings("unchecked")
public T Get(long id) {
if(id <= 0) return null;
String sql = "SELECT * FROM " + TableName() + " WHERE id=?";
boolean cached = IsObjectCachedByID();
return (T)QueryHelper.read_cache(getClass(), cached?CacheRegion():null, id, sql, id);
public List extends POJO> BatchGet(List ids) {
if(ids==null || ids.size()==0)
return null;
StringBuilder sql = new StringBuilder("SELECT * FROM " + TableName() + " WHERE id IN (");
for(int i=1;i<=ids.size();i++) {
sql.append('?');
if(i < ids.size())
sql.append(',');
sql.append(')');
List extends POJO> beans = QueryHelper.query(getClass(), sql.toString(), ids.toArray(new Object[ids.size()]));
if(IsObjectCachedByID()){
for(Object bean : beans){
CacheManager.set(CacheRegion(), ((POJO)bean).getId(), (Serializable)bean);
return beans;
* 统计此对象的总记录数
* @return
*/http://www.huiyi8.com/jiaoben/
public int TotalCount() {javascript特效
if(this.IsObjectCachedByID())
return (int)QueryHelper.stat_cache(CacheRegion(),OBJ_COUNT_CACHE_KEY, "SELECT COUNT(*) FROM " + TableName());
return (int)QueryHelper.stat("SELECT COUNT(*) FROM " + TableName());
* 批量加载项目
* @param pids
* @return
*/
@SuppressWarnings("rawtypes")
public List LoadList(List p_pids) {
if(p_pids==null)
return null;
final List pids = new ArrayList(p_pids.size());
for(Number obj : p_pids){
pids.add(obj.longValue());
}
String cache = this.CacheRegion();
List prjs = new ArrayList(pids.size()){{for(int i=0;i
List no_cache_ids = new ArrayList();
for(int i=0;i
long pid = pids.get(i);
POJO obj = (POJO)CacheManager.get(cache, pid);
if(obj != null)
prjs.set(i, obj);
else{
no_cache_ids.add(pid);
if(no_cache_ids.size()>0){
List extends POJO> no_cache_prjs = BatchGet(no_cache_ids);
if(no_cache_prjs != null)
for(POJO obj : no_cache_prjs){
prjs.set(pids.indexOf(obj.getId()), obj);
no_cache_ids = null;
//Check Users
if(prjs!=null && IsAutoLoadUser()){
List no_cache_userids = new ArrayList();
String user_cache = User.INSTANCE.CacheRegion();
for(POJO pojo : prjs){
if(pojo == null)
continue;
long userid = pojo.GetAutoLoadUser();
if(userid > 0 && !no_cache_userids.contains(userid)){
POJO user = (POJO)CacheManager.get(user_cache, userid);
if(user == null){
no_cache_userids.add(userid);
if(no_cache_userids.size()>0)
User.INSTANCE.BatchGet(no_cache_userids);
no_cache_userids = null;
return prjs;
protected boolean IsAutoLoadUser() { return false; }
protected long GetAutoLoadUser() { return 0L; }
* 插入对象
* @param obj
* @return 返回插入对象的主键
*/
private static long _InsertObject(POJO obj) {
Map pojo_bean = obj.ListInsertableFields();
String[] fields = pojo_bean.keySet().toArray(new String[pojo_bean.size()]);
StringBuilder sql = new StringBuilder("INSERT INTO ") ;
sql.append(obj.TableName());
sql.append('(');
for(int i=0;i
if(i > 0) sql.append(',');
sql.append(fields[i]);
}
sql.append(") VALUES(");
for(int i=0;i
if(i > 0) sql.append(',');
sql.append('?');
}
sql.append(')');
PreparedStatement ps = null;
ResultSet rs = null;
try{
ps = QueryHelper.getConnection().prepareStatement(sql.toString(), PreparedStatement.RETURN_GENERATED_KEYS);
for(int i=0;i
ps.setObject(i+1, pojo_bean.get(fields[i]));
ps.executeUpdate();
rs = ps.getGeneratedKeys();
return rs.next()?rs.getLong(1):-1;
}catch(SQLException e){
throw new DBException(e);
}finally{
DbUtils.closeQuietly(rs);
DbUtils.closeQuietly(ps);
sql = null;
fields = null;
pojo_bean = null;
* 列出要插入到数据库的域集合,子类可以覆盖此方法
* @return
*/
@SuppressWarnings("unchecked")
protected Map ListInsertableFields() {
try {
Map props = BeanUtils.describe(this);
if(getId() <= 0)
props.remove("id");
props.remove("class");
return props ;
} catch (Exception e) {
throw new RuntimeException("Exception when Fetching fields of " + this);
@Override
public boolean equals(Object obj) {
if (obj == null) return false;
if (obj == this) return true;
//不同的子类尽管ID是相同也是不相等的
if(!getClass().equals(obj.getClass()))
return false;
POJO wb = (POJO) obj;
return wb.getId() == getId();
}