EasyDBO上對(duì)象關(guān)聯(lián)還是存在很大問(wèn)題。
其中一個(gè),添加對(duì)象時(shí),沒(méi)能將被關(guān)聯(lián)對(duì)象的主鍵(由數(shù)據(jù)庫(kù)生成)插入到關(guān)聯(lián)對(duì)象的外鍵上。
注:
(1) EasyDBO的一對(duì)一關(guān)聯(lián)中,外鍵在關(guān)聯(lián)對(duì)象方。
Class A{
.....
B b ;
}
Class B{
}
對(duì)應(yīng)于實(shí)體A的數(shù)據(jù)庫(kù)表有外鍵,如 fk_b
(2) EasyDBO的一對(duì)多關(guān)聯(lián)中,外鍵在被關(guān)聯(lián)對(duì)象方(多方)。
Class A{
.....
List<B> bList ;
}
Class B{
A a;
}
對(duì)應(yīng)于實(shí)體B的數(shù)據(jù)庫(kù)表有外鍵,如 fk_a
在解決這個(gè)問(wèn)題中,對(duì)源碼做一些的修改:
1、首先解決如果是數(shù)據(jù)庫(kù)生成的主鍵(如auto_increment類型),在DatabaseDAO添加getGeneratedKey()方法。
public Serializable getGeneratedKey()

{

if(prepared==null)
{
return null;
}
Serializable ret =null;
ResultSet rs = null;
try

{
rs = prepared.getGeneratedKeys();
if(rs.next())

{
ret = (Serializable)rs.getObject(1);
logger.info("get the GeneratedKey:" + ret);
}
}
catch(SQLException e)

{
e.printStackTrace();
}
finally

{
if(rs != null)
try

{
rs.close();
}
catch(SQLException e)

{
e.printStackTrace();
}
}
return ret;
}
2、在EasyJDBEngine中添加generatedKey字段和getter方法。
private Serializable generatedKey;
public Serializable getGeneratedKey()

{
return generatedKey;
}
在EasyJDBEngine的public boolean add(DBObject obj)方法中try的括號(hào)末尾添加
generatedKey = dba.getGeneratedKey();
3、EasyJDB中添加以下方法:

private Object setObjectGenIdValue(Object obj)
{
BeanWrapper wrapper = new BeanWrapper(obj);
DBTable dbTable = findTable(obj.getClass());
String idFieldName = dbTable.getPoperty(dbTable.getId());

if(wrapper.getPropertyValue(idFieldName)==null && StringUtils.isNotEmpty(dbEngine.getGeneratedKey()))
{
Object javaPropertyValue = wrapper.convertIfNecessary(String.valueOf(dbEngine.getGeneratedKey()),
dbTable.getType(idFieldName));
wrapper.setPropertyValue(idFieldName, javaPropertyValue);
System.out.println("setting id
.");
return javaPropertyValue;
}
return null;
}


private Object getObjectIdValue(Object obj)
{
BeanWrapper wrapper = new BeanWrapper(obj);
DBTable dbTable = findTable(obj.getClass());
String idFieldName = dbTable.getPoperty(dbTable.getId());

if(StringUtils.isNotEmpty(wrapper.getPropertyValue(idFieldName)))
{
return wrapper.getPropertyValue(idFieldName);
}
return null;
}


private void setClassFieldValue(Object target,ClassField classField,Object value)
{
BeanWrapper wi=new BeanWrapper(target);
DBTable dbTable = findTable(target.getClass());
wi.setPropertyValue(dbTable.getPoperty(classField.getColumn()),value);
}
EasyJDB中的public boolean add(Object obj)方法改為:
public boolean add(Object obj)

{
logger.debug("把對(duì)象obj保存到數(shù)據(jù)庫(kù)中");
boolean ret = dbEngine.add(obj2dbo(obj));
setObjectGenIdValue(obj);///如果是新添加的記錄,且主鍵為數(shù)據(jù)庫(kù)生成,那么將主鍵值返回賦給對(duì)象
if(ret)ret = ret & addRelativeObject(obj);
return ret;
}
EasyJDB中的private boolean addRelativeObject(Object obj)方法改為:
private boolean addRelativeObject(Object obj)

{
boolean ret = true;
DBTable table = findTable(obj.getClass());
if(table != null)

{
BeanWrapper wrapper = new BeanWrapper(obj);
java.util.Iterator it = table.getClassField().entrySet().iterator();
while(it.hasNext())

{
// 嘗試處理其它字段
Map.Entry en = (Map.Entry)it.next();
String propertyName = (String)en.getKey();
ClassField classField = (ClassField)en.getValue();
// System.out.println(classField.getClass()+":"+propertyName);
if(classField instanceof ManyToManyField && wrapper.isReadableProperty(propertyName))

{
// 處理多對(duì)多
Object value = wrapper.getPropertyValue(propertyName);
// System.out.println("值內(nèi)容"+value.getClass());
if(value != null && value instanceof Collection)

{
java.util.Iterator es = ((Collection)value).iterator();
while(es.hasNext())

{
Object element = es.next();
ret = ret & this.saveOrUpdate(element);
// 保存關(guān)聯(lián)的第三方表
ManyToManyField field = (ManyToManyField)classField;

/**//*
* DBTable table2=findTable(element.getClass());
* if(table2!=null) { ManyToManyField field2=null;
* java.util.Iterator
* inf2=table2.getClassField().values().iterator();
* while(inf2.hasNext()) { ClassField
* ff=(ClassField)inf2.next();
* if(ff.getTableName().equals(field.getTableName()) &&
* ff.getType()==obj.getClass()) {
* field2=(ManyToManyField)ff; } }
*/
String sql = "insert into " + field.getTableName() + "(" + classField.getColumn() + ","
+ field.getTagColumn() + ") values(?,?)";
java.util.Collection paras = new java.util.ArrayList();
paras.add(wrapper.getPropertyValue(classField.getKey()));
BeanWrapper wrapper2 = new BeanWrapper(element);
paras.add(wrapper2.getPropertyValue(field.getTagKey()));
try

{
this.execute(sql, paras);
}
catch(Exception e)

{
logger.error("插入多對(duì)多關(guān)系時(shí)出錯(cuò)!");
e.printStackTrace();
}
// }
}
}
}
else if((classField instanceof ManyToOneField) && wrapper.isReadableProperty(propertyName))

{
// 處理一對(duì)多
Object value = wrapper.getPropertyValue(propertyName);
if(value != null && value instanceof Collection)

{
java.util.Iterator es = ((Collection)value).iterator();
while(es.hasNext())

{
Object item = es.next();
setClassFieldValue(item,classField,obj);//設(shè)置關(guān)聯(lián)值
ret = ret & this.saveOrUpdate(item);
}
}
}
else if((classField instanceof OneToOneField) && wrapper.isReadableProperty(propertyName))

{
// 處理一對(duì)一
Object value = wrapper.getPropertyValue(propertyName);
if(value != null)

{
ret = ret & this.saveOrUpdate(value);
if(StringUtils.isNotEmpty(getObjectIdValue(value)))

{
setClassFieldValue(obj, classField, value);//設(shè)置關(guān)聯(lián)值
update(obj);//更新一下數(shù)據(jù),將關(guān)聯(lián)的對(duì)象主鍵作為外鍵
}
}
}
}
}
return ret;
}
EasyJDB中的public boolean update(Object obj)方法改為:
public boolean update(Object obj)

{
logger.info("更新持久層中的數(shù)據(jù)表對(duì)象");
boolean ret = dbEngine.update(obj2dbo(obj));
// ret = ret & this.addRelativeObject(obj);//這句很容易會(huì)導(dǎo)致死循環(huán),先不要了
return ret;
}
EasyJDB中的public boolean saveOrUpdate(Object obj)方法改為:
public boolean saveOrUpdate(Object obj)

{
// logger.info("把對(duì)象持久化到數(shù)據(jù)庫(kù)中,先償試添加,若無(wú)法保存則執(zhí)行修改操作");
boolean ret = false;
try

{
Object id = getObjectIdValue(obj);
if(id == null)

{
ret = add(obj);
}

else

{
if(get(obj.getClass(), id) != null)
ret = update(obj);
else
ret = add(obj);
}
}
catch(Exception e)

{
//這里的也先不要的,很容易導(dǎo)致死循環(huán)
// 出錯(cuò),進(jìn)一步嘗試使用原始的方法進(jìn)行更改
// if(add(obj))
// {
// return true;
// }
// return update(obj);
e.printStackTrace();
}
return ret;
}
解釋一下:
這里處理的不包括多對(duì)多的關(guān)系,很少用到,暫時(shí)不管。
解決的思路是,如果是自增(數(shù)據(jù)庫(kù)生成的id),那么獲取這個(gè)id,并回賦給對(duì)象,對(duì)象有了主鍵值(每個(gè)這樣的對(duì)象都回賦主鍵值),關(guān)聯(lián)就有了導(dǎo)航。
在一對(duì)一關(guān)系處理中,因?yàn)槭窍炔迦腙P(guān)聯(lián)對(duì)象數(shù)據(jù),然后在插入被關(guān)聯(lián)對(duì)象數(shù)據(jù)。但是關(guān)聯(lián)對(duì)象需要知道被關(guān)聯(lián)的主鍵值,而被關(guān)聯(lián)的主鍵值是在最后插入數(shù)據(jù)后回賦的,所以,采取從新將對(duì)象關(guān)聯(lián),并更新數(shù)據(jù)。
setClassFieldValue(obj, classField, value);//設(shè)置關(guān)聯(lián)值
update(obj);//更新一下數(shù)據(jù),將關(guān)聯(lián)的對(duì)象主鍵作為外鍵
在處理一對(duì)多(也即多對(duì)一)關(guān)系中,如一開(kāi)就提到的“EasyDBO的一對(duì)多關(guān)聯(lián)中,外鍵在被關(guān)聯(lián)對(duì)象方(多方)”,數(shù)據(jù)插入順序同一對(duì)一的一樣,先關(guān)聯(lián)對(duì)象,后被關(guān)聯(lián)對(duì)象,所以,在這里只需要在被關(guān)聯(lián)對(duì)象插入前更新關(guān)聯(lián)就可以了
setClassFieldValue(item,classField,obj);//設(shè)置關(guān)聯(lián)值
比較明顯,將一對(duì)多的關(guān)系轉(zhuǎn)換成了多個(gè)一對(duì)一了?;蛟S這樣不是很好,但是,在原有的架構(gòu)上,比較難做更大修改。
EasyDBO有一些主鍵生成器的,不知對(duì)對(duì)象關(guān)聯(lián)上主鍵的處理上有沒(méi)有獨(dú)特的解決方法,待探索...
淺見(jiàn),不當(dāng)?shù)牡胤綒g迎指正~~~~~~~~
posted on 2007-07-02 18:15
三告習(xí)習(xí) 閱讀(1205)
評(píng)論(3) 編輯 收藏 所屬分類:
easyJF-projects