我基于 Thin 完成一个实现, Thin 是一种基于 key-value 的持久层框架,简单易用,体现持久本质。在此不再详述。大家可以参考源代码: http://sourceforge.net/projects/thinery/
public class ThinObject extends IObject {
protected static Logger log = Logger.getLogger(IObject.class);
static {
/**
* 这里建立了一种约定,一种对象的属性名与数据库中表字段名相互转换的约定。
*/
KVUtils.mappingRule = new AnnotationMappingRule();
}
/**
* 在配置文件中加载自定义的SQL,存放在此处以供该类的方法使用
*
*/
static Properties sqls = new Properties();
transient protected BeanTable beanTable;
/**
* 把该类的所有属性,全部转化成key-value用于存储
*
* @return
* @throws Exception
*/
protected Map<String, Object> toKeyValue() throws Exception {
return KVUtils.toKeyValue(this);
}
protected Field hasPrimary() {
Field[] fields = getClass().getDeclaredFields();
for (Field field : fields) {
Primary pry = field.getAnnotation(Primary.class);
if (pry != null) {
return field;
}
}
return null;
}
/**
* 该设计的持久方式采用的是'thin',<a
* href="http://sourceforge.net/projects/thinery/">thin</a>
* 是基于key-value的持久层框架,简单,易用,透析持久本质; 默认采用约定优先,注解在后的映射方式,还支持定义映射。
*
* @return
* @throws SQLException
*/
protected BeanTable getBeanTable() throws SQLException {
if (beanTable == null) {
BeanTableName btn = this.getClass().getAnnotation(
BeanTableName.class);
String tableName = btn.name();
String schema = btn.schema();
if ("".endsWith(schema)) {
beanTable = ThinContext.getThinContext()
.getBeanTable(tableName);
} else {
beanTable = ThinContext.getThinContext(schema).getBeanTable(
tableName);
}
}
return beanTable;
}
public ThinObject() {
if (!inited) {
try {
initSQLProperties();
} catch (Exception e) {
e.printStackTrace();
}
inited = true;
}
}
private void initSQLProperties() throws IOException {
InputStream inStream = this.getClass().getClassLoader()
.getResourceAsStream(this.getThisName() + "_sql.properties");
if (inStream != null) {
sqls.load(inStream);
}
}
@SuppressWarnings("unchecked")
protected List toBeans(List<Map<String, Object>> keyvalues)
throws Exception {
return KVUtils.toBeans(keyvalues, this.getClass());
}
/**
* 把对象自身持久的数据库的方法。子类可以根据类的情况,重写该方法。 如该类是一对一,一对多的,想把关联对象一起存储,就需要重写该方法
*
* @throws RuntimeException
*/
public void remember() throws RuntimeException {
try {
this.getBeanTable().addOrUpdate(toKeyValue());
this.setChanged();
this.notifyObservers();
} catch (Exception e) {
log.error("记忆出现异常!", e);
throw new RuntimeException(e);
}
}
/**
* 删除此对象对应的数据库记录。 恰如我们忘记一件事物
*/
public void forget() {
try {
this.getBeanTable().delete(toKeyValue());
this.setChanged();
this.notifyObservers();
} catch (Exception e) {
log.error("删除记录出现异常", e);
throw new RuntimeException(e);
}
}
public void updateMemory(String... updateFields) {
try {
Map<String, Object> keyvalues = new HashMap<String, Object>();
for (String name : updateFields) {
KVUtils.mappingRule.setDBColumn(this, this.getClass()
.getDeclaredField(name), keyvalues);
}
Field primaryField = hasPrimary();
if (primaryField != null
&& !keyvalues.containsKey(primaryField.getName())) {
KVUtils.mappingRule.setDBColumn(this, primaryField, keyvalues);
}
this.getBeanTable().update(keyvalues);
this.setChanged();
this.notifyObservers();
} catch (Exception e) {
log.error("更新存储出现异常", e);
throw new RuntimeException(e);
}
}
@SuppressWarnings("unchecked")
public List<Object> associate(Object... params) {
try {
Criterion[] criterions=toCriterion(params);
return this.toBeans(this.getBeanTable().get(criterions));
} catch (Exception e) {
log.error("查询记录出现异常", e);
throw new RuntimeException(e);
}
}
private Criterion[] toCriterion(Object... params) {
Criterion[] criterions = new Criterion[params.length];
for(int i=0;i<params.length;i++){
criterions[i] = (Criterion)params[i];
}
return criterions;
}
public void obtainMe() {
try {
Field field = this.hasPrimary();
Object value = PropertyUtils.getProperty(this, field.getName());
List<Map<String, Object>> keyvalues = this.getBeanTable().get(SQLCriterion.get(field.getName(), value));
if(!keyvalues.isEmpty()){
KVUtils.toBean(keyvalues.get(0), this);
}
} catch (Exception e) {
log.error("查询记录出现异常", e);
throw new RuntimeException(e);
}
}
}