分享自己写的db4o 连接池

08-05-30 gltbeyond
    

初步实现,如有问题欢迎拍砖。

package com.glt.table.db4oUtil;

import java.util.LinkedList;

import org.apache.log4j.Logger;

import com.db4o.Db4o;

import com.db4o.ObjectContainer;

import com.db4o.ObjectServer;

import com.db4o.config.Configuration;

/**

* 必须实现connection pool,因为在web应用中,servlet必定是多线程的。

* 1. 支持多客户端;

* 2. 事务必须手工commit;

* 3. 一个JVM中只能同时连接一个数据库。

* 4. 使用reset()更改参数。

*

* @author guolt

*/

public class Db4oCP {

private static final Logger log = Logger

.getLogger("com.glt.table.db4oUtil");

//数据库文件路径

private static String DATAFILE = "data/tableBuying.yap";

//连接池最小保持数

private static int MIN = 5;

//连接池最大保持数

private static int MAX = 10;

// 当前已经被获取使用的连接个数

private static int counts = 0;

//存放ObjectContainer对象

private static LinkedList connectionList=null;

private static ObjectServer objectServer = null;

// must be static 否则不会主动运行,不会在static 方法之前运行

static{

try {

init();

} catch (Exception e) {

e.printStackTrace();

}

}

/**

* 初始化Connection Pool中的Db4o的连接

* @throws Exception

*/

private static void init() throws Exception {

try {

connectionList=new LinkedList();

if(DATAFILE==null ||MIN==MAX){

log.error("Db4oCP initi faild, Please check configuration...");

System.exit(-1);

}

objectServer = Db4o.openServer(DATAFILE, 0);

Configuration cfg=Db4o.configure();

log.info("Db4o configuration: activationDepth:"+cfg.activationDepth());

//Db4o级联保存设置

//The default setting is 1: Only the object passed to ObjectContainer.set(java.lang.Object) will be updated.

//In client-server environment this setting should be used on both client and server sides

Db4o.configure().updateDepth(1);

for (int i = 0; i < MIN; i++) {

// 放在末尾

connectionList.add(objectServer.openClient());

}

} catch (Exception e) {

throw new Exception("Db4o init Faild");

}

log.info("Db4oCP init OK[DataFile:"+DATAFILE + "|MIN:"+MIN +"|MAX:"+MAX+ "|Free:" + connectionList.size()+"]");

}

public synchronized static ObjectContainer getODBConnection() throws Exception {

if (connectionList == null) {

log.error("Db4oCP is null.");

}

while (connectionList.isEmpty()) {

// 如果在MIX,MAX之间仍然创建并返回;否则出错。

if (counts < MAX) {

log.debug("DB4oCP free over MIN ,now new One CP..");

connectionList.add(objectServer.openClient());

} else {

throw new Exception("DB4oCP over MAX.");

}

}

// 移除并返回此列表的第一个元素

ObjectContainer odb = (ObjectContainer) connectionList.removeFirst();

counts++;

log.info("Db4oCP getODBConnection OK[used:" + counts + " |MAX:" + MAX + "|Free:" + connectionList.size()+"]");

return odb;

}

/**

* 释放,回收连接。

*/

public synchronized static void release(ObjectContainer odb) {

if(odb==null){

return;

}

counts--;

connectionList.add(odb);

log.info("Db4oCP release OK[used:" + counts + "|MAX:"+MAX+"|Free:"

+ connectionList.size()+"]");

//must set null ,or else be conflict.

odb=null;

}

/**

* 关闭数据库连接池

* @deprecated 调用会产生不可预料结果

* */

public static void cloesDB(){

connectionList=null;

counts=0;

objectServer.close();

}

/**

* 重置数据库连接池

* */

public static void reset(String dataFile,int min,int max){

DATAFILE=dataFile;

MIN=min;

MAX=max;

connectionList=null;

counts=0;

objectServer.close();

try {

init();

log.info("Db4oCP reset OK[DataFile:"+DATAFILE + "|MIN:"+MIN +"|MAX:"+MAX+ "|Free:" + connectionList.size()+"]");

} catch (Exception e) {

e.printStackTrace();

}

}

}

    

gltbeyond
2008-05-30 15:09

线程测试类:

public class Db4oCPTest extends TestCase {

private static final Logger log=Logger.getLogger("com.glt.table.test");

protected void setUp() throws Exception {

super.setUp();

}

protected void tearDown() throws Exception {

super.tearDown();

}

public void testGetODBConnection() {

Db4oCP.reset("data/sb.yap",5,10);

for(int i=0;i<17;i++){

Thread thread=new Thread(new Db4oClient(i));

thread.start();

try {

Thread.sleep(5);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

//必须sleep,否则

try {

Thread.sleep(10000);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println("main test over");

//下面是关闭数据库连接池的,不要调用,因为下面的方法可能会先于线程而调用!!!

//Db4oCP.cloesDB();

}

}

gltbeyond
2008-05-30 15:09

package com.glt.table.test;

import org.apache.log4j.Logger;

import com.db4o.ObjectContainer;

import com.db4o.ObjectSet;

import com.glt.table.db4oUtil.Db4oCP;

import com.glt.test.util.bean.Car;

import com.glt.test.util.bean.Person;

public class Db4oClient implements Runnable {

private static final Logger log=Logger.getLogger("com.glt.table.test");

private long wait;

public Db4oClient(long wait) {

super();

this.wait = wait;

}

/**

* @return the wait

*/

public long getWait() {

return wait;

}

/**

* @param wait the wait to set

*/

public void setWait(long wait) {

this.wait = wait;

}

public void run() {

ObjectContainer odb=null;

try {

odb=Db4oCP.getODBConnection();

Person person=new Person();

person.setName("name_"+wait);

Car car1=new Car();

car1.setDesc("XXX");

person.setCar(car1);

//odb.set(new StringBuffer("Hello, i'am waiting for "+wait));

odb.set(person);

odb.commit();

log.debug("thread:"+this+" sleep :"+wait);

Thread.sleep(wait);

ObjectSet objectset=odb.get(Person.class);

log.debug(this+"result.size:"+objectset.size());

while(objectset.hasNext()){

log.debug(this+" |"+objectset.next().toString());

}

} catch (Exception e) {

// TODO Auto-generated catch block

e.printStackTrace();

}finally{

Db4oCP.release(odb);

}

}

}

gltbeyond
2008-05-30 15:11

INFO - Db4o configuration: activationDepth:5

INFO - Db4oCP init OK[DataFile:data/tableBuying.yap|MIN:5|MAX:10|Free:5]

INFO - Db4o configuration: activationDepth:5

INFO - Db4oCP init OK[DataFile:data/sb.yap|MIN:5|MAX:10|Free:5]

INFO - Db4oCP reset OK[DataFile:data/sb.yap|MIN:5|MAX:10|Free:5]

INFO - Db4oCP getODBConnection OK[used:1 |MAX:10|Free:4]

INFO - Db4oCP getODBConnection OK[used:2 |MAX:10|Free:3]

INFO - Db4oCP getODBConnection OK[used:3 |MAX:10|Free:2]

INFO - Db4oCP getODBConnection OK[used:4 |MAX:10|Free:1]

INFO - Db4oCP getODBConnection OK[used:5 |MAX:10|Free:0]

DEBUG - DB4oCP free over MIN ,now new One CP..

INFO - Db4oCP getODBConnection OK[used:6 |MAX:10|Free:0]

DEBUG - DB4oCP free over MIN ,now new One CP..

DEBUG - thread:com.glt.table.test.Db4oClient@29e357 sleep :2

DEBUG - thread:com.glt.table.test.Db4oClient@ca470 sleep :0

DEBUG - thread:com.glt.table.test.Db4oClient@1ffc686 sleep :4

DEBUG - thread:com.glt.table.test.Db4oClient@1a082e2 sleep :3

DEBUG - thread:com.glt.table.test.Db4oClient@1f297e7 sleep :1

INFO - Db4oCP getODBConnection OK[used:7 |MAX:10|Free:0]

DEBUG - DB4oCP free over MIN ,now new One CP..

DEBUG - thread:com.glt.table.test.Db4oClient@14e3f41 sleep :5

INFO - Db4oCP getODBConnection OK[used:8 |MAX:10|Free:0]

DEBUG - DB4oCP free over MIN ,now new One CP..

DEBUG - com.glt.table.test.Db4oClient@ca470result.size:25

DEBUG - com.glt.table.test.Db4oClient@29e357result.size:25

DEBUG - com.glt.table.test.Db4oClient@1a082e2result.size:26

DEBUG - com.glt.table.test.Db4oClient@1f297e7result.size:26

DEBUG - thread:com.glt.table.test.Db4oClient@476128 sleep :6

INFO - Db4oCP getODBConnection OK[used:9 |MAX:10|Free:0]

DEBUG - DB4oCP free over MIN ,now new One CP..

DEBUG - com.glt.table.test.Db4oClient@1ffc686result.size:26

DEBUG - thread:com.glt.table.test.Db4oClient@164dbd5 sleep :7

DEBUG - com.glt.table.test.Db4oClient@ca470 |[Person:name_1|car:][Car:XXX|]

INFO - Db4oCP getODBConnection OK[used:10 |MAX:10|Free:0]

DEBUG - com.glt.table.test.Db4oClient@29e357 |[Person:name_1|car:][Car:XXX|]

java.lang.Exception: DB4oCP over MAX.

at com.glt.table.db4oUtil.Db4oCP.getODBConnection(Db4oCP.java:85)

at com.glt.table.test.Db4oClient.run(Db4oClient.java:39)

at java.lang.Thread.run(Thread.java:534)

java.lang.Exception: DB4oCP over MAX.

at com.glt.table.db4oUtil.Db4oCP.getODBConnection(Db4oCP.java:85)

at com.glt.table.test.Db4oClient.run(Db4oClient.java:39)

at java.lang.Thread.run(Thread.java:534)

DEBUG - com.glt.table.test.Db4oClient@1a082e2 |[Person:name_1|car:][Car:XXX|]

java.lang.Exception: DB4oCP over MAX.

at com.glt.table.db4oUtil.Db4oCP.getODBConnection(Db4oCP.java:85)

at com.glt.table.test.Db4oClient.run(Db4oClient.java:39)

at java.lang.Thread.run(Thread.java:534)

java.lang.Exception: DB4oCP over MAX.

at com.glt.table.db4oUtil.Db4oCP.getODBConnection(Db4oCP.java:85)

at com.glt.table.test.Db4oClient.run(Db4oClient.java:39)

at java.lang.Thread.run(Thread.java:534)

java.lang.Exception: DB4oCP over MAX.

at com.glt.table.db4oUtil.Db4oCP.getODBConnection(Db4oCP.java:85)

at com.glt.table.test.Db4oClient.run(Db4oClient.java:39)

at java.lang.Thread.run(Thread.java:534)

java.lang.Exception: DB4oCP over MAX.

at com.glt.table.db4oUtil.Db4oCP.getODBConnection(Db4oCP.java:85)

at com.glt.table.test.Db4oClient.run(Db4oClient.java:39)

at java.lang.Thread.run(Thread.java:534)

java.lang.Exception: DB4oCP over MAX.

at com.glt.table.db4oUtil.Db4oCP.getODBConnection(Db4oCP.java:85)

at com.glt.table.test.Db4oClient.run(Db4oClient.java:39)

at java.lang.Thread.run(Thread.java:534)

DEBUG - com.glt.table.test.Db4oClient@1f297e7 |[Person:name_1|car:][Car:XXX|]

DEBUG - com.glt.table.test.Db4oClient@14e3f41result.size:28

DEBUG - thread:com.glt.table.test.Db4oClient@1d95492 sleep :8

。。。。。。。。。。。。。。。。。。。。

[该贴被gltbeyond于2008-05-30 15:11修改过]

gltbeyond
2011-05-26 14:42

更新一下代码,时过3年,再次改写连接池:

package com.sdb.ebank.dbaccess;

import java.util.LinkedList;

import com.db4o.Db4o;
import com.db4o.ObjectContainer;
import com.db4o.ObjectServer;
..............

/**
 * Db4o Connection Pool,use C/S model
 * @[author]author[/author] Guolt
 * **/
public final class Db4oCP {

//	private static final String DB4OCSFLAG = "C";//LianaStandard.getSelfDefineSettingsValue("db4oCSFlag");
//	private static final String Db4oServerIP ="10.14.36.27";// LianaStandard.getSelfDefineSettingsValue("db4oServerIP");
//	private static final int Db4oServerPort = 30001;//Integer.parseInt(LianaStandard.getSelfDefineSettingsValue("db4oServerPort"));
//	private static String DATAFILE ="D:/db4o.yap."+System.currentTimeMillis(); // LianaStandard.getSelfDefineSettingsValue("tempDownloadDir")+ "/db4o.yap";
	
	private static final String DB4OCSFLAG = LianaStandard.getSelfDefineSettingsValue("db4oCSFlag");
	private static final String Db4oServerIP =  LianaStandard.getSelfDefineSettingsValue("db4oServerIP");
	private static final int Db4oServerPort =  Integer.parseInt(LianaStandard.getSelfDefineSettingsValue("db4oServerPort"));
	private static String DATAFILE = LianaStandard.getSelfDefineSettingsValue("tempDownloadDir")+ "/db4o.yap."+System.currentTimeMillis();

	
	private static final String _DEFAULT_DATAFILE = "db4o.yap."+System.currentTimeMillis();
	//perServer,perClient connection size.
	private static int MIN = 1;
	private static int MAX = 10;
	
	private static int counts = 0;

	private static LinkedList connectionList = new LinkedList();

	private static ObjectServer objectServer = null;

	private static void init() throws Exception {
		try {
			cloesDB();
			counts = 0;
			//cascadeOnUpdate cascadeOnDelete
			Db4o.configure().objectClass(CacheV2Element.class).cascadeOnUpdate(true);
			Db4o.configure().objectClass(CacheV2Element.class).cascadeOnDelete(true);
			
//			Db4o.configure().objectClass(DataElement.class).cascadeOnUpdate(true);
//			Db4o.configure().objectClass(DataElement.class).cascadeOnDelete(true);
//			
//			Db4o.configure().objectClass(KeyedCollection.class).cascadeOnUpdate(true);
//			Db4o.configure().objectClass(KeyedCollection.class).cascadeOnDelete(true);
			
			Trace.logDebug(Trace.COMPONENT_JDBC, "Db4o.configure() cascadeOnUpdate cascadeOnDelete :true");
			
			connectionList = new LinkedList();
			DATAFILE = (DATAFILE == null) ? _DEFAULT_DATAFILE : DATAFILE;
			if (DB4OCSFLAG.equalsIgnoreCase("S")) {
				// server model
				objectServer = Db4o.openServer(DATAFILE, 30001);
				objectServer.grantAccess("db4o", "db4o");
			} 
			
		} catch (Exception e) {
			Trace.logError(Trace.COMPONENT_JDBC, "Db4oCP init Error."
					+ e.getMessage());
			e.printStackTrace();
		}
		
		try{
			
			for (int i = 0; i < MIN; i++) {
				ObjectContainer container = Db4o.openClient(Db4oServerIP,
						Db4oServerPort, "db4o", "db4o");
				connectionList.add(container);
			}
			
		}catch(Exception e){}
		
		
		Trace.logWarn(Trace.COMPONENT_JDBC, "Db4oCP init OK.[DB4OCSFLAG:"+DB4OCSFLAG+",Db4oServerIP:"+Db4oServerIP+"|Port:"+Db4oServerPort+"|DataFile:"
				+ DATAFILE + "|MIN:" + MIN + "|MAX:" + MAX + "|Free:"
				+ connectionList.size() + "]");
	}

	/**
	 * 获取连接池中的ObjectContainer对象。
	 * */
	public static synchronized ObjectContainer getODBConnection()
			throws Exception {
		if (connectionList == null) {
			Trace.logError(Trace.COMPONENT_JDBC, "Db4oCP is null.");
			throw new Exception("db4o connectionList is null!");
		}
		//连接池空了,并且当前申请的未超MAX值。
		if ( connectionList.isEmpty() && counts < MAX ) {
			Trace.logInfo(Trace.COMPONENT_JDBC,
					"DB4oCP available 0,And not excess MAX:"+MAX+",now new One CP..");
			connectionList.add(Db4o.openClient(Db4oServerIP,
					Db4oServerPort, "db4o", "db4o"));// add where ?
		}else if(connectionList.isEmpty() && counts >= MAX){
			//当前申请的超MAX值
			Trace.logError(Trace.COMPONENT_JDBC, "Db4oCP available 0, And over MAX="+MAX);
			throw new Exception("Db4oCP is over MAX="+MAX);
		}

		// 从linkedList头部获取一个objectContainer实例
		ObjectContainer odb = (ObjectContainer) connectionList.removeFirst();
		counts += 1;
//		Trace.logDebug(Trace.COMPONENT_JDBC,
//				"Db4oCP getODBConnection OK[hashCode:"
//						+ odb.hashCode() + "|used:" + counts + " |MAX:" + MAX
//						+ "|Free:" + connectionList.size() + "]");
		return odb;
	}

	public static synchronized void release(ObjectContainer odb) {
		if (odb == null) {
			return;
		}
		counts -= 1;
		connectionList.add(odb);
//		Trace.logDebug(Trace.COMPONENT_JDBC, "Db4oCP release OK[used:" + counts
//				+ "|MAX:" + MAX + "|Free:" + connectionList.size() + "]");

		odb = null;
	}

	/** @deprecated */
	public static void cloesDB() {
		try {
			connectionList = null;
			counts = 0;
			if (objectServer != null) {
				objectServer.close();
			}

			Trace.logDebug(Trace.COMPONENT_JDBC, "db4o connection closed..");
		} catch (Exception e) {
			Trace.logError(Trace.COMPONENT_JDBC, "db4o connection closed,ERROR"
					+ e.getMessage());
		}

	}

	public static void reset(String dataFile, int min, int max) {
		try {
			DATAFILE = dataFile;
			MIN = min;
			MAX = max;
			cloesDB();

			init();
			Trace.logDebug(Trace.COMPONENT_JDBC, "Db4oCP reset OK[DataFile:"
					+ DATAFILE + "|MIN:" + MIN + "|MAX:" + MAX + "|Free:"
					+ connectionList.size() + "]");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/** @deprecated */
	public static void refreshx(Object object, int deepth) {
		for (int i = 0; i < connectionList.size(); ++i) {
			ObjectContainer odb = (ObjectContainer) connectionList.get(i);
			Trace.logDebug(Trace.COMPONENT_JDBC, "refresh |odb:"
					+ odb.hashCode() + "|object:" + object);
			odb.ext().refresh(object, deepth);
		}
	}

	static {
		try {
			init();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public static void test(){
		
	}
}


<p>

[该贴被gltbeyond于2011-05-26 14:43修改过]

2Go 1 2 下一页