mybatis 多数据源 配置实例

 简介:本案例是使用使用mybatis来增删改查的一个实例, 它的数据源是多个的,可以随意切换,这在数据量比较大的项目中还是经常要用到的哦。 简单的说有点意思,哈哈。最后测试由于刚好有httpclients的代码就之间拿过来用了。

操作的实体类:

public class User {
	
	private int id;
	private String username;
	private String password;
	private String salt;

        ////////////get/set方法省略/////////////
}

数据属性配置文件mybatis-config-datasource.properties

使用mysql数据库,其中%DBNAME%会根据实际情况替换实际连接的数据库。

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/%DBNAME%
username=root
password=123456

数据库连接配置文件:mybatis-config.xml

使用了C3P0连接池

红色字体部分(最后三行)配置了实体操作配置文件路径

<?xml version="1.0" encoding="UTF-8" ?>   
<!DOCTYPE configuration        
    PUBLIC "-//ibatis.apache.org//DTD Config 3.0//EN"        
    "http://ibatis.apache.org/dtd/ibatis-3-config.dtd">  
<configuration>  
    <settings>  
        <!-- 全局映射器启用缓存 -->  
        <setting name="cacheEnabled" value="false" />  
        
        <!-- 查询时,关闭关联对象即时加载以提高性能 -->  
        <setting name="lazyLoadingEnabled" value="true" />
          
        <!-- 设置关联对象加载的形态,此处为按需加载字段(加载字段由SQL指定),不会加载关联表的所有字段,以提高性能 -->  
        <setting name="aggressiveLazyLoading" value="false" />  
        
        <!-- 对于未知的SQL查询,允许返回不同的结果集以达到通用的效果 -->  
        <setting name="multipleResultSetsEnabled" value="true" />  
        
        <!-- 允许使用列标签代替列名 -->  
        <setting name="useColumnLabel" value="true" />  
        
        <!-- 允许使用自定义的主键值(比如由程序生成的UUID 32位编码作为键值),数据表的PK生成策略将被覆盖 -->  
        <setting name="useGeneratedKeys" value="true" />  
        
        <!-- 给予被嵌套的resultMap以字段-属性的映射支持 -->  
        <setting name="autoMappingBehavior" value="FULL" />  
        
        <!-- 对于批量更新操作缓存SQL以提高性能  -->  
        
        <!-- <setting name="defaultExecutorType" value="BATCH" />   -->
        <!-- FORSQLSERVER -->
        <setting name="defaultExecutorType" value="SIMPLE" />
        
        <!-- 数据库超过25000秒仍未响应则超时 -->  
        <setting name="defaultStatementTimeout" value="25000" />  
    </settings>  
	<typeAliases>
		<typeAlias type="com.qing.datasource.C3P0DataSourceFactory" alias="C3P0" />
	</typeAliases>
	<environments default="DAG">
		<environment id="DAG">
			<transactionManager type="JDBC"></transactionManager>
            <dataSource type="C3P0">
                <property name="driverClass" value="${driver}" />
                <property name="jdbcUrl" value="${url}" />
                <property name="user" value="${username}" />
                <property name="password" value="${password}" />
                <property name="preferredTestQuery" value="SELECT 1" />
                <property name="acquireIncrement" value="3" />
                <property name="minPoolSize" value="10" />
                <property name="maxPoolSize" value="100" />
                <property name="maxIdleTime" value="60" />
            </dataSource>
		</environment>
	</environments>

         <mappers>  
           <mapper resource="sqlmapper/UserMapper.xml"/>
        </mappers>
</configuration>  

数据库切换的初始化

public class DBNameUtil {
     
	private Map<String,String> map = new HashMap<String,String>();
	
	private static DBNameUtil dbName = new DBNameUtil();
	
	private DBNameUtil(){
		map.clear();
		map.put("dag1", "test");
		map.put("dag2", "shiro");
		map.put("dag3", "shiroweb");
	}
	
	public String getDBName(String dagId){
		return map.get(dagId);
	}
	
	public static DBNameUtil getInstance(){
		return dbName;
	}
}

现在我们应该把这两个配置文件里的数据组合起来

创建Mybatis SqlSessionFactory实例

import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.springframework.util.StringUtils;

import com.qing.utils.DBNameUtil;

/**
 * 构造指定DAG ID的Mybatis SqlSessionFactory实例,并进行全局缓存.
 */
public final class DataSourceSqlSessionFactoryBuilder {

	private DataSourceSqlSessionFactoryBuilder() {};

	/**
	 * Mybatis配置文件名.
	 */
	private static final String MYBATIS_CONFIG = "mybatis-config.xml";

	/**
	 * Mybatis数据源属性配置文件.
	 */
	private static final String MYBATIS_CONFIG_PROPERTIES = "mybatis-config-datasource.properties";

	/**
	 * 缓存每个DAG对应的Mybatis数据源.
	 */
	private static final Map<String, SqlSessionFactory> DATASOURCE = new ConcurrentHashMap<String, SqlSessionFactory>();

	public static SqlSessionFactory buildSqlSessionFactory(String dagID)
			throws IOException {
		if (StringUtils.isEmpty(dagID)) {
			throw new IOException("The DAG id is Empty!");
		}
		if (DATASOURCE.get(dagID) != null) {
			System.out.println("DDR: get dataSource from cache width dagid[{" + dagID + "}].");
			return DATASOURCE.get(dagID);
		}
		String dbName = DBNameUtil.getInstance().getDBName(dagID);
		if (dbName == null) {
			throw new IOException("The DAG id is not found! " + dagID);
		}
		Properties properties = null;
		SqlSessionFactory sqlSessionFactory = null;
		InputStream inputStream = Resources.getResourceAsStream(MYBATIS_CONFIG);
		properties = Resources.getResourceAsProperties(MYBATIS_CONFIG_PROPERTIES);
		String url = properties.getProperty("url").toString().replace("%DBNAME%", dbName);
		properties.setProperty("url", url);
		sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream,properties);
		DATASOURCE.put(dagID, sqlSessionFactory);
		System.out.println("DDR: build dataSource with dagId[{" + dagID + "}] and domain[{" + dbName + "}].");
		return DATASOURCE.get(dagID);
	}
}

有了SqlSessionFactory,现在就要创建SqlSession了,但是为方便管理,并且考虑到线程安全以及事物,我们建立一个SessionManager类。

import java.sql.SQLException;
import org.apache.ibatis.session.SqlSession;
/**
 * 管理线程上下文持有的 Mybatis SqlSession实例.
 */
public final class SessionManager {
	
	private SessionManager(){};
	
	//当前线程上下文,持有Mybatis SqlSession对象.
	private static ThreadLocal<SqlSession> sqlSessionHolder = new ThreadLocal<SqlSession>();

	//获取当前线程持有的SqlSession对象实例.
	public static SqlSession getSqlSession() {
		return sqlSessionHolder.get();
	}

	//设置当前线程持有的SqlSession实例.
	public static void setSqlSession(SqlSession sqlSession) {
		sqlSessionHolder.set(sqlSession);
	}

	/**
	 * 使用当前线程的SqlSession实例构造指定Mapper实例的代理对象.
	 * @param clazz Mapper接口类型.
	 * @return
	 */
	public static <T> T get(Class<T> clazz) {
		SqlSession session = sqlSessionHolder.get();
		try {
			System.out.println("==> dataSource: {}"+session.getConnection().getMetaData().getURL());
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return sqlSessionHolder.get().getMapper(clazz);
	}

	//关闭当前线程持有的SqlSession实例并从其ThreadLocal上下文实例中移除.
	public static void close() {
		if (sqlSessionHolder.get() != null) {
			sqlSessionHolder.get().close();
		}
		sqlSessionHolder.remove();
	}
	
	/**
	 * 进行数据库事务提交.
	 * @param deltegate 回调接口.
	 * @throws Exception
	 */
	public static void transactional(TransactionDelegate deltegate) throws Exception{
		SqlSession session = sqlSessionHolder.get();
		try {
			System.out.println("==> dataSource: {}"+session.getConnection().getMetaData().getURL());
		} catch (SQLException e) {
			e.printStackTrace();
		}
		try{
			session.commit(false);
			deltegate.execute(session);
			session.commit();
		}catch(Exception ex){
			session.rollback();
			throw ex;
		}finally{
			session.commit(true);
		}
	}
	
	//事务代理接口
	public interface TransactionDelegate{
		public void execute(SqlSession session) throws Exception;
	} 
}

最后就是创建操作实体的接口,以及实体相关配置了

UserMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.qing.mapper.UserMapper">

	<resultMap id="BaseResultMap" type="com.qing.entity.User">
		<result column="id" jdbcType="TINYINT" property="id" />
		<result column="username" jdbcType="VARCHAR" property="username" />
		<result column="password" jdbcType="VARCHAR" property="password" />
		<result column="salt" jdbcType="VARCHAR" property="salt" />
	</resultMap>
	
	<sql id="Base_Column_List">
		id,username,password,salt
	</sql>

	<select id="findByUserName" parameterType="java.lang.String" resultMap="BaseResultMap">
		SELECT
		<include refid="Base_Column_List" />
		FROM sys_user_test
		WHERE username = #{username}
	</select>

	<insert id="save" parameterType="com.qing.entity.User" useGeneratedKeys="false">
		INSERT INTO sys_user_test (id
		,username
		,password
		,salt
		) VALUES (
		 #{id}
		,#{username}
		,#{password}
		,#{salt}
		)
	</insert>
	
	<update id="updateUser" parameterType="com.qing.entity.User">
	    UPDATE sys_user_test
    <set >
      <if test="id != null" >
        id = #{id},
      </if>
      <if test="username != null">
        username = #{username},
      </if>
      <if test="password != null">
        password = #{password},
      </if>
      <if test="salt != null">
        salt = #{salt},
      </if>
    </set>
    WHERE id = #{id}
	</update>	  
</mapper>

操作数据库接口

public interface UserMapper {
	List<User> findByUserName(String username);

	void save(User user);

	int updateUser(User user);

}

测试:

新建一个测试的servlet

public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		System.out.println("====================MyServlet 我来啦 ==================");
		String dagId = request.getParameter("dagId");
		System.out.println("dagId================>"+dagId);
		System.out.println("dbName================>"+DBNameUtil.getInstance().getDBName(dagId));
		SqlSessionFactory sqlSessionFactory = DataSourceSqlSessionFactoryBuilder.buildSqlSessionFactory(dagId);
		SessionManager.setSqlSession(sqlSessionFactory.openSession(true));
		
		User user = new User();
		user.setId(5);
		user.setUsername("wang");
		user.setPassword("2345134");
		user.setSalt(DBNameUtil.getInstance().getDBName(dagId)+user.getId());
		
		SessionManager.get(UserMapper.class).save(user);
}

把项目放到tomcat下面启动。

使用的是HttpClients进行测试

public class Test1 {
	/** 
     * 发送 post请求访问本地应用并根据传递参数不同返回不同结果 
     */  
    public void post() {  
        // 创建默认的httpClient实例.    
        CloseableHttpClient httpclient = HttpClients.createDefault();  
        // 创建httppost    
        HttpPost httppost = new HttpPost("http://localhost:8080/mybatis/MyServlet");  
        // 创建参数队列    
        List<NameValuePair> formparams = new ArrayList<NameValuePair>();  
        formparams.add(new BasicNameValuePair("dagId", "dag2"));  
        UrlEncodedFormEntity uefEntity;  
        try {  
            uefEntity = new UrlEncodedFormEntity(formparams, "UTF-8");  
            httppost.setEntity(uefEntity);  
            System.out.println("executing request " + httppost.getURI());  
            CloseableHttpResponse response = httpclient.execute(httppost);  
            try {  
                HttpEntity entity = response.getEntity();  
                if (entity != null) {  
                    System.out.println("--------------------------------------");  
                    System.out.println("Response content: " + EntityUtils.toString(entity, "UTF-8"));  
                    System.out.println("--------------------------------------");  
                }  
            } finally {  
                response.close();  
            }  
        } catch (ClientProtocolException e) {  
            e.printStackTrace();  
        } catch (UnsupportedEncodingException e1) {  
            e1.printStackTrace();  
        } catch (IOException e) {  
            e.printStackTrace();  
        } finally {  
            // 关闭连接,释放资源    
            try {  
                httpclient.close();  
            } catch (IOException e) {  
                e.printStackTrace();  
            }  
        }  
    }   
	public static void main(String[] args) {
		Test1 t = new Test1();
		t.post();
	}
}

猜你喜欢

转载自zhanshi258.iteye.com/blog/2224376