动态数据源3之动态分库反思

来源:互联网 发布:android快递查询源码 编辑:程序博客网 时间:2024/06/08 13:17

       看过我的关于动态分库的文章:http://blog.csdn.net/rainyspring4540/article/details/51828573

一定发现了 这种分库方式有个很要命的缺陷,吃性能!!!,由于本身我们项目特点,不会有太大的访问量,但在测试阶段,测试人员在产品上建了50多个库,虽然并发人数少,单这么多数据源都在内存里,性能可想而知。

       如果项目本身不会跨域的话,事实上有个不错的解决方案。

       根据上一篇文章的表结构设计,只要在创建项目库时的界面上加入IP、端口的设置,是允许同时连接不同ip的库的,即连接域不同,如果你们的所有项目库是在一个ip上,即都在一个服务器上,那么同域多数据源的问题是可以转化成一个数据源了。

       大家都知道,单纯的sql是可以在客户端执行类似于select * from dbA.tableA  a  inner join dbB.tableB b on a.id=b.id的同域跨库语句的

       那么jdbc实现的sql调用可以吗?hibernate框架也允许吗?springmvc封装的jdbcTemplate和HibernateTemplate也可以吗?必须可以!!!

       实践证明:虽然我们在配置jdbc链接时是明确指定了访问具体的库,但其实同一个ip的其他库也可以访问,而且可以进行复杂综合关联查询(这样就不必为了数据一致性来进行项目库和主库的数据反复同步)

       简单的jdbc和jdbcTemplate我就不写例子了,很简单,和普通的sql没啥区别,就是库名+.+表名就ok了

       下面我说下hibernateTemplate(因为我们项目是整合了springmvc4+hibernate4),所有用的是spring管理的hibernate

package com.fulong.construction.entity;import java.util.HashSet;import java.util.Set;import javax.persistence.Column;import javax.persistence.Entity;import javax.persistence.Id;import javax.persistence.OneToMany;import javax.persistence.Table;/** * @author  * @date 2015-11-16 * @description dba库中的国家表 */@Entity@Table(name="tableCountry",catalog="dba")public class Country2{@Idprivate String countryId;@Columnprivate String countryName;public String getCountryId() {return countryId;}public void setCountryId(String countryId) {this.countryId = countryId;}public String getCountryName() {return countryName;}public void setCountryName(String countryName) {this.countryName = countryName;}}
package com.fulong.construction.entity;import java.util.HashSet;import java.util.Set;import javax.persistence.Column;import javax.persistence.Entity;import javax.persistence.FetchType;import javax.persistence.Id;import javax.persistence.JoinColumn;import javax.persistence.ManyToOne;import javax.persistence.OneToMany;import javax.persistence.Table;/** * @author  * @date 2015-11-16 * @description dbb库中的公司表 */@Entity@Table(name = "tableCompany",catalog="dbb")public class Company2 {@Id private String companyId;// 公司id@Columnprivate String companyName;// 公司名称@ManyToOne(targetEntity=Country2.class,fetch=FetchType.LAZY)@JoinColumn(name="countryId")private Country2 country;public String getCompanyId() {return companyId;}public void setCompanyId(String companyId) {this.companyId = companyId;}public String getCompanyName() {return companyName;}public void setCompanyName(String companyName) {this.companyName = companyName;}public Country2 getCountry() {return country;}public void setCountry(Country2 country) {this.country = country;}}

查询:

List<Country2> list4 = session.createQuery("select b from Company2 c inner join c.country b where b.countryId='JPZ'").list();for(Country2 c:list4){System.out.println(c.getCountryId()+"--3--"+c.getCountryName());}System.out.println(list4.size());

通过给实体加入catalog属性来实现跨库综合查询没问题的  ^_^


反思上个项目:

根据刚刚的方法可以将上个项目的多数据源变成一个数据源,性能和稳定性(不必同步库间差异信息)都会更好,但有个问题:由于是动态数据源,会导致一个库一套bean实体文件(annotation方式)或多套实体配置文件(xml方式的实体),而动态创建hibernate实体并加载有些复杂,这里有个取巧的解决方式:


经过测试:在多数据源下,如果实体没有指定catalog属性,则当前的数据源是谁,那就是谁的实体,如果指定了catalog,则catalog的属性值即为实体永久的库名,忽略当前数据源

根据这么结论,实际上我们只需要配置2套bean就ok了,一套指定catalog为主库的名字,另一套不指定catalog,为当前切换到指定从库的库名,由于已经不存在从库与从库或  主库与从库的同步数据问题,故2套就ok了


提示:以上结论都指定测试用例上通过,并未真正用在项目上,毕竟已经完结的项目是不允许随意更改核心技术架构的,留着以后用吧

0 0