??xml version="1.0" encoding="utf-8" standalone="yes"?>久久亚洲精品无码av,亚洲AV永久无码精品一百度影院,亚洲色大成网站www久久九http://www.tkk7.com/wangxq/articles/41818.html扭{乑֝扭{乑֝Wed, 19 Apr 2006 02:11:00 GMThttp://www.tkk7.com/wangxq/articles/41818.htmlhttp://www.tkk7.com/wangxq/comments/41818.htmlhttp://www.tkk7.com/wangxq/articles/41818.html#Feedback0http://www.tkk7.com/wangxq/comments/commentRss/41818.htmlhttp://www.tkk7.com/wangxq/services/trackbacks/41818.htmlhttp://www.matrix.org.cn/resource/article/43/43837_JDBC.html
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 />

扭{乑֝ 2006-04-19 10:11 发表评论
]]>
[转]JDBCq接数据库经验技?/title><link>http://www.tkk7.com/wangxq/articles/37746.html</link><dc:creator>扭{乑֝</dc:creator><author>扭{乑֝</author><pubDate>Tue, 28 Mar 2006 03:13:00 GMT</pubDate><guid>http://www.tkk7.com/wangxq/articles/37746.html</guid><wfw:comment>http://www.tkk7.com/wangxq/comments/37746.html</wfw:comment><comments>http://www.tkk7.com/wangxq/articles/37746.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/wangxq/comments/commentRss/37746.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/wangxq/services/trackbacks/37746.html</trackback:ping><description><![CDATA[ <span id="LblContent">from: <a >http://it.com.cn/f/edu/053/22/90113.htm</a><br />Java数据库连接(JDBCQ由一l用 Java ~程语言~写的类和接口组成。JDBC 为工?数据库开发h员提供了一个标准的 APIQ他们能够用纯Java API 来编写数据库应用E序。然而各个开发商的接口ƈ不完全相同,所以开发环境的变化会带来一定的配置变化。本文主要集合了不同数据库的q接方式?<br /><br />  <strong>一、连接各U数据库方式速查?<br /></strong><br />  下面|列了各U数据库使用JDBCq接的方式,可以作ؓ一个手册用?<br /><br />  1、Oracle8/8i/9i数据库(thin模式Q?<br /><br />  Class.forName("oracle.jdbc.driver.OracleDriver").newInstance(); <br />  String url="jdbc:oracle:thin:@localhost:1521:orcl"; //orcl为数据库的SID <br />  String user="test"; <br />  String password="test"; <br />  Connection conn= DriverManager.getConnection(url,user,password); <br /><br />  2、DB2数据?<br /><br />  Class.forName("com.ibm.db2.jdbc.app.DB2Driver ").newInstance(); <br />  String url="jdbc:db2://localhost:5000/sample"; //sampleZ的数据库?<br />  String user="admin"; <br />  String password=""; <br />  Connection conn= DriverManager.getConnection(url,user,password); <br /><br />  3、Sql Server7.0/2000数据?<br /><br />  Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver").newInstance(); <br />  String url="jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=mydb"; <br />  //mydb为数据库 <br />  String user="sa"; <br />  String password=""; <br />  Connection conn= DriverManager.getConnection(url,user,password); <br /><br />  4、Sybase数据?<br /><br />  Class.forName("com.sybase.jdbc.SybDriver").newInstance(); <br />  String url =" jdbc:sybase:Tds:localhost:5007/myDB";//myDBZ的数据库?<br />  Properties sysProps = System.getProperties(); <br />  SysProps.put("user","userid"); <br />  SysProps.put("password","user_password"); <br />  Connection conn= DriverManager.getConnection(url, SysProps); <br /><br />  5、Informix数据?<br /><br />  Class.forName("com.informix.jdbc.IfxDriver").newInstance(); <br />  String url = "jdbc:informix-sqli://123.45.67.89:1533/myDB:INFORMIXSERVER=myserver; <br />  user=testuser;password=testpassword"; //myDB为数据库?<br />  Connection conn= DriverManager.getConnection(url); <br /><br />  6、MySQL数据?<br /><br />  Class.forName("org.gjt.mm.mysql.Driver").newInstance(); <br />  String url ="jdbc:mysql://localhost/myDB?user=soft&password=soft1234&useUnicode=true&characterEncoding=8859_1" <br />  //myDB为数据库?<br />  Connection conn= DriverManager.getConnection(url); <br /><br />  7、PostgreSQL数据?<br /><br />  Class.forName("org.postgresql.Driver").newInstance(); <br />  String url ="jdbc:postgresql://localhost/myDB" //myDB为数据库?<br />  String user="myuser"; <br />  String password="mypassword"; <br />  Connection conn= DriverManager.getConnection(url,user,password); <br /><br />  8、access数据库直q用ODBC?<br /><br />  Class.forName("sun.jdbc.odbc.JdbcOdbcDriver") ; <br />  String url="jdbc:odbc:Driver={MicroSoft Access Driver (*.mdb)};DBQ="+application.getRealPath("/Data/ReportDemo.mdb"); <br />  Connection conn = DriverManager.getConnection(url,"",""); <br />  Statement stmtNew=conn.createStatement() ; <br /><br />  <strong>二、JDBCq接MySql方式 <br /></strong><br />  下面是用JDBCq接MySql的一个小的教E?<br /><br />  1、查N动程?<br /><br />  MySQL目前提供的java驱动E序为Connection/JQ可以从MySQL官方|站下蝲Qƈ扑ֈmysql-connector-java-3.0.15-ga-bin.jar文gQ此驱动E序为纯java驱动E序Q不需做其他配|?<br /><br />  2、动态指定classpath <br /><br />  如果需要执行时动态指定classpathQ就在执行时采用Qcp方式。否则将上面?jar文g加入到classpath环境变量中?<br /><br />  3、加载驱动程?<br /><br />  try{ <br />  Class.forName(com.mysql.jdbc.Driver); <br />  System.out.println(Success loading Mysql Driver!); <br />  }catch(Exception e) <br />  { <br />  System.out.println(Error loading Mysql Driver!); <br />  e.printStackTrace(); <br />  } <br /><br />  4、设|连接的url <br /><br />  jdbcQmysqlQ?/localhost/databasename[?pa=va][Qpa=va] <br /><br />   <strong>三、以下列Z在用JDBC来连接Oracle数据库时可以使用的一些技?<br /><br /></strong>  1、在客户端Y件开发中使用Thin驱动E序 <br /><br />  在开发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序?<br /><br />  2、关闭自动提交功能,提高pȝ性能 <br /><br />  在第一ơ徏立与数据库的q接Ӟ在缺省情况下Q连接是在自动提交模式下的。ؓ了获得更好的性能Q可以通过调用带布值false参数的ConnectioncȝsetAutoCommit()Ҏ关闭自动提交功能Q如下所C: <br /><br />  conn.setAutoCommit(false); <br /><br />  值得注意的是Q一旦关闭了自动提交功能Q我们就需要通过调用Connectioncȝcommit()和rollback()Ҏ来h工的方式对事务进行管理?<br /><br />  3、在动态SQL或有旉限制的命令中使用Statement对象 <br /><br />  在执行SQL命oӞ我们有二U选择Q可以用PreparedStatement对象Q也可以使用Statement对象。无论多次C用同一个SQL命oQPreparedStatement都只对它解析和编译一ơ。当使用Statement对象Ӟ每次执行一个SQL命oӞ都会对它q行解析和编译。这可能会你认为,使用PreparedStatement对象比用Statement对象的速度更快。然而,我进行的试表明Q在客户端Y件中Q情况ƈ非如此。因此,在有旉限制的SQL操作中,除非成批地处理SQL命oQ我们应当考虑使用Statement对象?<br /><br />  此外Q用Statement对象也得编写动态SQL命o更加单,因ؓ我们可以字W串q接在一P建立一个有效的SQL命o。因此,我认为,Statement对象可以使动态SQL命o的创建和执行变得更加单?<br /><br />  4、利用helper函数对动态SQL命oq行格式?<br /><br />  在创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串表达式?<br /><br />  5、利用PreparedStatement对象提高数据库的M效率 <br /><br />  在用PreparedStatement对象执行SQL命oӞ命o被数据库q行解析和编译,然后被放到命令缓冲区。然后,每当执行同一个PreparedStatement对象Ӟ它就会被再解析一ơ,但不会被再次~译。在~冲Z可以发现预编译的命oQƈ且可以重C用。在有大量用L企业U应用Y件中Q经怼重复执行相同的SQL命oQ用PreparedStatement对象带来的编译次数的减少能够提高数据库的M性能。如果不是在客户端创建、预备、执行PreparedStatementd需要的旉长于StatementdQ我会徏议在除动态SQL命o之外的所有情况下使用PreparedStatement对象?<br /><br />  6、在成批处理重复的插入或更新操作中用PreparedStatement对象 <br /><br />  如果成批地处理插入和更新操作Q就能够显著地减它们所需要的旉。Oracle提供的Statement?CallableStatementq不真正地支持批处理Q只有PreparedStatement对象才真正地支持批处理。我们可以用addBatch()和executeBatch()Ҏ选择标准的JDBC批处理,或者通过利用PreparedStatement对象的setExecuteBatch()Ҏ和标准的executeUpdate()Ҏ选择速度更快的Oracle专有的方法。要使用Oracle专有的批处理机制Q可以以如下所C的方式调用setExecuteBatch()Q?<br /><br />  PreparedStatement pstmt3D null; <br />  try { <br />  ((OraclePreparedStatement)pstmt).setExecuteBatch(30); <br />  ... <br />  pstmt.executeUpdate(); <br />  } <br /><br />  调用setExecuteBatch()时指定的值是一个上限,当达到该值时Q就会自动地引发SQL命o执行Q标准的executeUpdate()Ҏ׃被作为批处理送到数据库中。我们可以通过调用PreparedStatementcȝsendBatch()Ҏ随时传输批处理Q务?<br /><br />  7、用Oracle locatorҎ插入、更新大对象QLOBQ?<br /><br />  Oracle的PreparedStatementcM完全支持BLOB和CLOB{大对象的处理,其是Thin驱动E序不支持利用PreparedStatement对象的setObject()和setBinaryStream()Ҏ讄BLOB的|也不支持利用setCharacterStream()Ҏ讄CLOB的倹{只有locator本n中的Ҏ才能够从数据库中获取LOBcd的倹{可以用PreparedStatement对象插入或更新LOBQ但需要用locator才能获取LOB的倹{由于存在这二个问题Q因此,我徏议用locator的方法来插入、更新或获取LOB的倹{?<br /><br />  8、用SQL92语法调用存储q程 <br /><br />  在调用存储过E时Q我们可以用SQL92或Oracle PL/SQLQ由于用Oracle PL/SQLq没有什么实际的好处Q而且会给以后l护你的应用E序的开发h员带来麻烦,因此Q我在调用存储过E时使用SQL92?<br /><br />  9、用Object SQL对象模式{Ud数据库中 <br /><br />  既然可以Oracle的数据库作ؓ一U面向对象的数据库来使用Q就可以考虑应用程序中的面向对象模式{到数据库中。目前的Ҏ是创建Java bean作ؓ伪装的数据库对象Q将它们的属性映到关系表中Q然后在q些bean中添加方法。尽这样作在Java中没有什么问题,但由于操作都是在数据库之外进行的Q因此其他访问数据库的应用Y件无法利用对象模式。如果利用Oracle的面向对象的技术,可以通过创徏一个新的数据库对象cd在数据库中模仿其数据和操作,然后使用JPublisher{工L成自qJava beancR如果用这U方式,不但Java应用E序可以使用应用软g的对象模式,其他需要共享你的应用中的数据和操作的应用Y件也可以使用应用软g中的对象模式?<br /><br />  10、利用SQL完成数据库内的操?<br /><br />  我要向大家介l的最重要的经验是充分利用SQL的面向集合的Ҏ来解x据库处理需求,而不是用Java{过E化的编E语a?<br /><br />  如果~程人员要在一个表中查找许多行Q结果中的每个行都会查找其他表中的数据,最后,~程人员创徏了独立的UPDATE命o来成批地更新W一个表中的数据。与此类似的d可以通过在set子句中用多列子查询而在一个UPDATE命o中完成。当能够在单一的SQL命o中完成Q务,何必要让数据在网上流来流ȝQ我用户认真学习如何最大限度地发挥SQL的功能?/span> <img src ="http://www.tkk7.com/wangxq/aggbug/37746.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/wangxq/" target="_blank">扭{乑֝</a> 2006-03-28 11:13 <a href="http://www.tkk7.com/wangxq/articles/37746.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]iBATIS SQL Mapshttp://www.tkk7.com/wangxq/articles/36809.html扭{乑֝扭{乑֝Wed, 22 Mar 2006 03:25:00 GMThttp://www.tkk7.com/wangxq/articles/36809.htmlhttp://www.tkk7.com/wangxq/comments/36809.htmlhttp://www.tkk7.com/wangxq/articles/36809.html#Feedback0http://www.tkk7.com/wangxq/comments/commentRss/36809.htmlhttp://www.tkk7.com/wangxq/services/trackbacks/36809.html 自:http://www.codesky.net/article/doc/200412/2004121597969923.htm
什么是
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" ?>
<!DOCTYPE sqlMapConfig
    PUBLIC "-//iBATIS.com//DTD SQL Map Config 2.0//EN"
    "
http://www.ibatis.com/dtd/sql-map-config-2.dtd ">

<sqlMapConfig>

  <settings
    cacheModelsEnabled="true"
    enhancementEnabled="true"
    lazyLoadingEnabled="true"
    errorTracingEnabled="false"
    maxRequests="32"
    maxSessions="10"
    maxTransactions="5"
    useStatementNamespaces="false"
    />

  <transactionManager type="JDBC">
    <dataSource type="SIMPLE">
      <property name="JDBC.Driver" value="org.gjt.mm.mysql.Driver"/>
      <property name="JDBC.ConnectionURL" value="jdbc:mysql://localhost/new_db?useUnicode=true"/>
      <property name="JDBC.Username" value="root"/>
      <property name="JDBC.Password" value=""/>
      <property name="JDBC.DefaultAutoCommit" value="true"/>
      <property name="Pool.MaximumActiveConnections" value="10"/>
      <property name="Pool.MaximumIdleConnections" value="5"/>
      <property name="Pool.MaximumCheckoutTime" value="120000"/>
      <property name="Pool.TimeToWait" value="500"/>
      <property name="Pool.PingQuery" value="select 1 from ACCOUNT"/>
      <property name="Pool.PingEnabled" value="false"/>
      <property name="Pool.PingConnectionsOlderThan" value="1"/>
      <property name="Pool.PingConnectionsNotUsedFor" value="1"/>
      <property name="Pool.QuietMode" value="true"/>
    </dataSource>
  </transactionManager>

  <sqlMap resource="bo/mapping/AutoMag.xml"/>
</sqlMapConfig>


transactionManager
元素定义?/span> iBATIS 事务理器?/span> type 可选项包括Q?/span>  

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 resource="bo/mapping/AutoMag2.xml"/>

<sqlMap url=" file:///c:/eclipse/workspace/iBATISTest/src/bo/ AutoMag2.xml "/>
??/font>

你也许已发现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 />
                       
       

Q请注意Q引用、{贴本文应注明原作者:Rosen Jiang 以及出处Q?/font>http://blog.csdn.net/rosenQ?/strong>



扭{乑֝ 2006-03-22 11:25 发表评论
]]>
[转]iBatis DAO入门与进?/title><link>http://www.tkk7.com/wangxq/articles/36805.html</link><dc:creator>扭{乑֝</dc:creator><author>扭{乑֝</author><pubDate>Wed, 22 Mar 2006 03:17:00 GMT</pubDate><guid>http://www.tkk7.com/wangxq/articles/36805.html</guid><wfw:comment>http://www.tkk7.com/wangxq/comments/36805.html</wfw:comment><comments>http://www.tkk7.com/wangxq/articles/36805.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/wangxq/comments/commentRss/36805.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/wangxq/services/trackbacks/36805.html</trackback:ping><description><![CDATA[ <div id="acmuskq" class="center"> <h4>自:<a >http://www.matrix.org.cn/resource/article/44/44058_iBatis+DAO.html</a></h4> <h4>摘要:</h4>q篇文章是关于如何一步一步的在项目中应用iBatis DAO框架的基指导。我们将由如何把SQL Maps一文中的应用实例改为应用DAO框架入手。然后,我们要讨论DAO框架的构造。再下一步,我们x事务理是如何在DAO框架中得到支持的。最后一部分是关于如何徏立自q事务理模块 </div> <div id="koygewy" class="right"> <div id="suiwsiq" class="help"> <b> <span style="FONT-SIZE: 20px">iBatis DAO入门与进?/span> </b> </div> </div> <div id="ucokcww" class="overflow" id="text"> <br /> <center>作者:Sunil Patil</center> <br /> <center>译?<a target="_new">rotter_pal</a></center> <br /> <br /> <br /> <br /> <br /> <span style="COLOR: red">版权声明QQ何获得Matrix授权的网站,转蝲时请<b>务必</b>以超链接形式标明文章原始出处和作者信息及本声?/span> <br />作?Sunil Patil;<a target="_new">rotter_pal</a><br />原文地址:<a target="_new">http://www.onjava.com/pub/a/onjava/2005/08/10/ibatisdao.html</a><br />中文地址:<a target="_new">http://www.matrix.org.cn/resource/article/44/44058_iBatis+DAO.html</a><br />关键词: iBatis DAO<br /><br /><br />在核心J2EE模式中是q样介绍DAO模式的:Z建立一个健壮的J2EE应用Q应该将所有对数据源的讉K操作抽象装在一个公共API中。用E序设计的语a来说Q就是徏立一个接口,接口中定义了此应用程序中会用到的所有事务方法。在q个应用E序中,当需要和数据源进行交互的时候则使用q个接口Qƈ且编写一个单独的cL实现q个接口在逻辑上对应这个特定的数据存储?br /><br />比如考虑在iBatis: SQL Maps中的应用例子。这是一个Struts应用允许对一个关p表执行SELECT, INSERT, UPDATE和DELETE的SQLh。在q个应用中,使用SQL Maps做持l性框架。现在我们要修改q个应用Q将q个关系表储存在一个XML文g中而不是存在关pL据库中,或者用Hibernate来实现SELECThQ而用SQL Map来执行其他请求,因ؓHibernate提供了对高速缓存更好的支持。这L修改很难实现Q或者即使我们能修改而实Cq个功能Q也会是很؜q解决Ҏ?br /><br /><br />对于q类问题更好的解x法是建立一个ContactDAO接口Q在q个接口中定义处理SELECT, INSERT, UPDATE, 和DELETE h的事务方法。然后根据不同的事务逻辑建立不同的类实现各个Ҏ。所以可能会有一个类处理使用SQL Maps同关p表q行交互的情况,而另外一个类处理用XML文g存放关系表而不是关pL据库的情况,{等。在目中,Ҏ实际的需要从不同的ContactDAO中选择相应的实现。这U关p见?Q?br /><br /><img onmouseover="javascript:imgShowTip(this);" style="DISPLAY: inline" onclick="javascript:imgClick(this);" alt="image" src="http://www.matrix.org.cn/resource/upload/article/2005_12_18_224911_SOAyTyFzWZ.gif" onload="javascript:imgLoad(this);" border="0" resized="0" /><br />?. ContactDAO 接口及实?br /><br />iBatis DAO是由ApacheL的开源框枉目,主要目标是ؓ了解册c问题。它允许在工E中以DAO模式为基建立应用。这意味着可以建立一个XML文gQƈ声明XMLContactDAO.java是ContactDAO的实现类Q这个类知道如何从XML文g中读写数据。SQLMapContactDAO则知道如何用SQL Maps作ؓ持箋化框架与关系表进行交互。在工程中,如果向DAO框架提交一个需要XML的ContactDAOhQ框架则会返回一个XMLContactDAO对象。同LDAO框架提供了唯一的接口处理事务管理,q个接口能实C数据的存储方式无兟뀂它同样考虑了底层连接管理细节和初始化存储框架?br /><br />q篇文章是关于如何一步一步的在项目中应用iBatis DAO框架的基指导。我们将由如何把SQL Maps一文中的应用实例改为应用DAO框架入手。然后,我们要讨论DAO框架的构造。再下一步,我们x事务理是如何在DAO框架中得到支持的。最后一部分是关于如何徏立自q事务理模块?br /><br /><b><span style="FONT-SIZE: 16px">CZ应用</span></b><br /><br />首先Q我们将SQL Maps一文中的例子改为应用DAO框架?br />1.        ibatis-dao-2.jar文g复制到WEB-INF/lib目录下?br />2.        在Java源程序的目录里新Z个如下的DAOMap.xml文g<br /><b>清单1Q?/b><br /><pre class="overflow"><daoConfig><br /> <context id="sqlmap"><br />  <transactionManager type="SQLMAP"><br />  <property name="SqlMapConfigResource" value=<br />   "com/sample/contact/dao/sqlmap/SqlMapConfig.xml"/><br />  </transactionManager><br />  <dao interface="com.sample.contact.dao.ContactDAO"<br />   implementation=<br />   "com.sample.contact.dao.sqlmap.SQLMapContactDAO"/><br /> </context><br /></daoConfig></pre><br /><br />DAOMap.xml是发布iBatis DAO框架的配|文件?lt;daoConfig>是根元素Q每?lt;context>元素描述了一U存储机制。在q个例子中只使用了SQL Maps来存储,所以我们这里只有一?lt;context>元素。每U存储机制必d含一?lt;transactionManager>元素Q这个元素描q连接它后面的数据存储所用的理器,q且标记事务的界限。我们将在稍后再讨论transactionManager?br /><br /><context>元素q包括一lDAO用于描述其他的存储管理机制。在q个例子中,我们生成一个用SQL Maps存储的ContactDAOQ所以在配置文g中添加一个ie<dao>标记来定义SQLMapContactDAO?br /><br />3.        建立ContactDAO.java,如下Q?br /><b>清单2Q?/b><br /><pre class="overflow">public interface ContactDAO extends DAO {<br />    public int insertContact(Contact contact);<br />    public int updateContact(Contact contact);<br />    public Contact selectContact(int contactId);<br />    public int deleteContact(int contactId);<br />} </pre>   <br /><br />ContactDAO.java定义了用户和一个关p表q行交互所需要用到的所有事务处理方法。请注意到ContactDAO.java中的所有方法都一个Contact对象作ؓ参数Q这是一个用来携带数据的数据传递对象?br /><br /><br />4.        建立一个SQLMapContactDAO.java文gQ如?br /><b>清单3Q?/b><br /><pre class="overflow">public class SQLMapContactDAO extends<br /> SqlMapDaoTemplate implements ContactDAO {<br />  public SQLMapContactDAO(DaoManager arg0) {<br />      super(arg0);<br />  }<br />  public int deleteContact(int contactId) {<br />    return super.delete("deleteContact",<br />    new Integer(contactId));<br />  }<br />  public int insertContact(Contact contact) {<br />    Integer contactId =(Integer)super.insert<br />      ("insertContact",contact);<br />    return contact.getContactId();<br />  }<br />  public Contact selectContact(int contactId) {<br />    return (Contact)super.queryForObject("getContact",<br />      new Integer(contactId));<br />  }<br />  public int updateContact(Contact contact) {<br />    return super.update("updateContact",contact);<br />  }<br />}</pre><br /><br />SQLMapContactDAO是ContactDAO接口的具体实玎ͼ它用SQL Maps作ؓ存储理机制。注意到我们q没有写M代码来或者初始化SQL MapsQ或得到一个连接,或者在cM标注一个事务的界限。相反,我们l承SqlMapDaoTemplate.javac,它帮我们处理下层的、反复的操作。我们在SQLMapContactDAOcM需要考虑的唯一的事情就是事务处理逻辑?br /><br />5.        修改ContactSelectAction.javacM的execute()ҎQ如下:<br /><b>清单4Q?/b><br /><pre class="overflow">Contact contactForm = (Contact) form;<br />Reader reader=<br />  Resources.getResourceAsReader("DAOMap.xml");<br />DaoManager daoManager =<br />  DaoManagerBuilder.buildDaoManager(reader);<br />ContactDAO contactDAO =<br />  (ContactDAO) daoManager.getDao(<br />ContactDAO.class,"sqlmap");<br /><br />request.setAttribute("contactDetail",<br />  contactDAO.selectContact(<br />    contactForm.getContactId()));</pre><br /><br />最后一步是修改ContactSelectActioncM的execute()ҎQ它用DAO框架。ؓ了初始化DAO框架Q我们需要一个ؓDAOMap.xml 准备一个Reader对象。iBatis框架为我们提供了ҎResources.getResourceAsReader()来读取资源。一旦有了Reader对象来读取DAOMap.xmlQ就能将它们d至DAOManagerBuilder.buildDaoManager()Q返回一个DaoManager实例Q将来用于与DAO框架q行交互。从理论上来_应该在项目启动的时候初始化DAO框架Q在我们q个E序中,可以这个模块放入Struts插g中,但是Z化这个例子,我们初始化模块攑օexecuteҎ中?br /><br />有了DaoManager实例后,可以调用相应的接口和存储实现c??lt;context>元素中的id属性?的getDao()Ҏ。在我们的例子中Q需要一个SQLMapContactDAO的实例,所以以ContactDAO为接口名Uͼ“sqlmap”ؓ存储机制。一旦实CSQLMapContactDAO实例Q就可以在调用其中的事务Ҏ?br /><br />在最后的资源章节中可以下载到q个例子的源码?br /><br /><b><span style="FONT-SIZE: 16px">DAO框架架构</span></b><br /><br />׃有了一个可以运行的CZQ让我们得以_略了解DAO框架是如何运作的。在?表示的顺序图中演CZDAO的工作方式:<br /><br /><img onmouseover="javascript:imgShowTip(this);" style="DISPLAY: inline" onclick="javascript:imgClick(this);" height="450" alt="resized image" src="http://www.matrix.org.cn/resource/upload/article/2005_12_18_224916_OkWdiCStgH.gif" width="553" onload="javascript:imgLoad(this);" border="0" resized="1" /><br />?. DAO序?br /><br />在开始时Q调用DaoManagerBuilder.buildDaoManager()q传入DAOMap.xml来初始化DAO框架。在q个Ҏ中DAO框架会读取DAOMap.xmlq且由此生成相应的DAOManager对象。这个对象包括了Ҏ持的数据存储机制的描q。哪个接口会被实玎ͼ哪个是接口和存储机制l合的实现类Q基本上q是和DAOMap.xml文g相等?Java对象?br /><br />当有了DAOManager对象Q可以从中得到ContactDAO接口的SQL Map实例。DAO框架会返回一个包装了实现cȝDaoProxy对象。在本例子中给SQLMapContactDAOq回一个DaoProxy对象。这个DaoProxy对象允许DAO框架截获调用商业Ҏ。本例中Q当调用 contactDAO.selectContact()ӞDAO框架会截莯个调用ƈ查事务处理是否已l开始执行,如果没有Q它调用事务管理器中的startTransaction()创徏一个新的事务处理调用。如果处理已l开始,DaoProxy对象会调用事务中的SQLMapContactDAO中的selectContact()Ҏ。当selectContact()调用q回的时候,DaoProxy对象截获q回q提交给事务?br /><br />如果不希望事务在Ҏ层上可见Q或者希望在一个事务中调用多个不同的方法,则可在调用ContactDAO中的商业Ҏ前调用daoManager.startTransaction()Q然后在daoManager.startTransaction()执行完以后再提交商业Ҏ?br /><br />那么现在剩下要关心的事情是那个模块负责存储机制的初始化q传递控制给存储机制。在q个例子中,意味着由哪个模块负责将SqlMapConfig.xml的\径传递给SQL Map框架q给它初始化。同h味着哪个模块负责和SQL Maps框架q行实际的交互。DAO框架为每U存储提供了Templatec,在工E中Q可以从q个TemplatecMl承实例c,q只要自qҎ中编写商业事务逻辑。然后将控制传递给q个模板c,它将负责和存储机制的交互。在我们的例子中调用super.queryForObject("getContact",new Integer(contactId))Q意味着SqlMapDaoTemplate负责SQL Maps的初始化和与之交互?br /><br />初始化存储机刉要相关的一些信息,在例子中初始化需要SqlMapConfig.xml的\径,q个文g中包含驱动类的名字、JDBC URL、登陆信息之cȝ信息。这些特定的事务理器需要的信息会在DaoMap.xml文g中作Z个属性元素传递给理器。下一节,我们讨论DAO框架支持哪些事务理器,每个理器需要哪些初始化信息?br /><br /><b><span style="FONT-SIZE: 16px">支持的存储管理机?/span></b><br /><br />DAO框架提供了内|的对一些存储管理机制的支持。ؓ了用其中的一个内|的transactionManagersQ需要做两g事情Q?br />1.在DAOMap.xml中增加一?lt;transactionManager>元素来声明对存储理机制的支持?br />2.在生成DAO实现cȝ时候ؓtransactionManagerl承适当的TemplatecR?br /><br />下面我们要研I内|transactionManagersq找出在应用E序中用如何用它们?br /><br /><b>JDBC</b><br />如果不想使用M存储框架Q不惌己写JDBC代码Q那么JDBC事务理器是很好的选择。如果用JDBC作ؓ存储机制Q则可以使用以下三种q接理之一Q?br /><br />SIMPLEQ如果要使用iBatis'自己的连接池实例Q可以把SIMPLE作ؓDataSource元素的倹{将通常的JDBC属?DriverManagerc, JDBC URLQ等{?传入作ؓProperties。在iBatis在线文中查看更多的q接属性?br /><b>清单5Q?/b><br /><pre class="overflow"><transactionManager type="JDBC"><br /> <property name="DataSource" value="SIMPLE"/><br /> <property name="JDBC.Driver"<br />  value="com.ibm.db2j.jdbc.DB2jDriver"/><br /> <property name="JDBC.ConnectionURL"<br />  value="jdbc:db2j:D:\cloudscape\wpsdb"/><br /> <property name="JDBC.Username"<br />  value="db2admin"/><br /> <property name="JDBC.Password"<br />  value="db2admin"/><br /> <property name="JDBC.DefaultAutoCommit"<br />  value="true" /><br /></transactionManager></pre><br /><br /><br />DBCPQ用Apache DBCP作ؓq接理。请查看DAO在线指导获得如何配置DBCPq接池的信息?br /><br />JNDIQ当要用应用服务器的连接池Q那么要做的是提供连接池的JNDI名,DAO框架则用这个名U获得一个连接?br /><b>清单6Q?/b><br /><pre class="overflow"><transactionManager type="JDBC"><br /> <property name="DataSource" value="JNDI"/><br /> <property name="DBJndiContext"<br />  value="java:comp/env/jdbc/MyDataSource"/><br /></transactionManager></pre><br /><br /><br />然后要徏立一个类l承JdbcDaoTemplate.java来实C务方法借口。在CZ中,我们建立了JDBCContactDAO.java。在事务Ҏ中,可以调用getConnection()向父c请求连接。因为我们没有用Q何存储框Ӟ所以我们只能徏立ƈ执行我们自己的SQLh?br /><b>清单7Q?/b><br /><pre class="overflow">public int updateContact(Contact contact) {<br /> try {<br />  Connection conn = getConnection();<br />  PreparedStatement updateStmt =<br />   conn.prepareStatement("UPDATE DB2ADMIN.CONTACT<br />    SET FIRSTNAME=?,LASTNAME=? WHERE CONTACTID=?");<br />  updateStmt.setString(1, contact.getFirstName());<br />  updateStmt.setString(2, contact.getLastName());<br />  updateStmt.setInt(3, contact.getContactId());<br />  return updateStmt.executeUpdate();<br /> } catch (SQLException ex) {<br />    throw new DaoException(ex);<br /> }<br />}</pre><br /><br />使用JDBC transactionManager的时候,DAO框架会调用Connection 对象中的commit和rollbackҎ来控制事务处理。所以事务会在Connection层被处理Q而不参与全局事务处理?br /><br /><b>JTA</b><br />如果目是J2EE应用Q那么用应用服务器提供的连接池会更有利Q因为它比SIMPLE 或者DBCP q接池有更好的性能。同LQ用J2EE应用QRDBMS是唯一的处理源Q除了RDBMSq需要包含JCA、MQ Server{功能。因Z能在q接层开始和处理事务Q而要特别的在全局事务处理时在一个UserTransaction对象中调用begin()和commit()Ҏ。所以对于这c请求,可以使用JTA 作ؓtransctionManager,既可以向JNDI URL提供数据源连接池Q也可以在里面包含UserTransaction对象?br /><b>清单8Q?/b><br /><pre class="overflow"><transactionManager type="JTA"><br /> <property name="DBJndiContext"<br />  value="java:comp/env/jdbc/MyDataSource"/><br /> <property name="UserTransaction"<br />  value="java:comp/env/UserTransaction"/><br /></transactionManager></pre><br /><br /><b>Hibernate</b><br />因ؓHibernate是很常见的存储框ӞiBatis DAO也提供了对它的支持。ؓ了在目中用HibernateQ像下面那样在DAOMap.xml增加<transactionManager>元素Q?br /><b>清单9Q?/b><br /><pre class="overflow"><transactionManager type="HIBERNATE"><br /> <property name="hibernate.dialect"<br />  value="net.sf.hibernate.dialect.Cloudscape"/><br /> <property name="hibernate.connection.driver_class"<br />  value="com.ibm.db2j.jdbc.DB2jDriver"/><br /> <property name="hibernate.connection.url"<br />  value="jdbc:db2j:D:\cloudscape\wpsdb"/><br /> <property name="hibernate.connection.username"<br />  value="db2admin/><br /> <property name="hibernate.connection.password"<br />  value="db2admin"/><br /> <property name="class.1"<br />  value="com.sample.contact.Contact"/><br /></transactionManager></pre><br /><br /><br />同样的,需要徏立一个DAOcȝ承HibernateDaoTemplate。在q个DAO内,可以通过调用getSession()Ҏ来获得Hibernate Session对象的入口?br /><br /><b>SQL MAP</b><br />h看示?在资源小节中)了解如何在项目中使用SQL Map存储框架的细节?br /><br /><b>外部理</b><br />外部的事务管理器允许事务处理在外部被DAO框架控制。这U行为有利于处理和非关系数据库数据源的交互。下一节,我们讨论如何用DAO框架处理以XML文g作ؓ数据源的情况?br /><br /><br /><b><span style="FONT-SIZE: 16px">部vxml事务Map</span></b><br /><br />你可能也l常遇到q种情况Q需要从xml中读取数据,而不是从RDBMS中读取,假想你正在从事一个银行项目,你ƈ不能够直接接触到银行的数据库Q所有的用户信息暂时都会通过一个XML文g传输l你Q你必须使用q个XML文gq行开发,开发完毕再部v到真正的使用RDBMS的环境中Q?br />q样的话Q你需要做一下改变:<br /><br />1. 在DAOMap.xml 中增加对外部的transactionManager 的支持?br />2. 新徏一个XMLContactDAO.java文g:<br /><b>清单10Q?/b><br /><pre class="overflow">public class XMLContactDAO implements ContactDAO {<br /> public static final String<br />  CONTACTXMLNAME = "c:\\Contact.xml";<br /> public XMLContactDAO(DaoManager manager) {<br />    super(manager);<br /> }<br /> public int insertContact(Contact contact) {<br />  HashMap contactMap = loadChanges();<br />  if (contactMap.get(new Integer<br />    (contact.getContactId())) == null)<br />   contactMap.put(new<br />    Integer(contact.getContactId()), contact);<br />  saveChanges(contactMap);<br />  return contact.getContactId();<br /> }<br /> public Contact selectContact(int contactId) {<br />  HashMap contactMap = loadChanges();<br />  return (Contact) contactMap.get(<br />   new Integer(contactId));<br /> }<br /> public HashMap loadChanges() {<br />  HashMap contactMap = null;<br />  try {<br />   XStream xstream = new XStream(new DomDriver());<br />   xstream.alias("contact", Contact.class);<br />   contactMap =<br />    (HashMap) xstream.fromXML(<br />     new FileReader(CONTACTXMLNAME),HashMap.class);<br />  } catch (FileNotFoundException e) {<br />    e.printStackTrace();<br />    return new HashMap();<br />  }<br />  return contactMap;<br /> }<br /> public void saveChanges(HashMap contactMap) {<br />  try {<br />   XStream xstream = new XStream();<br />   xstream.alias("contact", Contact.class);<br />   xstream.toXML(contactMap,<br />    new FileWriter(CONTACTXMLNAME));<br />   } catch (IOException e) {<br />   e.printStackTrace();<br />  }<br /> }<br />}</pre><br /><br />q个例子中,XMLContactDAO实现了ContactDAO事务接口。因为我们用了一个EXTERNAL事务理器,所以不能用Q何已l存在的TemplatecR在我们的类中,我们使用XStream框架新徏了两个简单的Ҏ——loadChanges()和saveChanges()——实现对XML文g的读写。XStream是一个开源框Ӟ实现一个XML文g看作一个对象来dQ将对象保存为XML文g的功能?br /><br /><b><span style="FONT-SIZE: 16px">l论</span></b><br />当今Q有很多新的存储框架出现。这对于一个程序员既有好处也有坏处。好处是有更多的选择余地。坏处是因ؓ你必MZ个选择Q更p糕的是不得不在目开始的时候就选择一U框Ӟq就意味着你可能不能完全清楚的了解目的需求,或者不能完全确信这U框架是否能完全满目的需求。DAO是一U容易用ƈ且功能强大的框架能够处理存储机制的改变。你在前期作Z付出Q但是它肯定会在最后对你有帮助的?br /><br /><b><span style="FONT-SIZE: 16px">资源</span></b><br />·Matrix-Java开发者社?<a target="_new">http://www.matrix.org.cn</a><br />·onjava.com:<a target="_new">onjava.com</a><br />·q篇文章的示例代码:Q注Q与译文攑օ同一压羃包中Q?<a target="_new">http://www.onjava.com/onjava/2005/08/10/examples/SampleDAO.zip</a><br />·iBatis主页Q?a target="_new">http://ibatis.apache.org/</a><br />·核心 J2EE 模式Q数据存储对象:<a target="_new">http://java.sun.com/blueprints/corej2eepatterns/Patterns/DataAccessObject.html</a><br />·Hibernate主页 (或者CodeZoo: Hibernate) Q?a target="_new">http://www.hibernate.org/</a><br />·使用XStream序列化Java对象Q?a target="_new">http://www.xml.com/pub/a/2004/08/18/xstream.html</a>        <br />·XStream (或?CodeZoo: XStream) Qhttp://xstream.codehaus.org/ ( http://www.codezoo.com/ Qhttp://www.codezoo.com/pub/component/3551 )<br /><br /><b><span style="FONT-SIZE: 16px">关于作?/span></b><br />Sunil Patil对J2EE技术领域的研究过5q时间。他Ҏ兴趣的领域是与对象相关的映射工具、UI框架和Portals<br /><br /><br /><br /></div> <img src ="http://www.tkk7.com/wangxq/aggbug/36805.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/wangxq/" target="_blank">扭{乑֝</a> 2006-03-22 11:17 <a href="http://www.tkk7.com/wangxq/articles/36805.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]ibatis初步http://www.tkk7.com/wangxq/articles/36374.html扭{乑֝扭{乑֝Mon, 20 Mar 2006 08:46:00 GMThttp://www.tkk7.com/wangxq/articles/36374.htmlhttp://www.tkk7.com/wangxq/comments/36374.htmlhttp://www.tkk7.com/wangxq/articles/36374.html#Feedback0http://www.tkk7.com/wangxq/comments/commentRss/36374.htmlhttp://www.tkk7.com/wangxq/services/trackbacks/36374.html阅读全文

扭{乑֝ 2006-03-20 16:46 发表评论
]]>
վ֩ģ壺 þõӰҹ³˿Ƭ| ҹƷһƵ| ֻƬ| jizz18Ƶ| Ļ߹ۿƵ| ޾AA߹ۿSEE| ޹ϵһ| ɫƵѿ| ĻƵѹۿ| һһ| ȾþþƷƵ| ӰԺ߹ۿ| ѿƬ| ԭƵ| ޹AV| ÿµĻ| ޵һվ| Ƶ97| ޳AVƬһ| ĻAëƬ| ۺվɫɫ| Ůҹ24ʽƵ| ۺav뾫Ʒһ| ɫʹɫӰԺ| ۺϹƷһҳ| ŷ˳| þ4438| ŮƵ| ޳a޳av| ĻӰwwwĻ| Ƶ߹ۿ| 2022| | 뾫Ʒ| Ļѵַվ| һ| ޾Һ | ëƬѹۿ| ŷպ޾Ʒ| AV߹ۿ| þҹ޾Ʒ|