使用XML作為持久層解決方案的,它的基本功能要有:
1.對象的CRUD功能(本例中基本對象是Member類).
2.保證線程安全,對桌面程序和Web程序都一樣適用.
3.有緩存,在存儲介質即XML文件突然丟失的情況下還能有效工作.
本例采用了MemberService和MemberPersistence兩個類來協作完成這些功能.
MemberService是業務層和持久層之間的橋梁,用於對Member對象的CRUD操作,內置一個hashtable來緩存Member對象,即使文件突然丟失,緩存中的數據也不會被影響.它內置一個MemberPersistence成員來完成與持久介質的交互.
實現添加,刪除,更新的三個函數add(),delete(),update()都用lockObj實現了同步,這樣就無需擔心線程安全問題.其它函數對members成員沒有修改,故不需要實現同步.
try{memberPersistence.add(member);
members.put(member.getId(), member);
return true;
}
catch(XMLFileWriteException ex){
System.out.println("Member:" + member.getId() + " add error!");
return false;
}
當MemberPersistence添加對象成功後,這個對象才會被添加到members中,這樣保證了緩存和實際數據的同步;如果顛倒一下順序,那末MemberPersistence添加對象不成功時,出現XMLFileWriteException異常,這是還需要在catch中刪除剛才添加的對象,這樣做人為加大了程序的復雜度,不如上面的做法簡單高效.
關於查詢函數的做法不明白的請見 http://www.blogJava.Net/sitinspring/archive/2007/06/05/122119.Html 中形式三.
下面是MemberService類的全部代碼:
package com.import Java.util.ArrayList;
import Java.util.Collections;
import Java.util.Hashtable;
import Java.util.Iterator;
import Java.util.List;
import com.sitinpsring.domain.Member;
import com.sitinpsring.domain.MemberFilter;
import com.sitinpsring.exception.XMLFileReadException;
import com.sitinpsring.exception.XMLFileWriteException;
import com.sitinpsring.persistence.MemberPersistence;
public class MemberService {
private static Hashtable
members; private static MemberPersistence memberPersistence;
private static final Object lockObj = new Object();
static {
try {
memberPersistence = new MemberPersistence("member.XML");
members = memberPersistence.loadMemberFromFile();
} catch (XMLFileReadException ex) {
System.out.println("Can’t read the file:member.XML");
}catch (XMLFileWriteException ex) {
System.out.println("Can’t write to the file:member.XML");
}
}
public MemberService() {
}
public boolean hasMember(String id) {
return members.containsKey(id);
}
public boolean hasMember(Member member) {
return hasMember(member.getId());
}
public boolean add(Member member) {
if (hasMember(member)) {
System.out.println("Member:" + member.getId() + " has been exist!");
return false;
} else {
synchronized (lockObj) {
try{
memberPersistence.add(member);
members.put(member.getId(), member);
return true;
}
catch(XMLFileWriteException ex){
System.out.println("Member:" + member.getId() + " add error!");
return false;
}
}
}
}
public boolean update(Member member) {
if (hasMember(member)) {
synchronized (lockObj) {
try{
memberPersistence.update(member);
Member oldMember = members.get(member.getId());
oldMember.setName(member.getName());
oldMember.setAge(member.getAge());
return true;
}
catch(XMLFileWriteException ex){
System.out.println("Member:" + member.getId() + " upate error!");
return false;
}
}
} else {
System.out.println("Member:" + member.getId()
+ " can’t been found!");
return false;
}
}
public boolean saveOrUpdate(Member member) {
if (hasMember(member)) {
return update(member);
} else {
return add(member);
}
}
public boolean delete(Member member) {
if (hasMember(member)) {
synchronized (lockObj) {
try{
memberPersistence.delete(member.getId());
members.remove(member.getId());
return true;
}catch(XMLFileWriteException ex){
System.out.println("Member:" + member.getId() + " delete error!");
return false;
}
}
} else {
System.out.println("Member:" + member.getId()
+ " can’t been found!");
return false;
}
}
@SuppressWarnings("unchecked")
public List
search(MemberFilter memberFilter) { ArrayList
retval = new ArrayList (); for (Iterator it = members.keySet().iterator(); it.hasNext();) {
String key = (String) it.next();
Member member = members.get(key);
if (memberFilter.accept(member)) {
retval.add(member);
}
}
Collections.sort(retval);
return retval;
}
public List
getAll() { MemberFilter filter = new MemberFilter() {
public boolean accept(Member member) {
return true;
}
};
return search(filter);
}
public Member getMemberById(String id) {
for (Iterator it = members.keySet().iterator(); it.hasNext();) {
String key = (String) it.next();
Member member = members.get(key);
if (member.getId().equals(id)) {
return member;
}
}
return null;
}
}
MemberPersistence類是與XML文件打交道的類,通過它,數據才能真正存入持久介質-XML文件.它的函數都很好理解.這些函數工作時實際只會引發兩種異常--讀XML文件異常(一般由多個根節點導致)和寫XML文件異常,會觸發這些異常的函數都應該對他們進行捕獲和拋出處理.
package com.sitinpsring.persistence;import Java.io.File;
import Java.io.FileWriter;
import Java.util.Hashtable;
import Java.util.Iterator;
import Java.util.List;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import com.sitinpsring.domain.Member;
import com.sitinpsring.exception.XMLFileReadException;
import com.sitinpsring.exception.XMLFileWriteException;
public class MemberPersistence {
private String XMLFilePos;
private Document document;
public MemberPersistence(String XMLFilePos)
throws XmlFileReadException,XMLFileWriteException{
this.xmlFilePos = XMLFilePos;
if (isFileExist(this.XMLFilePos) == false) {
// Create document when file not exist
createDocument();
return;
} else {
// Get Docunent when file exist
SAXReader reader = new SAXReader();
try {
document = reader.read(new File(this.XMLFilePos));
} catch (Exception ex) {
throw new XMLFileReadException(ex.getMessage());
}
}
}
private void createDocument() throws XMLFileWriteException{
String text = "
"; try {
document = DocumentHelper.parseText(text);
writeDocumentToFile();
} catch (XMLFileWriteException ex) {
throw ex;
}catch (Exception ex) {
ex.printStackTrace();
}
}
private void writeDocumentToFile() throws XMLFileWriteException{
try {
XMLWriter writer = new XMLWriter(new FileWriter(this.XMLFilePos));
writer.write(document);
writer.close();
} catch (Exception ex) {
throw new XMLFileWriteException(ex.getMessage());
}
}
public Hashtable
loadMemberFromFile() { Hashtable
retval=new Hashtable (); List nodes = document.getRootElement().elements("member");
for (Iterator it = nodes.iterator(); it.hasNext();) {
Element elm = (Element) it.next();
Member member = new Member(elm.attributeValue("id"),elm.elementText("name"),
Integer.parseInt(elm.elementText("age")));
retval.put(member.getId(), member);
}
return retval;
}
public boolean add(Member member) throws XMLFileWriteException{
try {
Element rootElm = document.getRootElement();
Element newMemberElm = rootElm.addElement("member");
newMemberElm.addAttribute("id", member.getId());
Element nameElm=newMemberElm.addElement("name");
nameElm.setText(member.getName());
Element ageElm=newMemberElm.addElement("age");
ageElm.setText(String.valueOf(member.getAge()));
writeDocumentToFile();
return true;
} catch (XMLFileWriteException ex) {
throw ex;
}
}
public boolean update(Member member) throws XMLFileWriteException{
try {
Element rootElm = document.getRootElement();
List nodes = rootElm.elements("member");
for (Iterator it = nodes.iterator(); it.hasNext();) {
Element elm = (Element) it.next();
if(elm.attributeValue("id").equals(member.getId())){
elm.element("name").setText(member.getName());
elm.element("age").setText(String.valueOf(member.getAge()));
break;
}
}
writeDocumentToFile();
return false;
} catch (XMLFileWriteException ex) {
throw ex;
}
}
public boolean delete(String id) throws XMLFileWriteException{
try {
Element rootElm = document.getRootElement();
List nodes = rootElm.elements("member");
for (Iterator it = nodes.iterator(); it.hasNext();) {
Element elm = (Element) it.next();
Member member = new Member(elm.attributeValue("id"),elm.elementText("name"),
Integer.parseInt(elm.elementText("age")));
if(member.getId().equals(id)){
rootElm.remove(elm);
break;
}
}
writeDocumentToFile();
return false;
} catch (XMLFileWriteException ex) {
throw ex;
}
}
public static boolean isFileExist(String filePath) {
boolean exists = (new File(filePath)).exists();
return exists;
}
}