设为首页 收藏本站
查看: 830|回复: 0

[经验分享] mybatis 多数据源 配置实例

[复制链接]

尚未签到

发表于 2016-11-26 07:31:46 | 显示全部楼层 |阅读模式
  简介:本案例是使用使用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();
}
}

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-305606-1-1.html 上篇帖子: Mybatis statement-builders文档的坑 下篇帖子: Mybatis系列之实战篇(下)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表