使用入门-数据源配置

  • 数据源配置,tddl的入口,从datasource切入
<bean id="tddlDataSource" class="com.taobao.tddl.client.jdbc.TDataSource" init-method="init">
<property name="appName" value="tddl_sample" />
<property name="dynamicRule" value="true"/>
</bean>
  • Sequence生成器
<bean id="seqStudent" class="com.taobao.tddl.client.sequence.impl.GroupSequence" init-method="init">
<property name="sequenceDao" ref="idSequenceDao" />
<property name="name" value="seq_Student" />
</bean>
  • 指定静态文件,3.0以后支持动态推送
<bean id="myDataSource" class="com.taobao.tddl.client.jdbc.TDataSource" init-method="init">
<property name="appName" value="tddl_sample"/>
<property name="appRuleFile" value="classpath:tddl-rule.xml"/>
<property name="useLocalConfig" value="true"/>
</bean>

myDataSource--分库分表数据源

appName--数据库代号从dba获得

appRuleFile--分库分表配置文件

useLocalConfig--使用本地配置

  • Sequence配置:  tddl-sequence.xml
<bean id="sequenceDao" class="com.taobao.tddl.client.sequence.impl.GroupSequenceDao" init-method="init">
<!-- appName,必填 -->
<property name="appName" value="CUNTAO_SUPPLIER_APP" />
<!-- 数据源的个数 -->
<property name="dscount" value="1" />
<!-- dbGroupKeys 必填 -->
<!-- 如果在末尾插入"-OFF",该源将被关掉,该源占据的SQL段会被保留" -->
<!-- 当dbGroupKeys中配置的个数小于dbcount的值的时候,默认配置了"-OFF"的源 -->
<property name="dbGroupKeys">
<list>
<value>CUNTAO_SUPPLIER_BODY00_GROUP</value>
</list>
</property>
<!-- 内步长 ,默认为1000,取值在1-100000之间 -->
<property name="innerStep" value="500" />
<!-- 重试次数,在多个groupDataSource的场景下,建议设置成1-2次。默认为2次 -->
<property name="retryTimes" value="2" />
<!-- sequence表的表名 -->
<property name="tableName" value="cuntao_supplier_sequence" />
<!-- 自适应开关 ,默认为false -->
<property name="adjust" value="true" />
</bean>

TDDL分库分表配置bean

tddl-rule.xml

<?xml version="1.0" encoding="UTF-8" ?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
<bean id="vtabroot" class="com.taobao.tddl.interact.rule.VirtualTableRoot" init-method="init">
<property name="defaultDbIndex" value="CUNTAO_SUPPLIER_GROUP"/>
<property name="dbType" value="MYSQL"/>
<property name="tableRules">
<map>
<entry key="cuntao_purchase_order" value-ref="cuntao_purchase_order_bean"/>
<entry key="cuntao_sub_purchase_order" value-ref="cuntao_sub_purchase_order_bean"/>
<entry key="cuntao_logistics_order" value-ref="cuntao_logistics_order_bean"/>
<entry key="cuntao_sub_logistics_order" value-ref="cuntao_sub_logistics_order_bean"/>
</map>
</property>
</bean>
<bean id="cuntao_purchase_order_bean" class="com.taobao.tddl.interact.rule.TableRule">
<property name="dbNamePattern" value="CUNTAO_SUPPLIER_BODY{00}_GROUP"/>
<property name="dbRuleArray">
<value>(#supplier_id,1,256#.longValue() % 10000 % 256).intdiv(32)</value>
</property>
<property name="tbNamePattern" value="cuntao_purchase_order_{0000}" />
<property name="tbRuleArray">
<value>#supplier_id,1,256#.longValue() % 10000 % 256</value>
</property>
</bean>
</beans>

  

配置项说明
分表总配置VirtualTableRoot:
其中,defaultDbIndex是appgroup,从DBA获取;dbType,数据库类型;tableRules引入各个表的配置

分库分表配置TableRule;其中,dbNamePattern分库规则,大括号会替换成dbRuleArray中的值.
dbRuleArray,分库计算方法,(#supplier_id,1,256#.longValue() % 10000 % 256).intdiv(32)表示以supplier_id为分表键,256张表,8个库所以除以32,我们计算规则取后四位计算所以先模10000.

tbNamePattern分表规则,大括号会替换成tbRuleArray中的值。
dbRuleArray,分表计算方法,#supplier_id,1,256#.longValue() % 10000 % 256 就是分库计算方法不除以32.

sequence生成bean
我们用的sequence是一个单库单表的数据库,即每次使用GroupSequence获取新的seq值来计算id,保证全局各个表不会发生id冲突。

appName,从DBA获得。

dbGroupKeys,所在库名称

tableName,sequence表名,可以使用一个sequence表来计算多个表的id,因为每个表实际只占用一行数据。

name,目标表在sequence表中的key,一般取表名,其实是任意的。

  • DefaultSequenceDao源码
public class DefaultSequenceDao implements SequenceDao
{
private static final Log log = LogFactory.getLog(DefaultSequenceDao.class);
private static final int MIN_STEP = 1;
private static final int MAX_STEP = 100000;
private static final int DEFAULT_STEP = 1000;
private static final int DEFAULT_RETRY_TIMES = 150;
private static final String DEFAULT_TABLE_NAME = "sequence";
private static final String DEFAULT_NAME_COLUMN_NAME = "name";
private static final String DEFAULT_VALUE_COLUMN_NAME = "value";
private static final String DEFAULT_GMT_MODIFIED_COLUMN_NAME = "gmt_modified";
private static final long DELTA = 100000000L;
private DataSource dataSource;
private int retryTimes = 150;
private int step = 1000;
private String tableName = "sequence";
private String nameColumnName = "name";
private String valueColumnName = "value";
private String gmtModifiedColumnName = "gmt_modified";
private volatile String selectSql;
private volatile String updateSql; public SequenceRange nextRange(String name)
throws SequenceException
{
if (name == null) {
throw new IllegalArgumentException("序列名称不能为空");
} Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null; for (int i = 0; i < this.retryTimes + 1; i++) { long oldValue;
long newValue;
try { conn = this.dataSource.getConnection();
stmt = conn.prepareStatement(getSelectSql());
stmt.setString(1, name);
rs = stmt.executeQuery();
rs.next();
oldValue = rs.getLong(1); if (oldValue < 0L) {
StringBuilder message = new StringBuilder();
message.append("Sequence value cannot be less than zero, value = ").append(oldValue);
message.append(", please check table ").append(getTableName()); throw new SequenceException(message.toString());
} if (oldValue > 9223372036754775807L) {
StringBuilder message = new StringBuilder();
message.append("Sequence value overflow, value = ").append(oldValue);
message.append(", please check table ").append(getTableName()); throw new SequenceException(message.toString());
} newValue = oldValue + getStep();
} catch (SQLException e) {
throw new SequenceException(e);
} finally {
closeResultSet(rs);
rs = null;
closeStatement(stmt);
stmt = null;
closeConnection(conn);
conn = null;
}
try
{
conn = this.dataSource.getConnection();
stmt = conn.prepareStatement(getUpdateSql());
stmt.setLong(1, newValue);
stmt.setTimestamp(2, new Timestamp(System.currentTimeMillis()));
stmt.setString(3, name);
stmt.setLong(4, oldValue);
int affectedRows = stmt.executeUpdate();
if (affectedRows == 0)
{
closeStatement(stmt);
stmt = null;
closeConnection(conn);
conn = null;
}
else
{
return new SequenceRange(oldValue + 1L, newValue);
}
} catch (SQLException e) { throw new SequenceException(e);
} finally {
closeStatement(stmt);
stmt = null;
closeConnection(conn);
conn = null;
}
} throw new SequenceException("Retried too many times, retryTimes = " + this.retryTimes);
} private String getSelectSql() {
if (this.selectSql == null) {
synchronized (this) {
if (this.selectSql == null) {
StringBuilder buffer = new StringBuilder();
buffer.append("select ").append(getValueColumnName());
buffer.append(" from ").append(getTableName());
buffer.append(" where ").append(getNameColumnName()).append(" = ?"); this.selectSql = buffer.toString();
}
}
} return this.selectSql;
} private String getUpdateSql() {
if (this.updateSql == null) {
synchronized (this) {
if (this.updateSql == null) {
StringBuilder buffer = new StringBuilder();
buffer.append("update ").append(getTableName());
buffer.append(" set ").append(getValueColumnName()).append(" = ?, ");
buffer.append(getGmtModifiedColumnName()).append(" = ? where ");
buffer.append(getNameColumnName()).append(" = ? and ");
buffer.append(getValueColumnName()).append(" = ?"); this.updateSql = buffer.toString();
}
}
} return this.updateSql;
} private static void closeResultSet(ResultSet rs) {
if (rs != null)
try {
rs.close();
} catch (SQLException e) {
log.debug("Could not close JDBC ResultSet", e);
} catch (Throwable e) {
log.debug("Unexpected exception on closing JDBC ResultSet", e);
}
} private static void closeStatement(Statement stmt)
{
if (stmt != null)
try {
stmt.close();
} catch (SQLException e) {
log.debug("Could not close JDBC Statement", e);
} catch (Throwable e) {
log.debug("Unexpected exception on closing JDBC Statement", e);
}
} private static void closeConnection(Connection conn)
{
if (conn != null)
try {
conn.close();
} catch (SQLException e) {
log.debug("Could not close JDBC Connection", e);
} catch (Throwable e) {
log.debug("Unexpected exception on closing JDBC Connection", e);
}
} ...
  • GroupSequenceDao源码
public class GroupSequenceDao implements SequenceDao
{
private static final Log log = LogFactory.getLog(GroupSequenceDao.class);
private static final int MIN_STEP = 1;
private static final int MAX_STEP = 100000;
private static final int DEFAULT_INNER_STEP = 1000;
private static final int DEFAULT_RETRY_TIMES = 2;
private static final String DEFAULT_TABLE_NAME = "sequence";
private static final String DEFAULT_NAME_COLUMN_NAME = "name";
private static final String DEFAULT_VALUE_COLUMN_NAME = "value";
private static final String DEFAULT_GMT_MODIFIED_COLUMN_NAME = "gmt_modified";
private static final int DEFAULT_DSCOUNT = 2;
private static final Boolean DEFAULT_ADJUST = Boolean.valueOf(false);
private static final long DELTA = 100000000L;
private String appName;
private List<String> dbGroupKeys;
private Map<String, DataSource> dataSourceMap;
private boolean adjust = DEFAULT_ADJUST.booleanValue(); private int retryTimes = 2;
private int dscount = 2;
private int innerStep = 1000;
private int outStep = 1000;
private String tableName = "sequence";
private String nameColumnName = "name";
private String valueColumnName = "value";
private String gmtModifiedColumnName = "gmt_modified";
private volatile String selectSql;
private volatile String updateSql;
private volatile String insertSql;
private ConcurrentHashMap<Integer, AtomicInteger> excludedKeyCount = new ConcurrentHashMap(this.dscount);
private int maxSkipCount = 10000;
private boolean useSlowProtect = false;
private int protectMilliseconds = 50;
private ExecutorService exec = Executors.newFixedThreadPool(1); public void init()
throws SequenceException
{
if (StringUtils.isEmpty(this.appName)) {
SequenceException sequenceException = new SequenceException("appName is Null "); log.error("没有配置appName", sequenceException);
throw sequenceException;
}
if ((this.dbGroupKeys == null) || (this.dbGroupKeys.size() == 0)) {
log.error("没有配置dbgroupKeys");
throw new SequenceException("dbgroupKeys为空!");
} this.dataSourceMap = new HashMap();
for (String dbGroupKey : this.dbGroupKeys)
if (!dbGroupKey.toUpperCase().endsWith("-OFF"))
{
TGroupDataSource tGroupDataSource = new TGroupDataSource(dbGroupKey, this.appName); tGroupDataSource.init();
this.dataSourceMap.put(dbGroupKey, tGroupDataSource);
}
if (this.dbGroupKeys.size() >= this.dscount)
this.dscount = this.dbGroupKeys.size();
else {
for (int ii = this.dbGroupKeys.size(); ii < this.dscount; ii++) {
this.dbGroupKeys.add(new StringBuilder().append(this.dscount).append("-OFF").toString());
}
}
this.outStep = (this.innerStep * this.dscount); StringBuilder sb = new StringBuilder();
sb.append("GroupSequenceDao初始化完成:\r\n ");
sb.append("appName:").append(this.appName).append("\r\n");
sb.append("innerStep:").append(this.innerStep).append("\r\n");
sb.append("dataSource:").append(this.dscount).append("个:");
for (String str : this.dbGroupKeys) {
sb.append("[").append(str).append("]、");
}
sb.append("\r\n");
sb.append("adjust:").append(this.adjust).append("\r\n");
sb.append("retryTimes:").append(this.retryTimes).append("\r\n");
sb.append("tableName:").append(this.tableName).append("\r\n");
sb.append("nameColumnName:").append(this.nameColumnName).append("\r\n");
sb.append("valueColumnName:").append(this.valueColumnName).append("\r\n");
sb.append("gmtModifiedColumnName:").append(this.gmtModifiedColumnName).append("\r\n"); log.info(sb.toString());
} private boolean check(int index, long value)
{
return value % this.outStep == index * this.innerStep;
} public void adjust(String name)
throws SequenceException, SQLException
{
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null; for (int i = 0; i < this.dbGroupKeys.size(); i++)
if (!((String)this.dbGroupKeys.get(i)).toUpperCase().endsWith("-OFF"))
{
TGroupDataSource tGroupDataSource = (TGroupDataSource)this.dataSourceMap.get(this.dbGroupKeys.get(i));
try
{
conn = tGroupDataSource.getConnection();
stmt = conn.prepareStatement(getSelectSql());
stmt.setString(1, name);
GroupDataSourceRouteHelper.executeByGroupDataSourceIndex(0);
rs = stmt.executeQuery();
int item = 0;
while (rs.next()) {
item++;
long val = rs.getLong(getValueColumnName());
if (!check(i, val))
{
if (isAdjust()) {
adjustUpdate(i, val, name);
} else {
log.error("数据库中配置的初值出错!请调整你的数据库,或者启动adjust开关");
throw new SequenceException("数据库中配置的初值出错!请调整你的数据库,或者启动adjust开关");
}
}
} if (item == 0)
{
if (isAdjust()) {
adjustInsert(i, name);
} else {
log.error("数据库中未配置该sequence!请往数据库中插入sequence记录,或者启动adjust开关");
throw new SequenceException("数据库中未配置该sequence!请往数据库中插入sequence记录,或者启动adjust开关");
}
}
}
catch (SQLException e) {
log.error("初值校验和自适应过程中出错.", e);
throw e;
} finally {
closeResultSet(rs);
rs = null;
closeStatement(stmt);
stmt = null;
closeConnection(conn);
conn = null;
}
}
} private void adjustUpdate(int index, long value, String name)
throws SequenceException, SQLException
{
long newValue = value - value % this.outStep + this.outStep + index * this.innerStep;
TGroupDataSource tGroupDataSource = (TGroupDataSource)this.dataSourceMap.get(this.dbGroupKeys.get(index)); Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
conn = tGroupDataSource.getConnection();
stmt = conn.prepareStatement(getUpdateSql());
stmt.setLong(1, newValue);
stmt.setTimestamp(2, new Timestamp(System.currentTimeMillis()));
stmt.setString(3, name);
stmt.setLong(4, value);
GroupDataSourceRouteHelper.executeByGroupDataSourceIndex(0);
int affectedRows = stmt.executeUpdate();
if (affectedRows == 0) {
throw new SequenceException(new StringBuilder().append("faild to auto adjust init value at ").append(name).append(" update affectedRow =0").toString());
} log.info(new StringBuilder().append((String)this.dbGroupKeys.get(index)).append("更新初值成功!").append("sequence Name:").append(name).append("更新过程:").append(value).append("-->").append(newValue).toString());
}
catch (SQLException e) {
log.error(new StringBuilder().append("由于SQLException,更新初值自适应失败!dbGroupIndex:").append((String)this.dbGroupKeys.get(index)).append(",sequence Name:").append(name).append("更新过程:").append(value).append("-->").append(newValue).toString(), e); throw new SequenceException(new StringBuilder().append("由于SQLException,更新初值自适应失败!dbGroupIndex:").append((String)this.dbGroupKeys.get(index)).append(",sequence Name:").append(name).append("更新过程:").append(value).append("-->").append(newValue).toString(), e);
}
finally
{
closeStatement(stmt);
stmt = null;
closeConnection(conn);
conn = null;
}
} private void adjustInsert(int index, String name)
throws SequenceException, SQLException
{
TGroupDataSource tGroupDataSource = (TGroupDataSource)this.dataSourceMap.get(this.dbGroupKeys.get(index)); long newValue = index * this.innerStep;
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
conn = tGroupDataSource.getConnection();
stmt = conn.prepareStatement(getInsertSql());
stmt.setString(1, name);
stmt.setLong(2, newValue);
stmt.setTimestamp(3, new Timestamp(System.currentTimeMillis()));
GroupDataSourceRouteHelper.executeByGroupDataSourceIndex(0);
int affectedRows = stmt.executeUpdate();
if (affectedRows == 0) {
throw new SequenceException(new StringBuilder().append("faild to auto adjust init value at ").append(name).append(" update affectedRow =0").toString());
} log.info(new StringBuilder().append((String)this.dbGroupKeys.get(index)).append(" name:").append(name).append("插入初值:").append(name).append("value:").append(newValue).toString());
}
catch (SQLException e)
{
log.error(new StringBuilder().append("由于SQLException,插入初值自适应失败!dbGroupIndex:").append((String)this.dbGroupKeys.get(index)).append(",sequence Name:").append(name).append(" value:").append(newValue).toString(), e); throw new SequenceException(new StringBuilder().append("由于SQLException,插入初值自适应失败!dbGroupIndex:").append((String)this.dbGroupKeys.get(index)).append(",sequence Name:").append(name).append(" value:").append(newValue).toString(), e);
}
finally
{
closeResultSet(rs);
rs = null;
closeStatement(stmt);
stmt = null;
closeConnection(conn);
conn = null;
}
} public SequenceRange nextRange(final String name)
throws SequenceException
{
if (name == null) {
log.error("序列名为空!");
throw new IllegalArgumentException("序列名称不能为空");
} Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null; int[] randomIntSequence = RandomSequence.randomIntSequence(this.dscount);
for (int i = 0; i < this.retryTimes; i++) {
for (int j = 0; j < this.dscount; j++) {
boolean readSuccess = false;
boolean writeSuccess = false;
int index = randomIntSequence[j];
if (!((String)this.dbGroupKeys.get(index)).toUpperCase().endsWith("-OFF"))
{
if (this.excludedKeyCount.get(Integer.valueOf(index)) != null) {
if (((AtomicInteger)this.excludedKeyCount.get(Integer.valueOf(index))).incrementAndGet() > this.maxSkipCount) {
this.excludedKeyCount.remove(Integer.valueOf(index));
log.error(new StringBuilder().append(this.maxSkipCount).append("次数已过,index为").append(index).append("的数据源后续重新尝试取序列").toString());
} }
else
{
final TGroupDataSource tGroupDataSource = (TGroupDataSource)this.dataSourceMap.get(this.dbGroupKeys.get(index));
long oldValue;
long newValue;
try
{
long oldValue;
if ((!this.useSlowProtect) || (this.excludedKeyCount.size() >= this.dscount - 1)) {
conn = tGroupDataSource.getConnection();
stmt = conn.prepareStatement(getSelectSql());
stmt.setString(1, name);
GroupDataSourceRouteHelper.executeByGroupDataSourceIndex(0);
rs = stmt.executeQuery();
rs.next();
oldValue = rs.getLong(1);
} else {
FutureTask future = new FutureTask(new Callable()
{
public Long call() throws Exception
{
Connection fconn = null;
PreparedStatement fstmt = null;
ResultSet frs = null;
try {
fconn = tGroupDataSource.getConnection();
fstmt = fconn.prepareStatement(GroupSequenceDao.this.getSelectSql());
fstmt.setString(1, name);
GroupDataSourceRouteHelper.executeByGroupDataSourceIndex(0);
frs = fstmt.executeQuery();
frs.next();
return Long.valueOf(frs.getLong(1));
} finally {
GroupSequenceDao.closeResultSet(frs);
frs = null;
GroupSequenceDao.closeStatement(fstmt);
fstmt = null;
GroupSequenceDao.closeConnection(fconn);
fconn = null;
}
}
});
try
{
this.exec.submit(future);
oldValue = ((Long)future.get(this.protectMilliseconds, TimeUnit.MILLISECONDS)).longValue();
} catch (InterruptedException e) {
throw new SQLException("[SEQUENCE SLOW-PROTECTED MODE]:InterruptedException", e);
} catch (ExecutionException e) {
throw new SQLException("[SEQUENCE SLOW-PROTECTED MODE]:ExecutionException", e);
} catch (TimeoutException e) {
throw new SQLException(new StringBuilder().append("[SEQUENCE SLOW-PROTECTED MODE]:TimeoutException,当前设置超时时间为").append(this.protectMilliseconds).toString(), e);
}
} if (oldValue < 0L) {
StringBuilder message = new StringBuilder();
message.append("Sequence value cannot be less than zero, value = ").append(oldValue); message.append(", please check table ").append(getTableName()); log.info(message); closeResultSet(rs);
rs = null;
closeStatement(stmt);
stmt = null;
closeConnection(conn);
conn = null; continue;
}
if (oldValue > 9223372036754775807L) {
StringBuilder message = new StringBuilder();
message.append("Sequence value overflow, value = ").append(oldValue); message.append(", please check table ").append(getTableName()); log.info(message); closeResultSet(rs);
rs = null;
closeStatement(stmt);
stmt = null;
closeConnection(conn);
conn = null; continue;
}
newValue = oldValue + this.outStep;
if (!check(index, newValue))
{
if (isAdjust()) {
newValue = newValue - newValue % this.outStep + this.outStep + index * this.innerStep;
}
else {
SequenceException sequenceException = new SequenceException(new StringBuilder().append((String)this.dbGroupKeys.get(index)).append(":").append(name).append("的值得错误,覆盖到其他范围段了!请修改数据库,或者开启adjust开关!").toString()); log.error(new StringBuilder().append((String)this.dbGroupKeys.get(index)).append(":").append(name).append("的值得错误,覆盖到其他范围段了!请修改数据库,或者开启adjust开关!").toString(), sequenceException); throw sequenceException;
} } closeResultSet(rs);
rs = null;
closeStatement(stmt);
stmt = null;
closeConnection(conn);
conn = null;
}
catch (SQLException e)
{
log.error(new StringBuilder().append("取范围过程中--查询出错!").append((String)this.dbGroupKeys.get(index)).append(":").append(name).toString(), e); if (this.excludedKeyCount.size() < this.dscount - 1) {
this.excludedKeyCount.put(Integer.valueOf(index), new AtomicInteger(0));
log.error(new StringBuilder().append("暂时踢除index为").append(index).append("的数据源,").append(this.maxSkipCount).append("次后重新尝试").toString());
}
}
finally
{
closeResultSet(rs);
rs = null;
closeStatement(stmt);
stmt = null;
closeConnection(conn);
conn = null;
} try
{
conn = tGroupDataSource.getConnection();
stmt = conn.prepareStatement(getUpdateSql());
stmt.setLong(1, newValue);
stmt.setTimestamp(2, new Timestamp(System.currentTimeMillis())); stmt.setString(3, name);
stmt.setLong(4, oldValue);
GroupDataSourceRouteHelper.executeByGroupDataSourceIndex(0);
int affectedRows = stmt.executeUpdate();
if (affectedRows == 0)
{
closeStatement(stmt);
stmt = null;
closeConnection(conn);
conn = null;
}
else
{
closeStatement(stmt);
stmt = null;
closeConnection(conn);
conn = null;
}
}
catch (SQLException e)
{
log.error(new StringBuilder().append("取范围过程中--更新出错!").append((String)this.dbGroupKeys.get(index)).append(":").append(name).toString(), e);
}
finally
{
closeStatement(stmt);
stmt = null;
closeConnection(conn);
conn = null;
}
}
} } if (i == this.retryTimes - 2) {
this.excludedKeyCount.clear();
}
}
log.error(new StringBuilder().append("所有数据源都不可用!且重试").append(this.retryTimes).append("次后,仍然失败!").toString());
throw new SequenceException("All dataSource faild to get value!");
} private String getInsertSql() {
if (this.insertSql == null) {
synchronized (this) {
if (this.insertSql == null) {
StringBuilder buffer = new StringBuilder();
buffer.append("insert into ").append(getTableName()).append("("); buffer.append(getNameColumnName()).append(",");
buffer.append(getValueColumnName()).append(",");
buffer.append(getGmtModifiedColumnName()).append(") values(?,?,?);"); this.insertSql = buffer.toString();
}
}
}
return this.insertSql;
} private String getSelectSql() {
if (this.selectSql == null) {
synchronized (this) {
if (this.selectSql == null) {
StringBuilder buffer = new StringBuilder();
buffer.append("select ").append(getValueColumnName());
buffer.append(" from ").append(getTableName());
buffer.append(" where ").append(getNameColumnName()).append(" = ?"); this.selectSql = buffer.toString();
}
}
} return this.selectSql;
} private String getUpdateSql() {
if (this.updateSql == null) {
synchronized (this) {
if (this.updateSql == null) {
StringBuilder buffer = new StringBuilder();
buffer.append("update ").append(getTableName());
buffer.append(" set ").append(getValueColumnName()).append(" = ?, "); buffer.append(getGmtModifiedColumnName()).append(" = ? where "); buffer.append(getNameColumnName()).append(" = ? and ");
buffer.append(getValueColumnName()).append(" = ?"); this.updateSql = buffer.toString();
}
}
} return this.updateSql;
} private static void closeResultSet(ResultSet rs) {
if (rs != null)
try {
rs.close();
} catch (SQLException e) {
log.debug("Could not close JDBC ResultSet", e);
} catch (Throwable e) {
log.debug("Unexpected exception on closing JDBC ResultSet", e);
}
} private static void closeStatement(Statement stmt)
{
if (stmt != null)
try {
stmt.close();
} catch (SQLException e) {
log.debug("Could not close JDBC Statement", e);
} catch (Throwable e) {
log.debug("Unexpected exception on closing JDBC Statement", e);
}
} private static void closeConnection(Connection conn)
{
if (conn != null)
try {
conn.close();
} catch (SQLException e) {
log.debug("Could not close JDBC Connection", e);
} catch (Throwable e) {
log.debug("Unexpected exception on closing JDBC Connection", e);
}
}

TDDL实践的更多相关文章

  1. mongodb 最佳实践

    MongoDB功能预览:http://pan.baidu.com/s/1k2UfW MongoDB在赶集网的应用:http://pan.baidu.com/s/1bngxgLp MongoDB在京东的 ...

  2. 【大数据和云计算技术社区】分库分表技术演进&最佳实践笔记

    1.需求背景 移动互联网时代,海量的用户每天产生海量的数量,这些海量数据远不是一张表能Hold住的.比如 用户表:支付宝8亿,微信10亿.CITIC对公140万,对私8700万. 订单表:美团每天几千 ...

  3. TDDL调研笔记

    一,TDDL是什么 Taobao Distributed Data Layer,即淘宝分布式数据层,简称TDDL .它是一套分布式数据访问引擎 淘宝一个基于客户端的数据库中间件产品 基于JDBC规范, ...

  4. 分库分表技术演进&最佳实践

    每个优秀的程序员和架构师都应该掌握分库分表,这是我的观点. 移动互联网时代,海量的用户每天产生海量的数量,比如: 用户表 订单表 交易流水表 以支付宝用户为例,8亿:微信用户更是10亿.订单表更夸张, ...

  5. webp图片实践之路

    最近,我们在项目中实践了webp图片,并且抽离出了工具模块,整合到了项目的基础模板中.传闻IOS10也将要支持webp,那么使用webp带来的性能提升将更加明显.估计在不久的将来,webp会成为标配. ...

  6. Hangfire项目实践分享

    Hangfire项目实践分享 目录 Hangfire项目实践分享 目录 什么是Hangfire Hangfire基础 基于队列的任务处理(Fire-and-forget jobs) 延迟任务执行(De ...

  7. TDD在Unity3D游戏项目开发中的实践

    0x00 前言 关于TDD测试驱动开发的文章已经有很多了,但是在游戏开发尤其是使用Unity3D开发游戏时,却听不到特别多关于TDD的声音.那么本文就来简单聊一聊TDD如何在U3D项目中使用以及如何使 ...

  8. Logstash实践: 分布式系统的日志监控

    文/赵杰 2015.11.04 1. 前言 服务端日志你有多重视? 我们没有日志 有日志,但基本不去控制需要输出的内容 经常微调日志,只输出我们想看和有用的 经常监控日志,一方面帮助日志微调,一方面及 ...

  9. 【大型网站技术实践】初级篇:借助Nginx搭建反向代理服务器

    一.反向代理:Web服务器的“经纪人” 1.1 反向代理初印象 反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从 ...

随机推荐

  1. Linux入门进阶第二天——软件安装管理(上)

    一.大纲介绍 这里介绍的仅仅是两大家族之一的RPM,关于Debian家族的DPKG,请参考:http://justcoding.iteye.com/blog/1937171 二.简介 软件包分类: 源 ...

  2. 第三次随笔——虚拟机及Linux入门

    虚拟机及Linux入门 虚拟机的安装 对于虚拟机的概念我早有接触,但是从来没有真正的实践过,借这次作业机会我终于实践了虚拟机的安装,安装的过程较为顺利,但还是出现了以下问题: 无法选择64位的系统 解 ...

  3. 【java笔记】Calendar.getInstance()是什么意思

    Calendar类是个抽象类,因此本身不能被实例化,然而在却创建了Calendar 的对象,但并不是抽象类可以创建对象这个对象并不是Calendar 自身实例,而是其子类实例,这是在getInstan ...

  4. Apache入门篇(四)之LAMP架构部署

    一.LAMP解析 a: apachem: mariadb, mysqlp: php, perl, python 静态资源:静态内容:客户端从服务器获得的资源的表现形式与原文件相同:动态资源:通常是程序 ...

  5. [Bootstrap 源码解析]——bootstrap源码之初始化

    bootstrap源码之初始化 我们先来分析normalize.less编译后的源码,我们知道normalize.css是一个专门将不同浏览器的默认css特性设置为统一效果的css库,它和reset. ...

  6. 安装centos minimal 版本后安装mysql详细过程(linux)

    本文内容参考自:http://www.centoscn.com/mysql/2014/1211/4290.html PS:Yum(全称为 Yellow dog Updater, Modified)是一 ...

  7. 查询表的大小(mysql)

    --所有表的大小 select concat(round(sum(DATA_LENGTH/1024/1024),2),'M') from information_schema.tables where ...

  8. Unity Lighting - Light Types 灯光类型(八)

      Light Types 灯光类型 We have now covered some of the project settings which need to be considered befo ...

  9. Spine with Unity Mecanim

    前言 最近这两天刚刚接触Spine,研究了一下Unity Mecanim Animator如何控制Spine,在此分享记录一下,如有不当之处,请留言指出,欢迎讨论. Unity & Spine ...

  10. C语言零碎知识点

    1.  int整形在64位和32位计算机中都占4个字节. 指针在64位占8个字节,32位占4个字节. 2.  数组下标从0开始,a[0]开始,链表下标从1开始,a[1]开始. 3. 条件运算符(con ...