spring+hibernate实现分库分表操作

3 篇文章 0 订阅
1 篇文章 0 订阅

分库的实现:


写一个动态的数据源类

public class DynamicDataSource extends AbstractRoutingDataSource {


@Override
protected Object determineCurrentLookupKey() {
// TODO Auto-generated method stub
return DbContextHolder.getDbType();
}


}


public class DbContextHolder {
private static final ThreadLocal contextHolder = new ThreadLocal();


public static void setDbType(String dbType) {
contextHolder.set(dbType);
}


public static String getDbType() {
String str = (String) contextHolder.get();
if (StringUtils.isEmpty(str))
str = "1";
return str;
}


public static void clearDbType() {
contextHolder.remove();
}
}


这里主要用到一个线程本地化,实现同一个线程中的数据传递,我的理解是:请求过来,controller->service->dao->datasource这是在同一个线程 里,而要想从controller传一个数据到datasource,所有可以使用threadLocal


配制如下:

<!-- 多数据源配只 -->
<bean id="dataSource" class="com.lin.datasource.DynamicDataSource">
<property name="targetDataSources">
<map key-type="java.lang.String">
<entry key="1" value-ref="dataSource1"></entry>
<entry key="2" value-ref="dataSource2"></entry>
</map>
</property>
<!-- 莫认的 -->
<property name="defaultTargetDataSource" ref="dataSource1"></property>
</bean>
<!-- 数据源 -->
<bean id="dataSource1" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driverclass}" />
<property name="jdbcUrl" value="${jdbc.url}"></property>
<property name="user" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />


<property name="maxPoolSize" value="${c3p0.pool.size.max}" />
<property name="minPoolSize" value="${c3p0.pool.size.min}" />
<property name="initialPoolSize" value="${c3p0.pool.size.ini}" />
<property name="acquireIncrement" value="${c3p0.pool.size.increment}" />
</bean>
<bean id="dataSource2" parent="dataSource1">
<property name="jdbcUrl" value="${jdbc.url2}"></property>
</bean>


<!-- 本地会话工程bean,是spring整合hibernate的核心 入口 -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
</props>
</property>
<!-- 映射文件的目录 -->
<property name="mappingDirectoryLocations">
<list>
<value>classpath:com/lin/domain</value>
</list>
</property>
</bean>


测试:

@Autowired
private StudentService studentService;
@RequestMapping("/add")
public @ResponseBody String add(String type){
if(type==null)type="default";
DbContextHolder.setDbType(type);
Student student=new Student();
student.setAge(10);
student.setName("fdf"+type);
studentService.save(student);
return type;
}


传一个type,定向到哪一个数据库,就可以了

分表的实现:

主要是使用了hibernate的拦截器


public class QueryResInterceptor extends EmptyInterceptor {
private static final long serialVersionUID = 8307241774485402107L;


private String viewName;
private String fix;


public QueryResInterceptor(String viewName,String fix) {// 写个构造方法,根据参数来确定是增删改查那张表
this.viewName = viewName;
this.fix=fix;
}


@Override
public String onPrepareStatement(String sql) {
//重写该方法,hibernate是封装了jdbc的,但他底层还是通过sql来操作的。
if(viewName.equals("order")){//只有order表才使用多表
sql = sql.replace(viewName,viewName+"_"+fix);
System.out.println("sql_______"+sql);
}
       return sql;
}


}

通过拦截器改变sq语句的表名 


dao层的实现如下:

@Override
public void saveOrder(Order order,String fix) {
//加一个难截器,实现多表插入
QueryResInterceptor interceptor = new QueryResInterceptor("order",fix);
Session session = this.getHibernateTemplate().getSessionFactory()
.openSession(interceptor);
session.save(order);
}


@Override
public List<Order> selectList(String fix) {
QueryResInterceptor interceptor=new QueryResInterceptor("order", fix);
Session session=this.getHibernateTemplate().getSessionFactory().openSession(interceptor);
List<Order> orders=session
.createQuery("select o from "+Order.class.getSimpleName()+" o")
.list();
return orders;
}


就这样就可以了


测试如下:

@Test
public void add(){
OrderService orderService=(OrderService)context.getBean("orderServiceImpl");
Order order=new Order();
order.setContent("jfkd");
String fix="4";//多表中的后缀
orderService.save(order,fix);
}

@Test
public void select(){
OrderService orderService=(OrderService)context.getBean("orderServiceImpl");
List<Order>orders=orderService.selectList("2");
for (Order order : orders) {
System.out.println(order.getId());
}
}



  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值