springMVC基础上的hibernate与c3p0整合案例

之前我们完成了springMVC的学习和整理,包括spring的入门案例,源代码讲解和实战演练等,现在我们要做的是在我们springMVC框架的基础上新增hibernate的配置,并且使用c3p0作为数据库连接池,以减轻数据库的访问压力。我们所讲的内容不会太追究细节,只是对功能和配置讲解一个流程。之后的文章会对具体细节进行详解。


1、导入jar包

我们应该在之前的jar包基础上新增hibernate与c3p0的jar,但我试了几次都出现冲突的问题,为了节省时间我选择了之前项目的无冲突的jar,比较全,涵盖了ssh等全部的jar

springMVC基础上的hibernate与c3p0整合案例_第1张图片

2、配置sessionFactory

在spring的applicationContext中,我们需要增加对sessionHibernate的配置:


	
		
			
		
		
			
				classpath:hibernate/*.hbm.xml
			
		
		
			
				org.hibernate.dialect.OracleDialect
                true
                true
                10
                30
                org.hibernate.hql.ast.ASTQueryTranslatorFactory
			
		
		
        
	

我们发现这个factory使用的数据源是dataSource,一会我们会对他进行配置,它读取的配置文件是在classpath下的hibernate文件夹下的所有以hbm.xml为结尾的文件。sessionFactory配置完成后,我们需要编写我们的DAO类,封装这个sessionFactory并提供接口方法


3、配置daoHibernatImpl


		
	

这个dao类的源代码如下:

package com.itcast.hibernate.base.dao.impl;

import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import com.itcast.hibernate.base.dao.IDaoHibernat;

/**
 * 
 * @author lvpeng
 * 发现:如果不导入spring-transaction-3.x.RELEASE 
 * 是不能使用HibernateDaoSupport的
 */
public class DaoHibernatImpl extends HibernateDaoSupport implements IDaoHibernat{
	@Override
	public void save(Object entity) {
		try {
			this.getHibernateTemplate().save(entity);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

方法里我们发现我们因为集成了hibernateDaoSupport所以我们可以使用this.getHibernateTemplate().save(entity);


4、配置数据库连接池C3P0

使用c3p0作为数据库连接池是一件很简单的事情,与spring的整合也很容易,但现在我们想要扩展一下我们的连接池,我们希望连接池中的数据库是可以用多种形式来配置的,因为在一个应用中,也许有1个数据源,也许有多个,有的时候我们是通过内部的配置文件来配置,有的时候我们需要在外部,通过浏览器来配置,针对这些的情况,所以我们的c3p0数据库连接池的数据源不能单纯的使用它自己规定的数据源,而是可以动态改变的,这里我们稍微做了一些封装,首先我们来配置我们的dataSource:


	
		
			default
		
	
看一下这个C3P0DataSource类的源代码,我们可以看到:

package com.itcast.hibernate.datasource;

import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Iterator;

import javax.sql.DataSource;

import org.jdom.Document;
import org.jdom.Element;
import org.jdom.xpath.XPath;

import com.itcast.util.DbUtil;
import com.itcast.util.XmlUtil;
import com.mchange.v2.c3p0.ComboPooledDataSource;

public class C3P0DataSource implements DataSource{

	private ComboPooledDataSource dataSource;
	
	public C3P0DataSource(){
		this.dataSource = new ComboPooledDataSource();
	}
	
	public void setDataSourceName(String dataSourceName){
		try {
			Document doc = DataSourceConfig.getInstance().getDocument();
			Element root = doc.getRootElement();
			Element element = (Element) XPath.selectSingleNode(root,"//JdbcDataSource[@name=\'"+dataSourceName+"\']");
			
			//初始化dataSource
			this.dataSource.setDataSourceName(dataSourceName);
			String[] driverInfo = DbUtil.translateDriverInfo(
					DataBaseType.valueOf(XmlUtil.getAttribString(element,"dbType").toUpperCase()),
					XmlUtil.getAttribString(element,"dbUrl"),
					XmlUtil.getAttribString(element,"dbName"));
			
			
			this.dataSource.setDriverClass(driverInfo[0]);
			this.dataSource.setJdbcUrl(driverInfo[1]);
			this.dataSource.setUser(XmlUtil.getAttribString(element,"dbUser"));
			this.dataSource.setPassword(XmlUtil.getAttribString(element,"dbPass"));		
			
			Iterator iter = element.getChildren().iterator();
            Element child;
            String attriValue;
            while (iter.hasNext()) {
                child = (Element) iter.next();
                attriValue = child.getAttribute("name").getValue();
                if (attriValue.equals("minPoolSize")) {
                    this.dataSource.setMinPoolSize(Integer.parseInt(child.getTextTrim()));
                    continue;
                }
                if (attriValue.equals("maxPoolSize")) {
                    this.dataSource.setMaxPoolSize(Integer.parseInt(child.getTextTrim()));
                    continue;
                }
                if (attriValue.equals("initialPoolSize")) {
                    this.dataSource.setInitialPoolSize(Integer.parseInt(child.getTextTrim()));
                    continue;
                }
                if (attriValue.equals("acquireIncrement")) {
                    this.dataSource.setAcquireIncrement(Integer.parseInt(child.getTextTrim()));
                    continue;
                }
                if (attriValue.equals("maxIdleTime")) {
                    this.dataSource.setMaxIdleTime(Integer.parseInt(child.getTextTrim()));
                    continue;
                }
                if (attriValue.equals("idleConnectionTestPeriod")) {
                    this.dataSource.setIdleConnectionTestPeriod(Integer.parseInt(child.getTextTrim()));
                    continue;
                }
                if (attriValue.equals("acquireRetryAttempts")) {
                    this.dataSource.setAcquireRetryAttempts(Integer.parseInt(child.getTextTrim()));
                    continue;
                }
                if (attriValue.equals("automaticTestTable")) {
                    this.dataSource.setAutomaticTestTable(child.getTextTrim());
                    continue;
                }
            }
            System.out.println("----InitialPoolSize:----"+this.dataSource.getInitialPoolSize());
		} catch (Exception e) {
		}
		
		
	}

	
	@Override
	public Connection getConnection() throws SQLException {
		Connection con = this.dataSource.getConnection();
		return con;
	}

它实现了dataSource接口,并且重写了相关的方法getConnection,并且我们还重写了setDataSourceName方法,这个方法会在依赖注入dataSource时将我们在xml配置的properties注入进去,而我们在applicationContext.xml配置的dataSourceName是:


			default

default是什么呢,是一个字符串,字符串我们可以认为是一个默认的数据源名称,我们会通过代码和配置文件的形式,按照dataSourceName去查找该数据源,并且将这个数据源的相关参数加载出来,这个流程可以在setDataSourceName方法中体现出来:

//获取配置文件的xml的document
			Document doc = DataSourceConfig.getInstance().getDocument();
			Element root = doc.getRootElement();
			//获取xml中的以jdbcDataSource为开始的节点
			Element element = (Element) XPath.selectSingleNode(root,"//JdbcDataSource[@name=\'"+dataSourceName+"\']");
			
			//初始化dataSource
			this.dataSource.setDataSourceName(dataSourceName);
			String[] driverInfo = DbUtil.translateDriverInfo(
					DataBaseType.valueOf(XmlUtil.getAttribString(element,"dbType").toUpperCase()),
					XmlUtil.getAttribString(element,"dbUrl"),
					XmlUtil.getAttribString(element,"dbName"));
			
			
			this.dataSource.setDriverClass(driverInfo[0]);
			this.dataSource.setJdbcUrl(driverInfo[1]);
			this.dataSource.setUser(XmlUtil.getAttribString(element,"dbUser"));
			this.dataSource.setPassword(XmlUtil.getAttribString(element,"dbPass"));	

其中使用到了DataSourceConfig这个类,该类的源代码如下:

package com.itcast.hibernate.datasource;

import java.io.FileInputStream;
import java.io.InputStream;

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

import org.jdom.Document;

import com.itcast.util.XmlUtil;

public class DataSourceConfig implements ServletContextListener{
	private static final String DEFAULT_CONFIG_FILE = "/WEB-INF/classes/db-config.xml";
	private static final String LOCAL_CONFIG_FILE = "db-config.xml";
	private static DataSourceConfig sysDSconfig = new DataSourceConfig();
	
	private static ServletContext context;
	public DataSourceConfig(){
	}
	public static DataSourceConfig getInstance(){
		return sysDSconfig;
	}
	
	private Document document;
	public Document getDocument() {
		return document;
	}
	
	public void config(){
		System.out.println(System.getProperty("user.dir"));
		InputStream in = null;
		try {
			if(context != null){
				in = context.getResourceAsStream(DEFAULT_CONFIG_FILE);
			}else{
				in = new FileInputStream("G:/Workplace/spring/springmvc_hibernate/config/"+LOCAL_CONFIG_FILE);
			}
			document = XmlUtil.getDocument(in);
			System.out.println("document:"+document);
			in.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	@Override
	public void contextInitialized(ServletContextEvent sce) {
		context = sce.getServletContext();
		DataSourceConfig.getInstance().config();
	}
	
	@Override
	public void contextDestroyed(ServletContextEvent sce) {
		
	}
}

它是一个监听器,负责在服务启动时就去加载该配置文件,通过这样的机制,我们就可以动态的加载和变换配置文件的目录,如果找不到工程里的配置文件就可以告诉用户需要在外部配置我们的数据源。(代码中为了配置单元测试,我们将配置文件的路径写死了,这里可以优化)


在代码中我们还使用到了DbUtil.translateDriverInfo方法,源代码如下:

package com.itcast.util;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import com.itcast.hibernate.datasource.DataBaseType;


public class DbUtil {

	/**
	 * @return [driverClassName, connectURI]
	 */
	public static String[] translateDriverInfo(DataBaseType dbType, String serverName, String dbName) {
		String[] result = new String[2];
		switch (dbType) {
			case ORACLE:
				result[0] = "oracle.jdbc.driver.OracleDriver";
				if (serverName.indexOf("(") != -1) {
					result[1] = "jdbc:oracle:thin:@" + serverName;
				} else {
					if (serverName.indexOf(":") == -1)
						result[1] = "jdbc:oracle:thin:@" + serverName + ":1521:" + dbName;
					else
						result[1] = "jdbc:oracle:thin:@" + serverName + ":" + dbName;
				}
				break;
			case MYSQL:
				result[0] = "com.mysql.jdbc.Driver";
				result[1] = "jdbc:mysql://" + serverName + "/" + dbName;
				if (dbName.indexOf("?") == -1)
					result[1] = result[1] + "?useUnicode=true&characterEncoding=GBK";
				break;
		}
		return result;
	}

	public static void closeDBObject(ResultSet rs, Statement stat, Connection dbConn) {
		try {
			if (rs != null) {
				rs.close();
				rs = null;
			}
		} catch (SQLException e) {
		}
		try {
			if (stat != null) {
				stat.close();
				stat = null;
			}
		} catch (SQLException e) {
		}
		try {
			if (dbConn != null) {
				dbConn.close();
				dbConn = null;
			}
		} catch (SQLException e) {
		}
	}

}

它的主要功能是帮助我们找到数据源对应的驱动信息等。而我们的数据源配置文件的内容是:



	
	  
	    
	  	3
	  	
	  	5
	  	
	  	3
	  	
	  	2
	  	
	    3600
	    
	    60
	    
	    30
	    
	    S_TEST
	  
	

而如果我们想采用外部配置的方式,也需要提供这些基本的配置参数,来生成我们的目标配置文件,以供监听器发现。


5、增加业务DAO层和user.hbm.xml

package com.itcast.sm.dao.impl;

import org.springframework.beans.factory.annotation.Autowired;

import com.itcast.hibernate.base.dao.IDaoHibernat;
import com.itcast.spring.mvc.service.model.User;

public class UserDaoImpl implements UserDao{

	@Autowired
	private IDaoHibernat daoHibernat;
	
	@Override
	public void SaveUser(User user) {
		this.daoHibernat.save(user);
	}
}

这个类负责saveUser,将daoHibernate注入到该类中作为属性。直接调用save方法就能完成对user的insert,但我们需要配置对应的hbm.xml:

  
  
  
      
		
		
		
		
      
 


6、配置bean




	
	

7、修改web.xml



	
  
  
  	com.itcast.hibernate.datasource.DataSourceConfig
  
  
  
  	org.springframework.web.context.ContextLoaderListener
  
  
  
  
  	spring
  	
  		org.springframework.web.servlet.DispatcherServlet
  	
  	  
        contextConfigLocation  
        /WEB-INF/applicationContext.xml  
      
  
  
  
  
  	spring
  	*.html
  

  
  


8、工程目录

springMVC基础上的hibernate与c3p0整合案例_第2张图片

你可能感兴趣的:(Spring)