场景:在Spring+Mybatis搭建的项目中要配置两个数据库,如何实现?
其实也不是多难的事情,只要把配置配好了,一切问题就迎刃而解了,废话不多说,且看
如下配置……
配置一:jdbc.properties
配置两个数据库:myuser和myitem
myuser.jdbc.driver=com.mysql.jdbc.Driver
myuser.jdbc.url=jdbc:mysql://192.168.1.100:3306/myuser?useUnicode=true&zeroDateTimeBehavior=convertToNull&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true
myuser.jdbc.username=root
myuser.jdbc.password=123456
myitem.jdbc.driver=com.mysql.jdbc.Driver
myitem.jdbc.url=jdbc:mysql://192.168.1.100:3306/myitem?useUnicode=true&zeroDateTimeBehavior=convertToNull&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true
myitem.jdbc.username=root
myitem.jdbc.password=123456
配置二:applicationContext.xml
配置:
两个数据源(myUserDataSource和myItemDataSource)、
<!-- 数据库连接池1 :myuser-->
<bean id="myUserDataSource" class="com.jolbox.bonecp.BoneCPDataSource"
destroy-method="close">
<!-- 数据库驱动 -->
<property name="driverClass" value="${myuser.jdbc.driver}" />
<!-- 相应驱动的jdbcUrl -->
<property name="jdbcUrl" value="${myuser.jdbc.url}" />
<!-- 数据库的用户名 -->
<property name="username" value="${myuser.jdbc.username}" />
<!-- 数据库的密码 -->
<property name="password" value="${myuser.jdbc.password}" />
<!-- 检查数据库连接池中空闲连接的间隔时间,单位是分,默认值:240,如果要取消则设置为0 -->
<property name="idleConnectionTestPeriod" value="60" />
<!-- 连接池中未使用的链接最大存活时间,单位是分,默认值:60,如果要永远存活设置为0 -->
<property name="idleMaxAge" value="30" />
<!-- 每个分区最大的连接数 -->
<property name="maxConnectionsPerPartition" value="150" />
<!-- 每个分区最小的连接数 -->
<property name="minConnectionsPerPartition" value="5" />
</bean>
<!-- 数据库连接池2 :myitem-->
<bean id="myItemDataSource" class="com.jolbox.bonecp.BoneCPDataSource"
destroy-method="close">
<!-- 数据库驱动 -->
<property name="driverClass" value="${myitem.dbc.driver}" />
<!-- 相应驱动的jdbcUrl -->
<property name="jdbcUrl" value="${myitem.jdbc.url}" />
<!-- 数据库的用户名 -->
<property name="username" value="${myitem.jdbc.username}" />
<!-- 数据库的密码 -->
<property name="password" value="${myitem.jdbc.password}" />
<!-- 检查数据库连接池中空闲连接的间隔时间,单位是分,默认值:240,如果要取消则设置为0 -->
<property name="idleConnectionTestPeriod" value="60" />
<!-- 连接池中未使用的链接最大存活时间,单位是分,默认值:60,如果要永远存活设置为0 -->
<property name="idleMaxAge" value="30" />
<!-- 每个分区最大的连接数 -->
<property name="maxConnectionsPerPartition" value="150" />
<!-- 每个分区最小的连接数 -->
<property name="minConnectionsPerPartition" value="5" />
</bean>
<!-- 数据库连接池 -->
<bean id="dynamicDataSource" class="com.wupao.sso.dynamicdatasource.DynamicDataSource">
<property name="targetDataSources">
<map key-type="java.lang.String">
<entry value-ref="myUserDataSource" key="myUserDataSource"/>
<entry value-ref="myItemDataSource" key="myItemDataSource"/>
</map>
</property>
<!-- <property name="defaultTargetDataSource" ref="myUserDataSource"/>默认使用myUserDataSource的数据源 -->
</bean>
有童鞋可能会问:DynamicDataSource这个类是怎么回事?
别急,这个类是自定义的一个类,此类必须继承:AbstractRoutingDataSource这个抽象类,并且重写
AbstractRoutingDataSource方法,动态数据源才会生效。
代码如下:
/**
* 自定义动态数据源,继承AbstractRoutingDataSource抽象类,
* 重写determineCurrentLookupKey方法
* @author root
*/
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DBContextHolder.getDBType();
}
}
问:DataSourceContextHolder这个类是什么干嘛的?
代码如下:
/**
*设置数据库类型,指定使用哪个数据库
*@author root
*/
public class DataSourceContextHolder {
private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();
public static void setDbType(String dbType) {
contextHolder.set(dbType);
}
public static String getDbType() {
return ((String) contextHolder.get());
}
public static void clearDbType() {
contextHolder.remove();
}
}
问:那事物怎么管理呢?别急,继续往下看……
配置三:applicationContext-transaction.xml
<!-- 定义事务管理器 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dynamicDataSource" />
</bean>
<!-- 定义事务策略 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!--所有以query开头的方法都是只读的 -->
<tx:method name="query*" read-only="true" />
<!--其他方法使用默认事务策略 -->
<tx:method name="*" />
</tx:attributes>
</tx:advice>
<aop:config>
<!--pointcut元素定义一个切入点,execution中的第一个星号 用以匹配方法的返回类型,
这里星号表明匹配所有返回类型。 com.abc.dao.*.*(..)表明匹配com.simple.mybatis.service包下的所有类的所有
方法 -->
<aop:pointcut id="myPointcut" expression="execution(* com.simple.sso.service.*.*(..))" />
<!--将定义好的事务处理策略应用到上述的切入点 -->
<aop:advisor advice-ref="txAdvice" pointcut-ref="myPointcut" />
</aop:config>
问:那么sqlSessionFactory怎么获取数据源呢?继续配置……
配置四:applicationContext-mybatis.xml
<!-- 定义Mybatis的SqlSessionFactory -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 定义数据源 -->
<property name="dataSource" ref="dynamicDataSource" />
<!-- 指定mybatis全局配置文件 -->
<property name="configLocation" value="classpath:mybatis/mybatis-config.xml"></property>
<!-- 扫描mappers目录以及子目录下的所有xml文件 -->
<!-- <property name="mapperLocations" value="classpath:mybatis/mappers/**/*.xml" /> -->
<!-- 别名扫描包 -->
<property name="typeAliasesPackage" value="com.simple.sso.pojo"/>
</bean>
到这里,其实该配置的都已经配置完了。
问:那么在代码中该如何使用呢?比如说要插入的数据时该往哪个数据库中插入呢?我怎么保证数据就是我要插入的数据库呢?
我们都知道要插入数据首先是要生成实体类和表对应起来,把数据封装到实体类,通过映射关系和注解标识把数据插入到表中,所以亮点就在这里了,上面的问题也就不言而喻了。
在实体类上注解上添加注解:
如:myuser数据库中有user表,指定:数据库名.表名(重点!!!)
@Table(name = "myuser.user")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;// 用户id
@Length(min = 2, max = 20, message = "账户名为2-20位,由汉字、字母(不分大小写)、数字或下划线组成!")
private String loginname;// 用户名
这样指定之后,当在代码中要往myuser.user表中插入数据时,封装完的User对象作为参数传递到saveUser(User user)方法中,自动就会插入到myuser库中的user表中。
问:如果myitem表中也有user表怎么办?我要往myitem的user表中插入数据怎么实现?
答案:同上!
@Table(name = "myitem.user")
public class ItemUser {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;// 用户id
@Length(min = 2, max = 20, message = "账户名为2-20位,由汉字、字母(不分大小写)、数字或下划线组成!")
private String loginname;// 用户名
看到这里,我相信大家已经有所了解了,祝你配置成功!