﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-礼必风-随笔分类-数据库技术杂谈</title><link>http://www.blogjava.net/bily/category/17268.html</link><description>IT不等于it</description><language>zh-cn</language><lastBuildDate>Sat, 03 Mar 2007 03:40:11 GMT</lastBuildDate><pubDate>Sat, 03 Mar 2007 03:40:11 GMT</pubDate><ttl>60</ttl><item><title>JAVA中数据库操作的各种方式与设计模式的应用</title><link>http://www.blogjava.net/bily/archive/2006/11/15/81346.html</link><dc:creator>礼必风</dc:creator><author>礼必风</author><pubDate>Wed, 15 Nov 2006 10:16:00 GMT</pubDate><guid>http://www.blogjava.net/bily/archive/2006/11/15/81346.html</guid><wfw:comment>http://www.blogjava.net/bily/comments/81346.html</wfw:comment><comments>http://www.blogjava.net/bily/archive/2006/11/15/81346.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/bily/comments/commentRss/81346.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/bily/services/trackbacks/81346.html</trackback:ping><description><![CDATA[
		<p>1.   在业务层使用JDBC直接操作数据库－最简单，最直接的操作紧耦合方式，黑暗中的痛苦<br /> <br />1）数据库url,username,password写死在代码中<br />    Class.forName("oracle.jdbc.driver.OracleDriver").newInstance(); <br />    String url="jdbc:oracle:thin:@localhost:1521:orcl"; <br />    String user="scott"; <br />    String password="tiger"; <br />    Connection conn= DriverManager.getConnection(url,user,password);  <br />    Statement stmt=conn.createStatement(<br />ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE); <br />    String sql="select * from test"; <br />    ResultSet rs=stmt.executeQuery(sql); <br /> <br />2）采用Facade和Command模式，使用DBUtil类封装JDBC操作；<br />      数据库url,username,password可以放在配置文件中（如xml,properties,ini等）。<br />      这种方法在小程序中应用较多。<br /> <br />2.DAO(Data Accessor Object)模式－松耦合的开始<br /><br />DAO = data + accessor + domain object<br /> <br />例如User类－domain object (javabean)<br />        UserDAO类－accessor ，提供的方法getUser(int id)，save(User user)内包含了JDBC操作<br />在业务逻辑中使用这两个类来完成数据操作。<br /> <br />        使用Factory模式可以方便不同数据库连接之间的移植。<br /> <br />3.数据库资源管理模式<br /><br />3.1 数据库连接池技术<br /><br />资源重用，避免频繁创建，释放连接引起大大量性能开销；<br />更快的系统响应速度；<br /> <br />通过实现JDBC的部分资源对象接口( Connection, Statement, ResultSet )，可以使用Decorator设计模式分别产生三种逻辑资源对象: PooledConnection, PooledStatement和 PooledResultSet。<br /> <br />        一个最简单地数据库连接池实现：<br />public class ConnectionPool {<br /> <br />       private static Vector pools;<br />       private final int POOL_MAXSIZE = 25;<br />       /**<br />        * 获取数据库连接<br />        * 如果当前池中有可用连接，则将池中最后一个返回；若没有，则创建一个新的返回<br />        */<br />       public synchronized Connection getConnection() {<br />              Connection conn = null;<br />              if (pools == null) {<br />                     pools = new Vector();<br />              }<br /> <br />              if (pools.isEmpty()) {<br />                     conn = createConnection();<br />              } else {<br />                     int last_idx = pools.size() - 1;<br />                     conn = (Connection) pools.get(last_idx);<br />                     pools.remove(last_idx);<br />              }<br /> <br />              return conn;<br />       }<br /> <br />       /**<br />        * 将使用完毕的数据库连接放回池中<br />        * 若池中连接已经超过阈值，则关闭该连接；否则放回池中下次再使用<br />        */<br />       public synchronized void releaseConnection(Connection conn) {<br />              if (pools.size() &gt;= POOL_MAXSIZE)<br />                     try {<br />                            conn.close();<br />                     } catch (SQLException e) {<br />                            // TODO自动生成 catch 块<br />                            e.printStackTrace();<br />                     } else<br />                     pools.add(conn);<br />       }<br /> <br />       public static Connection createConnection() {<br />              Connection conn = null;<br />              try {<br />                     Class.forName("oracle.jdbc.driver.OracleDriver").newInstance();<br />                     String url = "jdbc:oracle:thin:@localhost:1521:orcl";<br />                     String user = "scott";<br />                     String password = "tiger";<br />                     conn = DriverManager.getConnection(url, user, password);<br />              } catch (InstantiationException e) {<br />                     // TODO自动生成 catch 块<br />                     e.printStackTrace();<br />              } catch (IllegalAccessException e) {<br />                     // TODO自动生成 catch 块<br />                     e.printStackTrace();<br />              } catch (ClassNotFoundException e) {<br />                     // TODO自动生成 catch 块<br />                     e.printStackTrace();<br />              } catch (SQLException e) {<br />                     // TODO自动生成 catch 块<br />                     e.printStackTrace();<br />              }<br />              return conn;<br />       }<br />}<br /> <br />        注意：利用getConnection()方法得到的Connection，程序员很习惯地调用conn.close()方法关闭了数据库连接，那么上述的数据库连接机制便形同虚设。   在调用conn.close()方法方法时如何调用releaseConnection()方法？这是关键。这里，我们使用Proxy模式和java反射机制。<br /> <br />public synchronized Connection getConnection() {<br />              Connection conn = null;<br />              if (pools == null) {<br />                     pools = new Vector();<br />              }<br /> <br />              if (pools.isEmpty()) {<br />                     conn = createConnection();<br />              } else {<br />                     int last_idx = pools.size() - 1;<br />                     conn = (Connection) pools.get(last_idx);<br />                     pools.remove(last_idx);<br />              }<br />        <br />        ConnectionHandler handler=new ConnectionHandler(this);<br />              return handler.bind(con);<br />       }<br /> <br />public class ConnectionHandler implements InvocationHandler {<br />     private Connection conn;<br />     private ConnectionPool pool;<br />     <br />     public ConnectionHandler(ConnectionPool pool){<br />            this.pool=pool;<br />     }<br />     <br />     /**<br />      * 将动态代理绑定到指定Connection<br />      * @param conn<br />      * @return<br />      */<br />     public Connection bind(Connection conn){<br />            this.conn=conn;<br />Connection proxyConn=(Connection)Proxy.newProxyInstance(<br />conn.getClass().getClassLoader(), conn.getClass().getInterfaces(),this);<br />          return proxyConn;<br />     }<br />     <br />       /* （非 Javadoc）<br />        * @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object, java.lang.reflect.Method, java.lang.Object[])<br />        */<br />       public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {<br />              // TODO自动生成方法存根<br />              Object obj=null;<br />              if("close".equals(method.getName())){<br />                     this.pool.releaseConnection(this.conn);<br />              }<br />              else{<br />                     obj=method.invoke(this.conn, args);<br />              }<br />              <br />              return obj;<br />       }<br />}<br /> <br />      在实际项目中，并不需要你来从头开始来设计数据库连接池机制，现在成熟的开源项目，如C3P0,dbcp,Proxool等提供了良好的实现。一般推荐使用Apache dbcp，基本使用实例：<br />DataSource ds = null;<br />   try{<br />     Context initCtx = new InitialContext();<br />     Context envCtx = (Context) initCtx.lookup("java:comp/env");<br />     ds = (DataSource)envCtx.lookup("jdbc/myoracle");<br />        if(ds!=null){<br />                out.println("Connection is OK!");<br />                Connection cn=ds.getConnection();<br />                if(cn!=null){<br />                        out.println("cn is Ok!");<br />                Statement stmt = cn.createStatement();<br />                 ResultSet rst = stmt.executeQuery("select * from BOOK");<br />                out.println("&lt;p&gt;rst is Ok!" + rst.next());<br />                while(rst.next()){<br />                        out.println("&lt;P&gt;BOOK_CODE:" + rst.getString(1));<br />                  }<br />                        cn.close();<br />                }else{<br />                        out.println("rst Fail!");<br />                }<br />        }<br />        else <br />                out.println("Fail!");<br />           }catch(Exception ne){ out.println(ne);<br />         }</p>
		<p>3.2 Statement Pool<br /><br />        普通预编译代码：<br />String strSQL=”select name from items where id=?”;<br />PreparedStatement ps=conn.prepareStatement(strSQL);<br />ps.setString(1, “2”);<br />ResultSet rs=ps.executeQuery();<br /> <br />        但是PreparedStatement 是与特定的Connection关联的，一旦Connection关闭，则相关的PreparedStatement 也会关闭。<br />        为了创建PreparedStatement 缓冲池，可以在invoke方法中通过sql语句判断池中还有没有可用实例。<br /> <br />4. 持久层设计与O/R mapping 技术<br /><br />1）Hernate：适合对新产品的开发，进行封闭化的设计<br />Hibernate 2003年被Jboss接管，通过把java pojo对象映射到数据库的table中，采用了xml/javareflection技术等。3.0提供了对存储过程和手写sql的支持，本身提供了hql语言。<br />        开发所需要的文件：<br />hibernate配置文件： hibernate.cfg.xml 或 hibernate.properties<br />hibernate 映射文件： a.hbm.xml<br />pojo类源文件： a.java　　<br /> <br />        导出表与表之间的关系：<br />a. 从java对象到hbm文件：xdoclet <br />b. 从hbm文件到java对象：hibernate extension <br />c. 从数据库到hbm文件：middlegen <br />d. 从hbm文件到数据库：SchemaExport<br /> <br />2）Iatis ：适合对遗留系统的改造和对既有数据库的复用，有很强的灵活性<br />3）Apache OJB：优势在于对标准的全面支持<br />4）EJB：适合集群服务器，其性能也不象某些人所诟病的那么差劲<br />5）JDO (java data object)<br />        设置一个Properties对象，从而获取一个JDO的PersistenceManagerFactory（相当于JDBC连接池中的DataSource），进而获得一个PersistenceManager对象（相当于JDBC中的Connection对象），之后，你可以用这个PersistenceManager对象来增加、更新、删除、查询对象。<br />        JDOQL是JDO的查询语言；它有点象SQL，但却是依照Java的语法的。<br /> <br />5. 基于开源框架的Struts+Spring+Hibernate实现方案<br /><br />        示例：这是一个3层架构的web 程序，通过一个Action 来调用业务代理，再通过它来回调 DAO类。下面的流程图表示了MyUsers是如何工作的。数字表明了流程的先后顺序，从web层(UserAction)到中间层(UserManager)，再到数据层(UserDAO)，然后返回。<br />Spring是AOP, UserManager和UserDAO都是接口.<br />1) web层(UserAction) ：调用中间层的接口方法，将UserManager作为属性注入。<br />        采用流行的Struts框架，虽然有很多人不屑一顾，但是这项技术在业界用的比较普遍，能满足基本的功能，可以减少培训学习成本。<br />2) 中间层(UserManager)：将UserDAO作为属性注入，其实现主要是调用数据层接口的一些方法；它处于事务控制中。<br />        采用Spring框架实现，IOC与AOP是它的代名词，功能齐全，非常棒的一个架构。<br />3) 数据层(UserDAO)：实现类继承HibernateDaoSupport类，在该类中可以调用getHibernateTemplate()的一些方法执行具体的数据操作。<br />        采用Hibernate做O/R mapping，从种种迹象可以看出，Hibernate就是EJB3.0的beta版。</p>
<img src ="http://www.blogjava.net/bily/aggbug/81346.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/bily/" target="_blank">礼必风</a> 2006-11-15 18:16 <a href="http://www.blogjava.net/bily/archive/2006/11/15/81346.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>