欢迎访问悦橙教程(wld5.com),关注java教程。悦橙教程  java问答|  每日更新
页面导航 : > > 文章正文

Mybatis 分表插件 shardbatis 0.9使用指南,mybatisshardbatis,shardbatis0.

来源: javaer 分享于  点击 34280 次 点评:242

Mybatis 分表插件 shardbatis 0.9使用指南,mybatisshardbatis,shardbatis0.


shardbatis0.9使用指南

运行环境

jdk5.0+:对于ibatis的扩展基于jdk5.0的api,并且使用jdk5.0进行编译Spring2.5+:使用spring+ibatis的话(这个好像是废话O(∩_∩)O哈哈)

1. 使用ibatis原生api since 0.9.1

添加sharding配置

<!-- 在sql-map-config.xml中添加如下配置 --><shardingConfig>        <!-- 对于app_test使用默认的切分策略,默认的切分策略只是简单按数值取模生成新的表名,如何实现切分策略后面再介绍 -->        <sharding tableName="app_test" strategyClass="com.ibatis.sqlmap.engine.sharding.impl.DefaultShardingStrategy"/>        <!-- 没有配置切分策略等于使用默认的切分策略 -->        <sharding tableName="app_2test" /></shardingConfig><!-- 在sqlmap.xml中statement节点都可以添加shardingParams属性shardingParams对应的值使用json数组格式,paramExpr 对应parameterClass对象中的某个属性,这个属性的值会传递给sharding策略用于计算新的表名,例如paramExpr:testId 等同于appTest.getTestId;paramExpr:model.id 等同于appTest.getModel().getId()tableName 用于表示当前这个json对象配使用于sql中的哪个表strategyClass strateg接口实现类的全名,这个值如果没有将使用sql-map-config.xml里shardingConfig下配置对应的值。--><select id="select_count_native" parameterClass="AppTest" resultClass="java.lang.Integer" shardingParams='[{"paramExpr":"testId","tableName":"app_test"}]'>select count(*) from app_test where cnt=#cnt#</select>

下面开始编码

AppTest param=new AppTest();param.setTestId(2);param.setCnt("testShardingWithConfig");Integer count=(Integer)sqlMapper.queryForObject("AppTest.select_count_native",param);//和使用原生的ibatis API没有区别

最终执行的SQL可能是如下样式

select count(*) from app_test_1 where cnt=?

2. 使用ibatis sharding API

添加sharding配置。在sql-map-config.xml中添加如下配置

<shardingConfig>        <!-- 对于app_test使用默认的切分策略,默认的切分策略只是简单按数值取模生成新的表名,如何实现切分策略后面再介绍 -->        <sharding tableName="app_test" strategyClass="com.ibatis.sqlmap.engine.sharding.impl.DefaultShardingStrategy"/>        <!-- 没有配置切分策略等于使用默认的切分策略 -->        <sharding tableName="app_2test" /></shardingConfig>

完成配置请参考http://shardbatis.googlecode.com/svn/trunk/src/test/resources/sql-map-config.xml

使用sharding API

public class SqlMapClientTest {        SqlMapClient sqlMapper;        @Before        public void init() {                Reader reader;                try {                        reader = Resources.getResourceAsReader("sql-map-config.xml");                        sqlMapper = SqlMapClientBuilder.buildSqlMapClient(reader);                        reader.close();                } catch (IOException e) {                        // TODO Auto-generated catch block                        e.printStackTrace();                }        }        @Test        public void testSharding() throws Exception {                Map param = new HashMap();                param.put("cnt", "ttt");                ShardingFactorGroup g = new ShardingFactorGroup();//ShardingFactorGroup为切分策略提供必要参数                g.setTableName("App_Test");//设置为哪张表配置切分策略                g.setParam(new Integer(123));//设置为切分策略提供参数                //这里还可以通过g.setShardingStrategy(...)来设置切分策略                //通过API配置的切分策略可以覆盖xml里配置的App_Test表的切分策略                Integer count = (Integer) sqlMapper.queryForObjectWithSharding(                                "AppTest.select_paging_count_by_map", param, g);                Assert.assertEquals(count.toString(), "0");        }        @Test        public void testUpdate() throws SQLException {                ShardingFactorGroup g = new ShardingFactorGroup();                g.setTableName("App_Test");                g.setParam(new Integer(123));                String cnt = "testUpdate" + System.currentTimeMillis();                AppTest at1 = new AppTest();                at1.setCnt(cnt);                Integer id = (Integer) sqlMapper.insertWithSharding(                                "AppTest.insert_h2", at1, g);                AppTest parameterObject = new AppTest();                parameterObject.setCnt(cnt);                AppTest ret = (AppTest) sqlMapper.queryForObjectWithSharding(                                "AppTest.select_by_condition", parameterObject, g);                Assert.assertEquals(ret.getId().toString(), id.toString());                ret.setCnt("NEW_CONTENT");                Integer count = sqlMapper.updateWithSharding("AppTest.update", ret, g);                Assert.assertEquals(count.toString(), "1");                count = (Integer) sqlMapper.queryForObjectWithSharding(                                "AppTest.select_paging_count", ret, g);                Assert.assertEquals(count.toString(), "1");        }        @Test        public void testDelete() throws SQLException {                ShardingFactorGroup g = new ShardingFactorGroup();                g.setTableName("App_Test");                g.setParam(new Integer(123));                String cnt = "testDelete" + System.currentTimeMillis();                AppTest at1 = new AppTest();                at1.setCnt(cnt);                Integer id = (Integer) sqlMapper.insertWithSharding(                                "AppTest.insert_h2", at1, g);                AppTest parameterObject = new AppTest();                parameterObject.setCnt(cnt);                AppTest ret = (AppTest) sqlMapper.queryForObjectWithSharding(                                "AppTest.select_by_condition", parameterObject, g);                Assert.assertEquals(ret.getId().toString(), id.toString());                Integer row = sqlMapper.deleteWithSharding("AppTest.delete", ret, g);                Assert.assertEquals(row.toString(), "1");        }}

具体代码可以查看org.shardbatis.test.ibatis.SqlMapClientTest

注意使用api方式将优先于配置,通过api传递的sharding参数可以覆盖原xml中的配置

3.使用spring+ibatis sharding API

ibatis配置

请参考http://shardbatis.googlecode.com/svn/trunk/src/test/resources/sql-map-config-spring.xml

spring关键配置

<bean id="sqlMapClient"        class="org.springframework.orm.ibatis.SqlMapClientFactoryBean" lazy-init="false">        <property name="configLocation"                value="classpath:/sql-map-config-spring.xml" /><!-- 使用带有sharding配置的配置ibatis配置文件 -->        <property name="dataSource" ref="dataSource" /></bean><!-- 配置shardbatis为spring重新实现的sqlmapclienttemplate --><bean id="sqlMapClientWithShardingTemplate"        class="org.shardbatis.spring.orm.SqlMapClientWithShardingTemplate" lazy-init="false">        <property name="sqlMapClient" ref="sqlMapClient" /></bean><!-- 将新的sqlMapClientWithShardingTemplate注入到应用的dao中 --><bean id="testDao" class="org.shardbatis.test.spring.TestDao">        <property name="sqlMapClientTemplate" ref="sqlMapClientWithShardingTemplate" /></bean>

完整spring配置请参考http://shardbatis.googlecode.com/svn/trunk/src/test/resources/applicationContext-test.xml

DAO实现

/** * 应用的DAO要继承SqlMapClientWithShardingDaoSupport */public class TestDao extends SqlMapClientWithShardingDaoSupport {        public <T> T get(Class<T> entityClass, Object param,                        String statementName,ShardingFactorGroup... groups) {                //通过getSqlMapClientWithShardingTemplate方法得到SqlMapClientWithShardingTemplate 的引用                SqlMapClientWithShardingTemplate template=this.getSqlMapClientWithShardingTemplate();                return (T)template.queryForObjectWithSharding(statementName, param, groups);        }        public void remove(Object parameterObject,String statementName,ShardingFactorGroup... groups) {                SqlMapClientWithShardingTemplate template=getSqlMapClientWithShardingTemplate();                template.deleteWithSharding(statementName, parameterObject, groups);        }        public int insert(Object parameterObject,String statementName,ShardingFactorGroup... groups) {                SqlMapClientWithShardingTemplate template=getSqlMapClientWithShardingTemplate();                return (Integer) template.insertWithSharding(statementName, parameterObject, groups);        }}

实现自己的sharding策略

实现一个简单的接口即可

public interface ShardingStrategy {        /**         * 计算得到新的表名         * @param baseTableName 逻辑表名         * @param params 为sharding逻辑提供必要参数         * @return          */        public String getTargetTableName(String baseTableName,Object params);}

可以参考http://shardbatis.googlecode.com/svn/trunk/src/main/java/com/ibatis/sqlmap/engine/sharding/impl/DefaultShardingStrategy.java

使用注意事项

0.9版本中insert update delete 语句中的子查询语句中的表不支持sharding(不好意思太拗口了-_-!)select语句中如果进行多表关联,请务必为每个表名加上别名

例如原始sql语句:SELECT a.* FROM ANTIQUES a,ANTIQUEOWNERS b, mytable c where a.id=b.id and b.id=c.id

经过转换后的结果可能为:SELECT a.* FROM ANTIQUES_0 AS a, ANTIQUEOWNERS_1 AS b, mytable_1 AS c WHERE a.id = b.id AND b.id = c.id

目前已经支持了大部分的sql语句的解析,已经测试通过的语句可以查看测试代码:http://shardbatis.googlecode.com/svn/trunk/src/test/java/org/shardbatis/test/ibatis/ConverterTest.java

可能有些sql语句没有出现在测试用例里,但是相信基本上常用的查询sql shardbatis解析都没有问题,因为shardbatis对sql的解析是基于jsqlparser

性能测试结果

50个线程并发,每个线程循环执行100次数据库(h2数据库)查询。

下面的测试结果建议关注两种场景的比较值,而不是关注某个具体值(你懂的)

jdk:1.5.0_22 无jvm参数

单位:毫秒

场景  20线程    30线程    50线程    50线程use jdk6sharding    690.721 1051.983778 1708.146467 1584.499067no sharding 683.7596667 1024.096444 1704.1314   1601.5926

在maven中使用(推荐)

<!-- 新增远程仓库设置 --><repository>        <id>shardbaits</id>        <name>shardbaits repository</name>        <url>http://shardbatis.googlecode.com/svn/trunk/repository</url>        <snapshots>                <enabled>false</enabled>        </snapshots></repository><!-- 声明依赖 --><dependency>        <groupId>org.shardbatis</groupId>        <artifactId>shardbatis</artifactId>        <version>0.9.2B</version></dependency>

手工添加到项目classpath中

相关栏目:

用户点评