??xml version="1.0" encoding="utf-8" standalone="yes"?>
Java 的JDBC 数据库连接池实现Ҏ
关键? Java, JDBC, Connection Pool, Database, 数据库连接池, sourcecode
虽然 J2EE E序员一般都有现成的应用服务器所带的JDBC 数据库连接池Q不q对于开发一般的 Java Application ?Applet 或?JSP、velocity Ӟ我们可用的JDBC 数据库连接池q不多,q且一般性能都不好?Java E序员都很M?Windows ADO Q只需?new Connection 可以直接从数据库连接池中返?Connection。ƈ?ADO Connection 是线E安全的Q多个线E可以共用一?ConnectionQ?所?ASP E序一般都?getConnection 攑֜ Global.asa 文g中,?IIS 启动时徏立数据库q接。ADO ?Connection ?Result 都有很好的缓Ԍq且很容易用?br />
其实我们可以自己写一个JDBC 数据库连接池。写 JDBC connection pool 的注意事ҎQ?br />
1. 有一个简单的函数从连接池中得C?Connection?
2. close 函数必须?connection 攑֛ 数据库连接池?
3. 当数据库q接池中没有I闲?connectionQ?数据库连接池必须能够自动增加 connection 个数?
4. 当数据库q接池中?connection 个数在某一个特别的旉变得很大Q但是以后很长时间只用其中一部分,应该可以自动多余的 connection 关闭掉?
5. 如果可能Q应该提供debug 信息报告没有关闭?new Connection ?
如果?new Connection 可以直接从数据库连接池中返?ConnectionQ?可以q样? Mediator pattern ) (以下代码中用了中文全角I格)Q?br />public class EasyConnection implements java.sql.Connection{
private Connection m_delegate = null;
public EasyConnection(){
m_delegate = getConnectionFromPool();
}
public void close(){
putConnectionBackToPool(m_delegate);
}
public PreparedStatement prepareStatement(String sql) throws SQLException{
m_delegate.prepareStatement(sql);
}
//...... other method
}
看来q不难。不q不q种写法Q因为应该尽量避免?Java Interface, 关于 Java Interface 的缺Ҏ另外再写文章讨论。大家关注的?Connection Pool 的实现方法。下面给ZU实现方法?import java.sql.*;
import java.lang.reflect.*;
import java.util.*;
import java.io.*;
public class SimpleConnetionPool {
private static LinkedList m_notUsedConnection = new LinkedList();
private static HashSet m_usedUsedConnection = new HashSet();
private static String m_url = "";
private static String m_user = "";
private static String m_password = "";
static final boolean DEBUG = true;
static private long m_lastClearClosedConnection = System.currentTimeMillis();
public static long CHECK_CLOSED_CONNECTION_TIME = 4 * 60 * 60 * 1000; //4 hours
static {
initDriver();
}
private SimpleConnetionPool() {
}
private static void initDriver() {
Driver driver = null;
//load mysql driver
try {
driver = (Driver) Class.forName("com.mysql.jdbc.Driver").newInstance();
installDriver(driver);
} catch (Exception e) {
}
//load postgresql driver
try {
driver = (Driver) Class.forName("org.postgresql.Driver").newInstance();
installDriver(driver);
} catch (Exception e) {
}
}
public static void installDriver(Driver driver) {
try {
DriverManager.registerDriver(driver);
} catch (Exception e) {
e.printStackTrace();
}
}
public static synchronized Connection getConnection() {
clearClosedConnection();
while (m_notUsedConnection.size() > 0) {
try {
ConnectionWrapper wrapper = (ConnectionWrapper) m_notUsedConnection.removeFirst();
if (wrapper.connection.isClosed()) {
continue;
}
m_usedUsedConnection.add(wrapper);
if (DEBUG) {
wrapper.debugInfo = new Throwable("Connection initial statement");
}
return wrapper.connection;
} catch (Exception e) {
}
}
int newCount = getIncreasingConnectionCount();
LinkedList list = new LinkedList();
ConnectionWrapper wrapper = null;
for (int i = 0; i < newCount; i++) {
wrapper = getNewConnection();
if (wrapper != null) {
list.add(wrapper);
}
}
if (list.size() == 0) {
return null;
}
wrapper = (ConnectionWrapper) list.removeFirst();
m_usedUsedConnection.add(wrapper);
m_notUsedConnection.addAll(list);
list.clear();
return wrapper.connection;
}
private static ConnectionWrapper getNewConnection() {
try {
Connection con = DriverManager.getConnection(m_url, m_user, m_password);
ConnectionWrapper wrapper = new ConnectionWrapper(con);
return wrapper;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
static synchronized void pushConnectionBackToPool(ConnectionWrapper con) {
boolean exist = m_usedUsedConnection.remove(con);
if (exist) {
m_notUsedConnection.addLast(con);
}
}
public static int close() {
int count = 0;
Iterator iterator = m_notUsedConnection.iterator();
while (iterator.hasNext()) {
try {
( (ConnectionWrapper) iterator.next()).close();
count++;
} catch (Exception e) {
}
}
m_notUsedConnection.clear();
iterator = m_usedUsedConnection.iterator();
while (iterator.hasNext()) {
try {
ConnectionWrapper wrapper = (ConnectionWrapper) iterator.next();
wrapper.close();
if (DEBUG) {
wrapper.debugInfo.printStackTrace();
}
count++;
} catch (Exception e) {
}
}
m_usedUsedConnection.clear();
return count;
}
private static void clearClosedConnection() {
long time = System.currentTimeMillis();
//sometimes user change system time,just return
if (time < m_lastClearClosedConnection) {
time = m_lastClearClosedConnection;
return;
}
//no need check very often
if (time - m_lastClearClosedConnection < CHECK_CLOSED_CONNECTION_TIME) {
return;
}
m_lastClearClosedConnection = time;
//begin check
Iterator iterator = m_notUsedConnection.iterator();
while (iterator.hasNext()) {
ConnectionWrapper wrapper = (ConnectionWrapper) iterator.next();
try {
if (wrapper.connection.isClosed()) {
iterator.remove();
}
} catch (Exception e) {
iterator.remove();
if (DEBUG) {
System.out.println("connection is closed, this connection initial StackTrace");
wrapper.debugInfo.printStackTrace();
}
}
}
//make connection pool size smaller if too big
int decrease = getDecreasingConnectionCount();
if (m_notUsedConnection.size() < decrease) {
return;
}
while (decrease-- > 0) {
ConnectionWrapper wrapper = (ConnectionWrapper) m_notUsedConnection.removeFirst();
try {
wrapper.connection.close();
} catch (Exception e) {
}
}
}
/**
* get increasing connection count, not just add 1 connection
* @return count
*/
public static int getIncreasingConnectionCount() {
int count = 1;
int current = getConnectionCount();
count = current / 4;
if (count < 1) {
count = 1;
}
return count;
}
/**
* get decreasing connection count, not just remove 1 connection
* @return count
*/
public static int getDecreasingConnectionCount() {
int count = 0;
int current = getConnectionCount();
if (current < 10) {
return 0;
}
return current / 3;
}
public synchronized static void printDebugMsg() {
printDebugMsg(System.out);
}
public synchronized static void printDebugMsg(PrintStream out) {
if (DEBUG == false) {
return;
}
StringBuffer msg = new StringBuffer();
msg.append("debug message in " + SimpleConnetionPool.class.getName());
msg.append("\r\n");
msg.append("total count is connection pool: " + getConnectionCount());
msg.append("\r\n");
msg.append("not used connection count: " + getNotUsedConnectionCount());
msg.append("\r\n");
msg.append("used connection, count: " + getUsedConnectionCount());
out.println(msg);
Iterator iterator = m_usedUsedConnection.iterator();
while (iterator.hasNext()) {
ConnectionWrapper wrapper = (ConnectionWrapper) iterator.next();
wrapper.debugInfo.printStackTrace(out);
}
out.println();
}
public static synchronized int getNotUsedConnectionCount() {
return m_notUsedConnection.size();
}
public static synchronized int getUsedConnectionCount() {
return m_usedUsedConnection.size();
}
public static synchronized int getConnectionCount() {
return m_notUsedConnection.size() + m_usedUsedConnection.size();
}
public static String getUrl() {
return m_url;
}
public static void setUrl(String url) {
if (url == null) {
return;
}
m_url = url.trim();
}
public static String getUser() {
return m_user;
}
public static void setUser(String user) {
if (user == null) {
return;
}
m_user = user.trim();
}
public static String getPassword() {
return m_password;
}
public static void setPassword(String password) {
if (password == null) {
return;
}
m_password = password.trim();
}
}
class ConnectionWrapper implements InvocationHandler {
private final static String CLOSE_METHOD_NAME = "close";
public Connection connection = null;
private Connection m_originConnection = null;
public long lastAccessTime = System.currentTimeMillis();
Throwable debugInfo = new Throwable("Connection initial statement");
ConnectionWrapper(Connection con) {
Class[] interfaces = {java.sql.Connection.class};
this.connection = (Connection) Proxy.newProxyInstance(
con.getClass().getClassLoader(),
interfaces, this);
m_originConnection = con;
}
void close() throws SQLException {
m_originConnection.close();
}
public Object invoke(Object proxy, Method m, Object[] args) throws Throwable {
Object obj = null;
if (CLOSE_METHOD_NAME.equals(m.getName())) {
SimpleConnetionPool.pushConnectionBackToPool(this);
}
else {
obj = m.invoke(m_originConnection, args);
}
lastAccessTime = System.currentTimeMillis();
return obj;
}
}
使用Ҏpublic class TestConnectionPool{
public static void main(String[] args) {
SimpleConnetionPool.setUrl(DBTools.getDatabaseUrl());
SimpleConnetionPool.setUser(DBTools.getDatabaseUserName());
SimpleConnetionPool.setPassword(DBTools.getDatabasePassword());
Connection con = SimpleConnetionPool.getConnection();
Connection con1 = SimpleConnetionPool.getConnection();
Connection con2 = SimpleConnetionPool.getConnection();
//do something with con ...
try {
con.close();
} catch (Exception e) {}
try {
con1.close();
} catch (Exception e) {}
try {
con2.close();
} catch (Exception e) {}
con = SimpleConnetionPool.getConnection();
con1 = SimpleConnetionPool.getConnection();
try {
con1.close();
} catch (Exception e) {}
con2 = SimpleConnetionPool.getConnection();
SimpleConnetionPool.printDebugMsg();
}
}
q行试E序后打印连接池?Connection 状态, 以及正在使用的没有关?Connection 信息?br />
]]>
Java数据库连接(JDBCQ由一l用 Java ~程语言~写的类和接口组成。JDBC 为工?数据库开发h员提供了一个标准的 APIQ他们能够用纯Java API 来编写数据库应用E序。然而各个开发商的接口ƈ不完全相同,所以开发环境的变化会带来一定的配置变化。本文主要集合了不同数据库的q接方式?
一、连接各U数据库方式速查?
下面|列了各U数据库使用JDBCq接的方式,可以作ؓ一个手册用?
1、Oracle8/8i/9i数据库(thin模式Q?
Class.forName("oracle.jdbc.driver.OracleDriver").newInstance();
String url="jdbc:oracle:thin:@localhost:1521:orcl"; //orcl为数据库的SID
String user="test";
String password="test";
Connection conn= DriverManager.getConnection(url,user,password);
2、DB2数据?
Class.forName("com.ibm.db2.jdbc.app.DB2Driver ").newInstance();
String url="jdbc:db2://localhost:5000/sample"; //sampleZ的数据库?
String user="admin";
String password="";
Connection conn= DriverManager.getConnection(url,user,password);
3、Sql Server7.0/2000数据?
Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver").newInstance();
String url="jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=mydb";
//mydb为数据库
String user="sa";
String password="";
Connection conn= DriverManager.getConnection(url,user,password);
4、Sybase数据?
Class.forName("com.sybase.jdbc.SybDriver").newInstance();
String url =" jdbc:sybase:Tds:localhost:5007/myDB";//myDBZ的数据库?
Properties sysProps = System.getProperties();
SysProps.put("user","userid");
SysProps.put("password","user_password");
Connection conn= DriverManager.getConnection(url, SysProps);
5、Informix数据?
Class.forName("com.informix.jdbc.IfxDriver").newInstance();
String url = "jdbc:informix-sqli://123.45.67.89:1533/myDB:INFORMIXSERVER=myserver;
user=testuser;password=testpassword"; //myDB为数据库?
Connection conn= DriverManager.getConnection(url);
6、MySQL数据?
Class.forName("org.gjt.mm.mysql.Driver").newInstance();
String url ="jdbc:mysql://localhost/myDB?user=soft&password=soft1234&useUnicode=true&characterEncoding=8859_1"
//myDB为数据库?
Connection conn= DriverManager.getConnection(url);
7、PostgreSQL数据?
Class.forName("org.postgresql.Driver").newInstance();
String url ="jdbc:postgresql://localhost/myDB" //myDB为数据库?
String user="myuser";
String password="mypassword";
Connection conn= DriverManager.getConnection(url,user,password);
8、access数据库直q用ODBC?
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver") ;
String url="jdbc:odbc:Driver={MicroSoft Access Driver (*.mdb)};DBQ="+application.getRealPath("/Data/ReportDemo.mdb");
Connection conn = DriverManager.getConnection(url,"","");
Statement stmtNew=conn.createStatement() ;
二、JDBCq接MySql方式
下面是用JDBCq接MySql的一个小的教E?
1、查N动程?
MySQL目前提供的java驱动E序为Connection/JQ可以从MySQL官方|站下蝲Qƈ扑ֈmysql-connector-java-3.0.15-ga-bin.jar文gQ此驱动E序为纯java驱动E序Q不需做其他配|?
2、动态指定classpath
如果需要执行时动态指定classpathQ就在执行时采用Qcp方式。否则将上面?jar文g加入到classpath环境变量中?
3、加载驱动程?
try{
Class.forName(com.mysql.jdbc.Driver);
System.out.println(Success loading Mysql Driver!);
}catch(Exception e)
{
System.out.println(Error loading Mysql Driver!);
e.printStackTrace();
}
4、设|连接的url
jdbcQmysqlQ?/localhost/databasename[?pa=va][Qpa=va]
三、以下列Z在用JDBC来连接Oracle数据库时可以使用的一些技?
1、在客户端Y件开发中使用Thin驱动E序
在开发Java软g斚wQOracle的数据库提供了四U类型的驱动E序Q二U用于应用Y件、applets、servlets{客L软gQ另外二U用于数据库中的Java存储q程{服务器端Y件。在客户机端软g的开发中Q我们可以选择OCI驱动E序或Thin驱动E序。OCI驱动E序利用Java本地化接口(JNIQ,通过Oracle客户端Y件与数据库进行通讯。Thin驱动E序是纯Java驱动E序Q它直接与数据库q行通讯。ؓ了获得最高的性能QOracle在客L软g的开发中使用OCI驱动E序Q这g是正的。但我徏议用Thin驱动E序Q因为通过多次试发现Q在通常情况下,Thin驱动E序的性能都超q了OCI驱动E序?
2、关闭自动提交功能,提高pȝ性能
在第一ơ徏立与数据库的q接Ӟ在缺省情况下Q连接是在自动提交模式下的。ؓ了获得更好的性能Q可以通过调用带布值false参数的ConnectioncȝsetAutoCommit()Ҏ关闭自动提交功能Q如下所C:
conn.setAutoCommit(false);
值得注意的是Q一旦关闭了自动提交功能Q我们就需要通过调用Connectioncȝcommit()和rollback()Ҏ来h工的方式对事务进行管理?
3、在动态SQL或有旉限制的命令中使用Statement对象
在执行SQL命oӞ我们有二U选择Q可以用PreparedStatement对象Q也可以使用Statement对象。无论多次C用同一个SQL命oQPreparedStatement都只对它解析和编译一ơ。当使用Statement对象Ӟ每次执行一个SQL命oӞ都会对它q行解析和编译。这可能会你认为,使用PreparedStatement对象比用Statement对象的速度更快。然而,我进行的试表明Q在客户端Y件中Q情况ƈ非如此。因此,在有旉限制的SQL操作中,除非成批地处理SQL命oQ我们应当考虑使用Statement对象?
此外Q用Statement对象也得编写动态SQL命o更加单,因ؓ我们可以字W串q接在一P建立一个有效的SQL命o。因此,我认为,Statement对象可以使动态SQL命o的创建和执行变得更加单?
4、利用helper函数对动态SQL命oq行格式?
在创Z用Statement对象执行的动态SQL命oӞ我们需要处理一些格式化斚w的问题。例如,如果我们惛_Z个将名字O'Reilly插入表中的SQL命oQ则必须使用二个相连的?'”号替换O'Reilly中的?”号。完成这些工作的最好的Ҏ是创Z个完成替换操作的helperҎQ然后在q接字符串心服用公式表达一个SQL命oӞ使用创徏的helperҎ。与此类似的是,我们可以让helperҎ接受一个Date型的|然后让它输出ZOracle的to_date()函数的字W串表达式?
5、利用PreparedStatement对象提高数据库的M效率
在用PreparedStatement对象执行SQL命oӞ命o被数据库q行解析和编译,然后被放到命令缓冲区。然后,每当执行同一个PreparedStatement对象Ӟ它就会被再解析一ơ,但不会被再次~译。在~冲Z可以发现预编译的命oQƈ且可以重C用。在有大量用L企业U应用Y件中Q经怼重复执行相同的SQL命oQ用PreparedStatement对象带来的编译次数的减少能够提高数据库的M性能。如果不是在客户端创建、预备、执行PreparedStatementd需要的旉长于StatementdQ我会徏议在除动态SQL命o之外的所有情况下使用PreparedStatement对象?
6、在成批处理重复的插入或更新操作中用PreparedStatement对象
如果成批地处理插入和更新操作Q就能够显著地减它们所需要的旉。Oracle提供的Statement?CallableStatementq不真正地支持批处理Q只有PreparedStatement对象才真正地支持批处理。我们可以用addBatch()和executeBatch()Ҏ选择标准的JDBC批处理,或者通过利用PreparedStatement对象的setExecuteBatch()Ҏ和标准的executeUpdate()Ҏ选择速度更快的Oracle专有的方法。要使用Oracle专有的批处理机制Q可以以如下所C的方式调用setExecuteBatch()Q?
PreparedStatement pstmt3D null;
try {
((OraclePreparedStatement)pstmt).setExecuteBatch(30);
...
pstmt.executeUpdate();
}
调用setExecuteBatch()时指定的值是一个上限,当达到该值时Q就会自动地引发SQL命o执行Q标准的executeUpdate()Ҏ׃被作为批处理送到数据库中。我们可以通过调用PreparedStatementcȝsendBatch()Ҏ随时传输批处理Q务?
7、用Oracle locatorҎ插入、更新大对象QLOBQ?
Oracle的PreparedStatementcM完全支持BLOB和CLOB{大对象的处理,其是Thin驱动E序不支持利用PreparedStatement对象的setObject()和setBinaryStream()Ҏ讄BLOB的|也不支持利用setCharacterStream()Ҏ讄CLOB的倹{只有locator本n中的Ҏ才能够从数据库中获取LOBcd的倹{可以用PreparedStatement对象插入或更新LOBQ但需要用locator才能获取LOB的倹{由于存在这二个问题Q因此,我徏议用locator的方法来插入、更新或获取LOB的倹{?
8、用SQL92语法调用存储q程
在调用存储过E时Q我们可以用SQL92或Oracle PL/SQLQ由于用Oracle PL/SQLq没有什么实际的好处Q而且会给以后l护你的应用E序的开发h员带来麻烦,因此Q我在调用存储过E时使用SQL92?
9、用Object SQL对象模式{Ud数据库中
既然可以Oracle的数据库作ؓ一U面向对象的数据库来使用Q就可以考虑应用程序中的面向对象模式{到数据库中。目前的Ҏ是创建Java bean作ؓ伪装的数据库对象Q将它们的属性映到关系表中Q然后在q些bean中添加方法。尽这样作在Java中没有什么问题,但由于操作都是在数据库之外进行的Q因此其他访问数据库的应用Y件无法利用对象模式。如果利用Oracle的面向对象的技术,可以通过创徏一个新的数据库对象cd在数据库中模仿其数据和操作,然后使用JPublisher{工L成自qJava beancR如果用这U方式,不但Java应用E序可以使用应用软g的对象模式,其他需要共享你的应用中的数据和操作的应用Y件也可以使用应用软g中的对象模式?
10、利用SQL完成数据库内的操?
我要向大家介l的最重要的经验是充分利用SQL的面向集合的Ҏ来解x据库处理需求,而不是用Java{过E化的编E语a?
如果~程人员要在一个表中查找许多行Q结果中的每个行都会查找其他表中的数据,最后,~程人员创徏了独立的UPDATE命o来成批地更新W一个表中的数据。与此类似的d可以通过在set子句中用多列子查询而在一个UPDATE命o中完成。当能够在单一的SQL命o中完成Q务,何必要让数据在网上流来流ȝQ我用户认真学习如何最大限度地发挥SQL的功能?/span>
]]>
什么是
iBATIS
Q?/span>
和众多的
SourceForge
开源项目一P
iBATIS
曄也是其中的一员。在
2004
q?/span>
11
?/span>
3
日成功地成ؓ?/span>
Apache Incubator
下的子项目?/span>
iBATIS
包括
for Java
?/span>
for .NET
两个版本Q?/span>
for Java
版提供了
SQL Maps
?/span>
DAO
框架Q?/span>
for .NET
只提供了
SQL Maps
框架。从现在开始我们只?/span>
for Java
版的
SQL Maps
展开讨论?/span>
你可以在
http://www.ibatis.com
下蝲
iBATIS for Java
Q目前最新版本是
2.0.9
Q压~包里已l包含了
SQL Maps(ibatis-sqlmap-2.jar)
?/span>
DAO
框架
(ibatis-dao-2.jar)
?/span>
Z么选择
iBATIS
Q?/span>
也许各位看官已在各种不同的技术资料上了解到它的优ѝ但是对于我来说Q选择它的理由只有一?/span>
——?/span>
利用原有资源
?/span>
?/span>
Hibernate
的却优秀Q但是用来整合原有系l,它却很难胜Q。例如,以前在进行数据徏模时使用了复合主键、跨多表生的几十甚至上百行的查询语句、利用原有存储过E?/span>
??
当面临这一pd问题?/span>
Hibernate
显得力不从心了Q要想?/span>
Hibernate
只能改造原有系l!
当我面;pȝ整合问题Ӟ整合的要求很单:只需要保留原有系l查询部分)Q?/span>
iBATIS
q入了我的视Uѝ原有系l中?/span>
SQL
语句需要小的修改外,数据表、查询结果都不需要改变!也不用像
Hibernate
那样映射Z多的配置文g?/span>
POJO
Q一下子清爽了很多?/span>
BTW
Q?/span>
Hibernate
q种做法没有错!只是我只需要查询功能,仅仅是取我所好而已Q避免了杀鸡用牛刀?/span>
目前Q系l整合已l结束,׃一个月旉。如果?/span>
Hibernate
Q恐怕我现在q在为怎么设计数据表、怎样?/span>
HQL
而和同事争论?/span>
开始另一?/span>
O/R Mapping
之旅
上次
O/R Mapping
之旅?/span>
BO
、数据表q可以重用,只是把数据库q移C
MySQL
?span style="COLOR: black">打开
Eclipse
Q新Z?/span>
Resin
目。把
ibatis-sqlmap-2.jar
?/span>
ibatis-common-2.jar
拯?/span>
lib
目录下,再导入项目。和
Hibernate
自动配置、自动映相比,
iBATIS
的一切都是手工完成的?/span>
?/span>
src
下徏立配|文?/span>
SqlMapConfig.xml
Q数据库链接、连接池?/span>
SqlMap
映射文g
??
q些都要靠它了。官方参考手册对怎样q行讄有很详细的描qͼ我只对要用到的地方进行粗略说明?br />
<?xml version="1.0" encoding="UTF-8" ?> <sqlMapConfig>
<settings
<transactionManager type="JDBC">
<sqlMap resource="bo/mapping/AutoMag.xml"/> |
JDBC
Q通过传统
JDBC
来管理事务?/span>
JTA Q用一?/span> JTA 全局事务Q iBATIS 的事务包括在更大的事务范围内Q跨数据?/span> Session 的)Q这个更大的事务范围可能包括了其他的数据库和事务资源。这个配|需要一?/span> UserTransaction 属性,以便?/span> JNDI 获得一?/span> UserTransaction ?/span>
EXTERNAL
Q调?/font>
iBATIS
以外的其他事务管理器来管理事务?/span>
dataSource
元素?/span>
transactionManager
的一部分?/span>
type
可选项包括Q?br />
SIMPLE
Q?/span>
SIMPLE
?/span>
iBATIS
内置?/span>
dataSource
实现Q其中实C一个简单的数据库连接池Q当无容器提?/span>
DataSource
服务时可以用该选项Q对?/span>
iBATIS
实现cMؓ
com.ibatis.sqlmap.engine.datasource.SimpleDataSourceFactory
?/span>
? DBCP:
Z
Apache DBCP
q接?/span>
API
实现?/span>
DataSource
Q当无容器提?/span>
DataSource
服务Ӟ可以使用该选项Q对?/span>
iBATIS
实现cMؓ
com.ibatis.sqlmap.engine.datasource.DbcpDataSourceFactory
?/span>
?JNDI
Q?/span>
J2EE
容器提供?/span>
DataSource
实现Q?/span>
DataSource
通过指定?/span>
JNDI Name
从容器中获取。对?/span>
iBATIS
实现cMؓ
com.ibatis.sqlmap.engine.datasource.JndiDataSourceFactory
?/span>
注意Q?/span>
每种
dataSource
元素?/font>
property
都有不同的地方,不能光把
type
名字改了了事?/span>
sqlMap
元素定义了映文件的存放位置Q配|文件中可包含多?/font>
sqlMap
元素Q比如:
<sqlMap resource="mapping/AutoMag1.xml"/>
<sqlMap url="
file:///c:/eclipse/workspace/iBATISTest/src/bo/
AutoMag2.xml "/> |
你也许已发现Q我只定义了单个映射文g。不错,?/font>
Hibernate
的一个表一个映文件不同,
iBATIS
的映文件个数可以h为控Ӟ颗粒度自己掌握?/span>
光有
BO
和配|文件还不行Q还要ؓ本次试创徏试c?/font>
AutoMag.java
。完整的布局如下所C:
以下?span lang="EN-US"> iBATIS SQL Maps 工作程Q对于理解概念很有帮助。大意是 1、你可以?JavaBean、Map cd、原始变量(或者它们的Wrapper ClassQ、XML 数据作ؓ传入对象Q?、通过配置文g载入映射文gQ?、利用框架翻译成 JDBC 来访问数据库Q?、执行结果可以是 JavaBean、Map cd、原始变量(或者它们的Wrapper ClassQ、XML 数据?br />
<daoConfig>
<context id="sqlmap">
<transactionManager type="SQLMAP">
<property name="SqlMapConfigResource" value=
"com/sample/contact/dao/sqlmap/SqlMapConfig.xml"/>
</transactionManager>
<dao interface="com.sample.contact.dao.ContactDAO"
implementation=
"com.sample.contact.dao.sqlmap.SQLMapContactDAO"/>
</context>
</daoConfig>
public interface ContactDAO extends DAO {
public int insertContact(Contact contact);
public int updateContact(Contact contact);
public Contact selectContact(int contactId);
public int deleteContact(int contactId);
}
public class SQLMapContactDAO extends
SqlMapDaoTemplate implements ContactDAO {
public SQLMapContactDAO(DaoManager arg0) {
super(arg0);
}
public int deleteContact(int contactId) {
return super.delete("deleteContact",
new Integer(contactId));
}
public int insertContact(Contact contact) {
Integer contactId =(Integer)super.insert
("insertContact",contact);
return contact.getContactId();
}
public Contact selectContact(int contactId) {
return (Contact)super.queryForObject("getContact",
new Integer(contactId));
}
public int updateContact(Contact contact) {
return super.update("updateContact",contact);
}
}
Contact contactForm = (Contact) form;
Reader reader=
Resources.getResourceAsReader("DAOMap.xml");
DaoManager daoManager =
DaoManagerBuilder.buildDaoManager(reader);
ContactDAO contactDAO =
(ContactDAO) daoManager.getDao(
ContactDAO.class,"sqlmap");
request.setAttribute("contactDetail",
contactDAO.selectContact(
contactForm.getContactId()));
<transactionManager type="JDBC">
<property name="DataSource" value="SIMPLE"/>
<property name="JDBC.Driver"
value="com.ibm.db2j.jdbc.DB2jDriver"/>
<property name="JDBC.ConnectionURL"
value="jdbc:db2j:D:\cloudscape\wpsdb"/>
<property name="JDBC.Username"
value="db2admin"/>
<property name="JDBC.Password"
value="db2admin"/>
<property name="JDBC.DefaultAutoCommit"
value="true" />
</transactionManager>
<transactionManager type="JDBC">
<property name="DataSource" value="JNDI"/>
<property name="DBJndiContext"
value="java:comp/env/jdbc/MyDataSource"/>
</transactionManager>
public int updateContact(Contact contact) {
try {
Connection conn = getConnection();
PreparedStatement updateStmt =
conn.prepareStatement("UPDATE DB2ADMIN.CONTACT
SET FIRSTNAME=?,LASTNAME=? WHERE CONTACTID=?");
updateStmt.setString(1, contact.getFirstName());
updateStmt.setString(2, contact.getLastName());
updateStmt.setInt(3, contact.getContactId());
return updateStmt.executeUpdate();
} catch (SQLException ex) {
throw new DaoException(ex);
}
}
<transactionManager type="JTA">
<property name="DBJndiContext"
value="java:comp/env/jdbc/MyDataSource"/>
<property name="UserTransaction"
value="java:comp/env/UserTransaction"/>
</transactionManager>
<transactionManager type="HIBERNATE">
<property name="hibernate.dialect"
value="net.sf.hibernate.dialect.Cloudscape"/>
<property name="hibernate.connection.driver_class"
value="com.ibm.db2j.jdbc.DB2jDriver"/>
<property name="hibernate.connection.url"
value="jdbc:db2j:D:\cloudscape\wpsdb"/>
<property name="hibernate.connection.username"
value="db2admin/>
<property name="hibernate.connection.password"
value="db2admin"/>
<property name="class.1"
value="com.sample.contact.Contact"/>
</transactionManager>
public class XMLContactDAO implements ContactDAO {
public static final String
CONTACTXMLNAME = "c:\\Contact.xml";
public XMLContactDAO(DaoManager manager) {
super(manager);
}
public int insertContact(Contact contact) {
HashMap contactMap = loadChanges();
if (contactMap.get(new Integer
(contact.getContactId())) == null)
contactMap.put(new
Integer(contact.getContactId()), contact);
saveChanges(contactMap);
return contact.getContactId();
}
public Contact selectContact(int contactId) {
HashMap contactMap = loadChanges();
return (Contact) contactMap.get(
new Integer(contactId));
}
public HashMap loadChanges() {
HashMap contactMap = null;
try {
XStream xstream = new XStream(new DomDriver());
xstream.alias("contact", Contact.class);
contactMap =
(HashMap) xstream.fromXML(
new FileReader(CONTACTXMLNAME),HashMap.class);
} catch (FileNotFoundException e) {
e.printStackTrace();
return new HashMap();
}
return contactMap;
}
public void saveChanges(HashMap contactMap) {
try {
XStream xstream = new XStream();
xstream.alias("contact", Contact.class);
xstream.toXML(contactMap,
new FileWriter(CONTACTXMLNAME));
} catch (IOException e) {
e.printStackTrace();
}
}
}