看过我的关于动态分库的文章: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{
@Id
private String countryId;
@Column
private 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
@Column
private 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了
提示:以上结论都指定测试用例上通过,并未真正用在项目上,毕竟已经完结的项目是不允许随意更改核心技术架构的,留着以后用吧