【Java EE 学习第77天】【数据采集系统第九天】【使用spring实现答案水平分库】【未解决问题:分库查询问题】

  之前说过,如果一个数据库中要存储的数据量整体比较小,但是其中一个表存储的数据比较多,比如日志表,这时候就要考虑分表存储了;但是如果一个数据库整体存储的容量就比较大,该怎么办呢?这时候就需要考虑分库了,就是建立多个数据库保存数据。这里以答案为例,就算调查对象不是很多,但是参与调查的人数非常多,那么需要保存的数据量就会非常大,怎样将答案以一种规则保存到不同的数据库中就是现在需要考虑的问题(查询分库的问题未解决,先存档)。

一、分库方法

  分库分为水平分库和竖直分库两种类型。

  (1)水平分库

    数据库之间是同构的,但是数据的存储范围不同。比如之后我将使用水平分库的方法保存答案到不同的数据库中。两个数据库中都有答案表,而且字段和约束等完全相同,两者的差异只是保存的数据不同,这样的分库方法就是水平分库。

  (2)竖直分库

    数据库和数据库之间的结构不相同,比如一个数据库存放一个模块的功能,每个模块的独立性比较强。而且量比较大。

二、实现答案分库的步骤:以2个数据库为例说明

  1.创建第二个数据库lsn_surveypark1

  2.配置数据源

    因为之前已经配置过数据源了,所以这里只需要直接继承上一个数据源并且修改url地址即可

 1 <!-- 配置数据源(主库) -->
 2 <bean id="dateSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
 3     <property name="driverClass" value="${jdbc.driverclass}"></property>
 4     <property name="jdbcUrl" value="${jdbc.url}"></property>
 5     <property name="user" value="${jdbc.username}"></property>
 6     <property name="password" value="${jdbc.password}"></property>
 7
 8     <!-- 配置c3p0自身的参数 -->
 9     <property name="maxPoolSize" value="${c3p0.pool.maxsize}"></property>
10     <property name="minPoolSize" value="${c3p0.pool.minsize}"></property>
11     <property name="initialPoolSize" value="${c3p0.pool.initsieze}"></property>
12     <property name="acquireIncrement" value="${c3p0.pool.increment}"></property>
13 </bean>
14 <!-- (从库) 为了实现分库的功能,必须针对每个数据库配置一个数据源 这里使用了包的继承的特殊属性使用parent属性对dataSource进行了继承 -->
15 <bean id="dataSource1" class="com.mchange.v2.c3p0.ComboPooledDataSource"
16     parent="dateSource">
17     <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/lsn_surveypark1"></property>
18 </bean>

  3.配置数据源路由器

    数据源路由器将会根据策略决定使用的数据源。

 1 <!-- 配置数据源路由器 -->
 2 <bean id="dataSource_router" class="com.kdyzm.datasource.SurveyparkDatasourceRouter">
 3     <property name="targetDataSources">
 4         <map>
 5             <!-- 如果id是偶数,保存到主库中 -->
 6             <entry key="even" value-ref="dateSource"></entry>
 7             <!-- 如果id是奇数,保存到从库中 -->
 8             <entry key="odd" value-ref="dataSource1"></entry>
 9         </map>
10     </property>
11     <!-- 如果不满足上述规则,则直接使用默认的数据源 -->
12     <property name="defaultTargetDataSource" ref="dateSource"></property>
13 </bean>

  这里的策略封装到了一个类中SurveyparkDatasourceRouter,该类必须继承org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource抽象类并重写determineCurrentLookupKey方法确定策略。

  4.自定义路由数据源策略

  自定义的方法就是继承org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource类并重写抽象方法。

 1 package com.kdyzm.datasource;
 2
 3 import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
 4
 5 import com.kdyzm.domain.Survey;
 6
 7 /**
 8  * 自定义数据源路由器
 9  *     有一个默认的实现类,该类是以传播属性来路由数据的。
10  * @author kdyzm
11  *
12  */
13 public class SurveyparkDatasourceRouter extends AbstractRoutingDataSource{
14
15     /**
16      * 该方法实际上确定了一个数据向哪里存放的策略
17      * 在这里使用id的就属性来确定
18      * 如果答案id是偶数,就想lsn_surveypark数据库中的answer表(主表)中存放
19      * 如果答案的id是奇数,就向lsn_surveypark1数据库中的answer表(从表)中存放
20      */
21     @Override
22     protected Object determineCurrentLookupKey() {
23         SurveyToken surveyToken=SurveyToken.getSurveyToken();
24         if(surveyToken!=null){
25             Survey survey=surveyToken.getSurvey();
26             int surveyId=survey.getSurveyId();
27             System.out.println("Survey对象不为空,值为:"+surveyId);
28             /**
29              * 在这里必须解除绑定
30              * 如果不在这里解除绑定的话就会将log日志写入到lsn_surveypark1数据库中。
31              * 由于lsn_surveypark1数据库中没有log表,所以一定会报错
32              */
33             SurveyToken.unbind();
34             return (surveyId%2)==0?"even":"odd";    //如果是偶数返回even字符串,如果是奇数返回odd字符串
35         }
36         System.out.println("survey对象为空");
37         return null;
38     }
39
40 }

  以上重写的方法中决定了路由数据源的策略:如果调查ID是偶数,就保存到主库lsn_surveypark的answer表中,如果是奇数,就保存到从库lsn_surveypark1中的answer表中。

  接下来就是解决怎么拿到Survey对象的问题,上面的黄色背景部分的代码是关键。

  注意,如果Survey对象为空,就使用默认的数据源:主库,这是由之前的配置文件中的配置决定的。

  5.使用ThreadLocal解决拿到Survey的问题。

  (1)分析问题

    

  

  

时间: 2024-10-18 21:58:21

【Java EE 学习第77天】【数据采集系统第九天】【使用spring实现答案水平分库】【未解决问题:分库查询问题】的相关文章

Java EE学习--Quartz基本用法

新浪博客完全不适合写技术类文章.本来是想找一个技术性的博客发发自己最近学的东西,发现博客园起源于咱江苏,一个非常质朴的网站,行,咱要养成好习惯,以后没事多总结总结经验吧.很多时候都在网上搜索别人的总结,我自己也总结些东西,或许多多少少能帮得上别人. 首先提到的是Quartz,一个开源的定期执行计划任务的框架.其实我内心好奇这个框架很久了,像那些能定时修改数据库数据,定时分配任务的功能一直觉得很神奇.心动不如行动,今天我就小小的学习了一下用法,力求言简意赅,大家都懂的我就不说了. 第一步:下载Qu

Java EE 学习(7):IDEA + maven + spring 搭建 web(3)- 配置数据库

参考: https://my.oschina.net/gaussik/blog/513444 注:在阅读本文前,请先阅读: Java EE 学习(5):IDEA + maven + spring 搭建 web(1) Java EE 学习(6):IDEA + maven + spring 搭建 web(2) 5 数据库配置 下面,就要通过一个简单的例子,来介绍 SpringMVC 如何集成 Spring Data JPA(由 Hibernate JPA 提供),来进行强大的数据库访问,并通过本章节

JAVA EE 学习笔记[V1 jsp编程]

在三月初学校开设了javaee的课程,也就此展开了对javaee基础的学习.然后老师也对这次的课程有一定要求.前面的基础就为最终的作业做准备啦~ 在上学期我们学习了java相关知识,也对java se 的安装使用有了一定的认知,而java ee则是构建于java se 平台之上的一套多层的,可扩展的的网络应用. 学习java ee我们首先进行环境的搭建.无非就是使用 tomcat进行服务器的搭建和jdk环境变量配置.而IDE这方面我们选择myeclipse 2016 CI(这个编译器自带tomc

Java EE 学习(8):IDEA + maven + spring 搭建 web(4)- 用户管理

转载:Gaussic(一个致力于AI研究却不得不兼顾项目的研究生) 注:在阅读本文前,请先阅读: Java EE 学习(5):IDEA + maven + spring 搭建 web(1) ava EE 学习(6):IDEA + maven + spring 搭建 web(2)- 配置 Spring Java EE 学习(7):IDEA + maven + spring 搭建 web(3)- 配置数据库 记录: 通过对用户表的管理,更加深入地讲解SpringMVC的操作. 6 用户管理 既然我们

Java EE 学习(9):IDEA + maven + spring 搭建 web(5)- 博客文章管理

转载:Gaussic(一个致力于AI研究却不得不兼顾项目的研究生) . 注:在阅读本文前,请先阅读: Java EE 学习(5):IDEA + maven + spring 搭建 web(1) Java EE 学习(6):IDEA + maven + spring 搭建 web(2)- 配置 Spring Java EE 学习(7):IDEA + maven + spring 搭建 web(3)- 配置数据库 Java EE 学习(8):IDEA + maven + spring 搭建 web(

【Java EE 学习第16天】【dbcp数据库连接池】【c3p0数据库连接池】

零.回顾之前使用的动态代理的方式实现的数据库连接池: 代码: 1 package day16.utils; 2 3 import java.io.IOException; 4 import java.lang.reflect.InvocationHandler; 5 import java.lang.reflect.Method; 6 import java.lang.reflect.Proxy; 7 import java.sql.Connection; 8 import java.sql.D

Java EE学习之旅1——HeadFirstJavaEE

因为找到的实习是用Java开发的公司,所以来学习一下Java EE的知识. 首先找来了书<轻量级Java EE企业应用实战>. 啊不得不说学了Java之后直接看这个还是完全不行呢,好多名词看都没有看过啊哈哈. 首先来看看都些啥看不懂的词... 1.JSP.Servlet和JavaBean JSP和Servlet都是用在表现层的东西,而实质上JSP编译成Servlet才运行. 但Servlet开发成本太大,所以用JSP. JavaBean用来通信交换表现层和底层数据. 2.MVC和Struts

Java EE学习——Quartz的Cron表达式

经历过低谷后,还是要好好学习,越失落会越来越落后. 今天写一下Cron表达式的用法,虽然是之前自己写的,也过了挺长一段时间,这次就拿出来作为回顾吧. Cron表达式是Quartz的精髓(个人觉得),比如我们想设定淘宝“秒杀”的那一秒时间,完全可以用下面的方法设置执行时间. Calendar cal = Calendar.getInstance(); //设置将要发生的时间... cal.set(Calendar.DATE, xxx); //.......常规的生成scheduler和job //

Java EE学习之旅3——MySQL

只是要是个正经项目,软件就需要使用到数据库,而我连基本的数据库语句都不会用, 所以还是在学习JavaEE之前学习一下MySQL的基本使用. 安装和配置 这个不多说,基本上按照默认的安装msi即可,最重要的是要记住配置时候设置的密码. 基本语句 一个基本原则是MySQL的特有语句在命令行里面不用加分号,操作数据库的通用语句要用分号. 下面是基本语句: create database DatabaseName 创建一个数据库 use DatabaseName 切换当前数据库 create table