论坛首页 Java企业应用论坛

如何在Hibernate中使用池?

浏览 4477 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2003-12-02  
文档上说,只要设置hibernate.dbcp.*相应的参数,hibernate会自动使用DBCP作为数据库连接池,我也是这样的配置的,如下所示:

<hibernate-configuration>
  <session-factory>
    <property name="show_sql">true</property>
    <property name="use_outer_join">true</property>
    <property name="hibernate.dialect">net.sf.hibernate.dialect.OracleDialect</property>
    <property name="hibernate.connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
    <property name="hibernate.connection.url">jdbc:oracle:thin:@131.1.2.237:1521:orcl</property>
    <property name="hibernate.connection.username">hotye1</property>
    <property name="hibernate.connection.password">hotye1</property>
    <property name="hibernate.use_outer_join">true</property>
    
    <property name="hibernate.dbcp.whenExhaustedAction">1</property>
    <property name="hibernate.dbcp.maxIdle">60</property>
    <property name="hibernate.dbcp.maxActive">60</property>
    <property name="hibernate.dbcp.maxWait">120000</property>
    <property name="hibernate.dbcp.ps.maxActive">100</property>
    <property name="hibernate.dbcp.ps.whenExhaustedAction">1</property>
    <property name="hibernate.dbcp.ps.maxWait">120000</property>
    <property name="hibernate.dbcp.ps.maxIdle">100</property>
    
    <!-- Mapping files -->
  </session-factory>
</hibernate-configuration>


我的应用是需要从数据库中的一个序列(我使用的是Oracle)中取出一个唯一的序列号,由于此序列不太好和别的表结合在一起,所以在使用中我是从Session中取出jdbc有Connection来使用的.但在运行中速度非常慢,经常在秒一级,而且我在程序中使用了ThreadLocal来保存一个当前线程使用的连接,在我的测试程序运行完成后,虚拟机不退出,不知道为什么?

另外,能否在运行时查看到Hibernate使用的数据库连接池的情况?
   发表时间:2003-12-02  
另外我对Session进行了一个非常简单的封装,如下:

package test;

import java.io.Serializable;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

import net.sf.hibernate.HibernateException;
import net.sf.hibernate.Session;
import net.sf.hibernate.Transaction;
import net.sf.hibernate.type.Type;

/**
 * <p>对Connection接口的Hibernate实现.它封装了Hibernate的Session对象和Transaction
 * 相关的处理.
 */
public class ConnectionImpl
    implements Connection {
    //
    //成员属性
    //
    /**
     * <p>封装的Hibernate使用的Session对象,通过此对象完成对数据库的操作
     */
    private Session session = null;
    /**
     * <p>由Session生成的交易事务管理类,通过它可以完成对事务的控制.
     */
    private Transaction transaction = null;

    //
    //构造方法
    //
    public ConnectionImpl(Session session); {
        this.session = session;
    }

    public void begin();
        throws DBException {
        try {
            transaction = session.beginTransaction();;
        } catch (HibernateException ex); {
            throw new DBException("初始化事务对象错误", ex);;
        }
    }

    public void commit();
        throws DBException {
        if (transaction == null); {
            throw new DBException("事务对象不存在,不能进行提交!");;
        }

        try {
            transaction.commit();;
        } catch (HibernateException ex); {
            throw new DBException("事务提交时出现错误", ex);;
        }
    }

    public void rollback();
        throws DBException {
        if (transaction == null); {
            throw new DBException("事务对象不存在,不能进行回滚!");;
        }

        try {
            transaction.rollback();;
        } catch (HibernateException ex); {
            throw new DBException("事务回滚时出现错误", ex);;
        }
    }

    public void flush();
        throws DBException {
        try {
            session.flush();;
        } catch (HibernateException ex); {
            throw new DBException(ex);;
        }
    }

    public java.sql.Connection close();
        throws DBException {
        try {
            java.sql.Connection conn = session.close();;
            session = null;
            transaction = null;
            return conn;
        } catch (HibernateException ex); {
            throw new DBException(ex);;
        }
    }

    public java.sql.Connection connection();
        throws DBException {
        try {
            return session.connection();;
        } catch (HibernateException ex); {
            throw new DBException(ex);;
        }
    }

    public java.sql.Connection disconnect();
        throws DBException {
        try {
            return session.disconnect();;
        } catch (HibernateException ex); {
            throw new DBException(ex);;
        }
    }

    public void reconnect();
        throws DBException {
        try {
            session.reconnect();;
        } catch (HibernateException ex); {
            throw new DBException(ex);;
        }
    }

    public boolean isOpen(); {
        return session.isOpen();;
    }

    public boolean isConnected(); {
        return session.isConnected();;
    }

    public Object load(Class theClass, Serializable id);
        throws DBException {
        try {
            return session.load(theClass, id);;
        } catch (HibernateException ex); {
            throw new DBException(ex);;
        }
    }

    public void load(Object object, Serializable id);
        throws DBException {
        try {
            session.load(object, id);;
        } catch (HibernateException ex); {
            throw new DBException(ex);;
        }
    }

    public Serializable save(Object object);
        throws DBException {
        try {
            return session.save(object);;
        } catch (HibernateException ex); {
            throw new DBException(ex);;
        }
    }

    public void save(Object object, Serializable id);
        throws DBException {
        try {
            session.save(object, id);;
        } catch (HibernateException ex); {
            throw new DBException(ex);;
        }
    }

    public void saveOrUpdate(Object object);
        throws DBException {
        try {
            session.save(object);;
        } catch (HibernateException ex); {
            throw new DBException(ex);;
        }
    }

    public void update(Object object);
        throws DBException {
        try {
            session.update(object);;
        } catch (HibernateException ex); {
            throw new DBException(ex);;
        }
    }

    public void update(Object object, Serializable id);
        throws DBException {
        try {
            session.update(object, id);;
        } catch (HibernateException ex); {
            throw new DBException(ex);;
        }
    }

    public void delete(Object object);
        throws DBException {
        try {
            session.delete(object);;
        } catch (HibernateException ex); {
            throw new DBException(ex);;
        }
    }

    public List find(String query);
        throws DBException {
        try {
            return session.find(query);;
        } catch (HibernateException ex); {
            throw new DBException(ex);;
        }
    }

    public List find(String query, Object value, Type type);
        throws DBException {
        try {
            return session.find(query, value, type);;
        } catch (HibernateException ex); {
            throw new DBException(ex);;
        }
    }

    public List find(String query, Object[] values, Type[] types);
        throws DBException {
        try {
            return session.find(query, values, types);;
        } catch (HibernateException ex); {
            throw new DBException(ex);;
        }
    }

    public Iterator iterate(String query);
        throws DBException {
        try {
            return session.iterate(query);;
        } catch (HibernateException ex); {
            throw new DBException(ex);;
        }
    }

    public Iterator iterate(String query, Object value, Type type);
        throws DBException {
        try {
            return session.iterate(query, value, type);;
        } catch (HibernateException ex); {
            throw new DBException(ex);;
        }
    }

    public Iterator iterate(String query, Object[] values, Type[] types);
        throws DBException {
        try {
            return session.iterate(query, values, types);;
        } catch (HibernateException ex); {
            throw new DBException(ex);;
        }
    }

    public Collection filter(Object collection, String filter);
        throws DBException {
        try {
            return session.filter(collection, filter);;
        } catch (HibernateException ex); {
            throw new DBException(ex);;
        }
    }

    public Collection filter(Object collection, String filter, Object value,
                             Type type);
        throws DBException {
        try {
            return session.filter(collection, filter, value, type);;
        } catch (HibernateException ex); {
            throw new DBException(ex);;
        }
    }

    public Collection filter(Object collection, String filter, Object[] values,
                             Type[] types);
        throws DBException {
        try {
            return session.filter(collection, filter, values, types);;
        } catch (HibernateException ex); {
            throw new DBException(ex);;
        }
    }

    public int delete(String query);
        throws DBException {
        try {
            return session.delete(query);;
        } catch (HibernateException ex); {
            throw new DBException(ex);;
        }
    }

    public int delete(String query, Object value, Type type);
        throws DBException {
        try {
            return session.delete(query, value, type);;
        } catch (HibernateException ex); {
            throw new DBException(ex);;
        }
    }

    public int delete(String query, Object[] values, Type[] types);
        throws DBException {
        try {
            return session.delete(query, values, types);;
        } catch (HibernateException ex); {
            throw new DBException(ex);;
        }
    }

    public Object get(Class clazz, Serializable id);
        throws DBException {
        try {
            return session.get(clazz, id);;
        } catch(HibernateException ex); {
            throw new DBException(ex);;
        }
    }
}
0 请登录后投票
   发表时间:2003-12-02  
通过ThreadLocal对Session进行管理的类,由于在一个线程中可能会和多个数据库服务器进行连接,所以在这个实现中,在ThreadLocal中保存的是一个线程对应的所有的Connection信息,在使用中应用程序需要通过一个数据库服务的名称取得相应的数据库连接进行访问.

package test;

import java.io.File;
import java.util.*;

import net.sf.hibernate.HibernateException;
import net.sf.hibernate.Session;
import net.sf.hibernate.SessionFactory;
import net.sf.hibernate.cfg.Configuration;
import net.sf.hibernate.tool.hbm2ddl.SchemaExport;

import test.Connection;
import test.ConnectionImpl;
import test.DBException;
import test.InitException;

/**
 * <p>对test.Connection进行管理的工厂类,在此类中可以生成对数据库
 * 操作的Connection类的对象.
 *
 * <p>在具体的处理中需要考虑以下几方面的情况:
 * <ul><li>1.系统支持多个数据库服务器,所以在生成Connection中需要指明使用的数据
 *           库服务器的名称</li>
 *     <li>2.不同的数据库服务器对应于不同的配置信息,所以在系统中有几个数据库服
 *           务器就对应有几个配置文件.</li>
 *     <li>3.为了保存在一个线程中不会使用多个Connection,在实际使用中会使用
 *           ThreadLocal的方式保存本线程相关的连接信息</li>
 *
 * <p>对于每个线程来说,它可能会对多个数据库服务器进行操作,由此时在ThreadLcoal
 * 变量中保存的是对于不同的数据库服务器生成的Connection对象.
 */
public class ConnectionUtils {
    //
    //成员属性
    //
    /**
     * <p>保存与该应用相应的数据库服务器的配置文件信息.
     */
    private static Hashtable cfgfiles = new Hashtable();;
    /**
     * <p>保存与该应用相关的数据库服务器的Hibernate配置对象信息
     */
    private static Hashtable configurations = new Hashtable();;
    /**
     * <p>保存与该项应用相关的数据库服务器的SessionFactory对象信息.
     */
    private static Hashtable factories = new Hashtable();;
    /**
     * <p>保存与线程相关的Connection信息,在每个ThreadLocal中保存的是一个Hashtable,
     * 保存了在当前的线程中使用到的几个不同的数据库服务器操作使用的Connection实例,
     * 但对于每个数据库服务器,在一个线程中只有一个Connection实例
     */
    private static ThreadLocal conn = new ThreadLocal();;

    public static void init(Properties props); throws InitException {
        StringBuffer debugmsg = new StringBuffer();;

        //从props中读取所有与数据库相关的参数信息,保存的应当是文件名,数据库配
        //置文件默认都保存在conf/db目录下
        //使用信息来初始化cfgfiles实例
        Enumeration enum = props.keys();;
        while( enum.hasMoreElements(); ); {
            String key = (String);enum.nextElement();;

            if( key.startsWith("test.db"); && key.endsWith("config"); ); {
                String cfgfile = props.getProperty(key);;
                key = key.substring(0, key.indexOf("config"); - 1);;
                debugmsg.append("[");.append(key);.append("]");;
                cfgfiles.put(key, cfgfile);;

                File file = new File(cfgfile);;
                if( !file.exists(); ); {
                    throw new InitException(cfgfile + "配置文件不存在.");;
                }

                //初始化configurations
                Configuration conf = null;
                try {
                    conf = new Configuration();.configure(file);;
                    configurations.put(key, conf);;
                } catch(Exception ex); {
                    ex.printStackTrace();;
                    throw new InitException("初始化数据库配置文件错误[" + key + "]");;
                }

                //初始化factories
                try {
                    SessionFactory factory = conf.buildSessionFactory();;
                    factories.put(key, factory);;
                } catch(Exception ex); {
                    ex.printStackTrace();;
                    throw new InitException("生成数据库工厂错误.[" + key + "]");;
                }
            }
        }

        System.out.println("[Database         ]" + debugmsg.toString();
                           + "配置完成.");;
    }

    /**
     * <p>取得一个数据库操作的连接对象,使用此连接对象可以完成对数据库的操作.
     * <p>所有的连接对象按线程的方式保存,如果某线程已经在使用一个数据库上连接,在
     * 本线程的另外一个地方如果需要对相同的数据库进行操作的话,不需要建立新的连接,
     * 使用已经存在的即可.而如果没有可用的已经建立的数据库连接,则会新建一个与该
     * 线程相关的连接对象.
     */
    public static Connection currentConnection(String dbname);
        throws DBException {

        Connection connection = null;

        Hashtable conns = (Hashtable);conn.get();;
        if( conns == null ); {
            conns = new Hashtable();;  //新生成一个列表
        }

        //表示还没有建立dbname对应的Connection,则此需要需要新建一个
        if( !conns.containsKey(dbname); ); {
            try {
                //取出dbname对应的工厂类
                SessionFactory factory = (SessionFactory);factories.get(dbname);;
                //建立一个新Hibernate的Session对象
                Session session = factory.openSession();;
                //将Session对象封装在Connection对象中
                connection = new ConnectionImpl(session);;
                //最后将connection对象保存在列表以及ThreadLocal中
                conns.put(dbname, connection);;
                conn.set(conns);;
            } catch (HibernateException ex); {
                throw new DBException("生成新的连接时出现错误:", ex);;
            }
        } else {
            //从列表中取出原来使用过后Connection对象
            connection = (Connection);conns.get(dbname);;

            if( !connection.isConnected(); ); {
                connection.reconnect();;
            }
        }

        return connection;
    }

    /**
     * <p>关闭本线程使用的所有数据库库连接.
     */
    public static void closeConnection(); throws DBException {
        Hashtable conns = (Hashtable);conn.get();;

        //将ThreadLcoal中保存的所有与本线程相关的实例进行清除
        conn.set(null);;

        if( conns != null ); {
            Iterator iter = conns.values();.iterator();;
            //关闭所有相关的数据库连接
            while( iter.hasNext(); ); {
                Connection connection = (Connection);iter.next();;

                if( connection != null ); {
                    con = connection.close();;
                }
            }
        }
    }

    /**
     * <p>停止所有的数据库具体的连接.此方法会将本线程对应的所有Connection对象中
     * 封装的JDBC连接关闭.
     */
    public static void disconnect(); throws DBException {
        Hashtable conns = (Hashtable);conn.get();;
        if( conns != null ); {
            Iterator iter = conns.values();.iterator();;
            //关闭所有相关的数据库具体的连接
            while( iter.hasNext(); ); {
                Connection connection = (Connection);iter.next();;

                if( connection != null ); {
                    connection.disconnect();;
                }
            }
        }
    }
}
0 请登录后投票
   发表时间:2003-12-02  
以下是我封装的一个DAO对象(省略了DAO接口的类定义),其中测试程序是在多线程并发的情况下取得一个序列号,T_System表中只有一条记录,S_SystemTrace一个Sequence.

package test.dao.impl;

import java.sql.ResultSet;
import java.sql.Statement;

import test.Connection;
import test.DAOFactory;
import test.SystemDAO;
import test.System;
import test.ConnectionUtils;
import test.SystemException;
import java.util.Properties;

/**
 * <p>与系统相关的操作的实现.
 */
public class SystemDAOImpl
    implements SystemDAO {

    private static final String SYSTEM_DBNAME = "test.db.main";

    /**
     *System类是我内部的一个数据类.
     */
    public System getSystemMsg(); {
        Connection conn = null;
        java.sql.Connection con = null;
        Statement stmt = null;
        ResultSet rs = null;
        try {
            long t0 = java.lang.System.currentTimeMillis();;

            //取得一个对数据库操作的数据库连接信息
            conn = ConnectionUtils.currentConnection(SYSTEM_DBNAME);;

            long t1 = java.lang.System.currentTimeMillis();;

            //从数据库中读取记录信息
            con = conn.connection();;

            long t2 = java.lang.System.currentTimeMillis();;

            stmt = con.createStatement();;
            rs = stmt.executeQuery(
                "SELECT S_SystemTrace.nextval, Status FROM T_System");;

            int status = System.STATUS_STOPPED;
            long trace = 0;
            if (rs.next();); {
                trace = rs.getLong(1);;
                status = rs.getInt(2);;
            }

            long t3 = java.lang.System.currentTimeMillis();;

            System system = new System();;
            system.setStatus(status);;
            system.setTrace(traceno);;

            long t4 = java.lang.System.currentTimeMillis();;
            StringBuffer sb = new StringBuffer();;
            sb.append("[1]");.append((t1-t0););.append(" ");;
            sb.append("[2]");.append((t2-t1););.append(" ");;
            sb.append("[3]");.append((t3-t2););.append(" ");;
            sb.append("[4]");.append((t4-t3););;
            java.lang.System.out.println("TRACE:[" + traceno + "]" + sb.toString(););;

            return system;
        } catch (Exception ex); {
            return null;
        } finally {
            try {
                stmt.close();;
                stmt = null;
            } catch (SQLException ex2); {
            }

            try {
                rs.close();;
                rs = null;
            } catch (SQLException ex3); {
            }

            long starttime = java.lang.System.currentTimeMillis();;

            try {
                ConnectionUtils.closeConnection();;
            } catch (DBException ex1); {
            }
        }
    }

    public static void main(String[] args);
        throws Exception {
        int count = 100;

        Properties props = new Properties();;
        props.setProperty("test.db.main.config", "hibernate.cfg.xml");;
        ConnectionUtils.init(props);;

        TestTrace[] tt = new TestTrace[count];
        for (int i = 0; i < count; i++); {
            tt[i] = new TestTrace();;
        }

        java.lang.System.out.println("Start run...");;

        for (int i = 0; i < count; i++); {
            tt[i].start();;
        }
    }
}

class TestTrace extends Thread {
    public void run(); {
        SystemDAO dao = (SystemDAO);DAOFactory.getDAO(SystemDAO.class);;
        long starttime = java.lang.System.currentTimeMillis();;
        System system = dao.getSystemMsg();;
        long endtime = java.lang.System.currentTimeMillis();;
        java.lang.System.out.println( "[" + system.getTrace(); + "]---" + (endtime - starttime););;
    }
}


其中,在getSystemMsg方法中的t2和和之间的时间差有几秒钟.

还请各位看看我这样做哪有问题?谢谢谢谢!
0 请登录后投票
   发表时间:2003-12-02  
对不起,关于池的问题是我自己的错.因为原来我的数据库装在Linux上,所以可以在人自己的电脑上可能通过1521查询所有相关的数据库连接的情况.最近将数据库转移到了window 2003 server上,没有想到在查询时不能使用1521来查了,因为在netstat -na时所有的数据库连接不会使用1521端口.

不过还是问题是,就是象我上面那样做,为什么对数据库的操作特别慢呢?

谢谢!
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics