package com.alibaba.cobar.client;
import static org.testng.AssertJUnit.assertEquals;
import static org.testng.AssertJUnit.assertNotNull;
import static org.testng.AssertJUnit.assertNull;
import static org.testng.AssertJUnit.assertTrue;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import org.apache.commons.lang.ArrayUtils;
import org.springframework.jdbc.core.RowMapper;
import org.testng.annotations.Test;
import com.alibaba.cobar.client.entities.Follower;
import com.alibaba.cobar.client.support.utils.CollectionUtils;
@Test(sequential=true)
public class CobarSqlMapClientTemplateWithSqlActionOnlyRouterTest extends
AbstractTestNGCobarClientTest {
public CobarSqlMapClientTemplateWithSqlActionOnlyRouterTest() {
super(new String[] { "META-INF/spring/cobar-client-appctx.xml",
"META-INF/spring/datasources-appctx.xml",
"META-INF/spring/sqlaction-router-appctx.xml" });
}
public void testInsertOnCobarSqlMapClientWithSqlActionOnlyRules() {
String name = "Darren";
Follower follower = new Follower(name);
getSqlMapClientTemplate().insert("com.alibaba.cobar.client.entities.Follower.create",
follower);
// since no rule for this insert, it will be inserted into default data source, that's, partition1
String confirmSQL = "select name from followers where name='" + name + "'";
verifyEntityExistenceOnSpecificDataSource(confirmSQL, jt1m);
verifyEntityNonExistenceOnSpecificDataSource(confirmSQL, jt1s);
verifyEntityNonExistenceOnSpecificDataSource(confirmSQL, jt2m);
verifyEntityNonExistenceOnSpecificDataSource(confirmSQL, jt2s);
// this sql action is routed to partition2, so can't find any matched record.
Follower followerToFind = (Follower) getSqlMapClientTemplate().queryForObject(
"com.alibaba.cobar.client.entities.Follower.finaByName", name);
assertNull(followerToFind);
// sql action below will be against all of the partitions , so we will get back what we want here
@SuppressWarnings("unchecked")
List<Follower> followers = (List<Follower>) getSqlMapClientTemplate().queryForList(
"com.alibaba.cobar.client.entities.Follower.findAll");
assertTrue(CollectionUtils.isNotEmpty(followers));
assertEquals(1, followers.size());
assertEquals(name, followers.get(0).getName());
}
public void testInsertWithBatchCommitOnCobarSqlMapClientTemplateWithSqlActionOnlyRules() {
String[] names = { "Aaron", "Amily", "Aragon", "Darren", "Darwin" };
batchInsertMultipleFollowersAsFixture(names);
// since no routing rule for insertion, all of the records will be inserted into default data source, that's, partition1
for (String name : names) {
String confirmSQL = "select name from followers where name='" + name + "'";
verifyEntityExistenceOnSpecificDataSource(confirmSQL, jt1m);
verifyEntityNonExistenceOnSpecificDataSource(confirmSQL, jt1s);
verifyEntityNonExistenceOnSpecificDataSource(confirmSQL, jt2m);
verifyEntityNonExistenceOnSpecificDataSource(confirmSQL, jt2s);
}
// since sql action below is routed to partition2, so no record will be found with it.
for (String name : names) {
Follower followerToFind = (Follower) getSqlMapClientTemplate().queryForObject(
"com.alibaba.cobar.client.entities.Follower.finaByName", name);
assertNull(followerToFind);
}
// although records only reside on partition1, but we can get all of them with sql action below
@SuppressWarnings("unchecked")
List<Follower> followers = (List<Follower>) getSqlMapClientTemplate().queryForList(
"com.alibaba.cobar.client.entities.Follower.findAll");
assertTrue(CollectionUtils.isNotEmpty(followers));
assertEquals(names.length, followers.size());
for (Follower f : followers) {
assertTrue(ArrayUtils.contains(names, f.getName()));
}
}
public void testDeleteOnCobarSqlMapClientTemplate() {
String name = "Darren";
String sqlAction = "com.alibaba.cobar.client.entities.Follower.deleteByName";
// no record at beginning
assertEquals(0, getSqlMapClientTemplate().delete(sqlAction, name));
// insert 1 record and delete will affect this record which resides on partition1
Follower follower = new Follower(name);
getSqlMapClientTemplate().insert("com.alibaba.cobar.client.entities.Follower.create",
follower);
assertEquals(1, getSqlMapClientTemplate().delete(sqlAction, name));
// insert 1 record to partition2, delete will NOT affect it because no rule is defined for it.
int updatedRow = jt2m.update("insert into followers(name) values('" + name + "')");
if (updatedRow == 1) // make sure it is do inserted into partition2 successfully.
{
assertEquals(0, getSqlMapClientTemplate().delete(sqlAction, name));
@SuppressWarnings("unchecked")
List<Follower> followers = (List<Follower>) getSqlMapClientTemplate().queryForList(
"com.alibaba.cobar.client.entities.Follower.findAll");
assertTrue(CollectionUtils.isNotEmpty(followers));
assertEquals(1, followers.size());
assertEquals(name, followers.get(0).getName());
}
}
/**
* insert data onto default data source , and query will against all of the
* partitions, so all of the records will be returned as expected.
*/
public void testQueryForListOnCobarSqlMapClientTemplateNormally() {
String[] names = { "Aaron", "Amily", "Aragon", "Darren", "Darwin" };
batchInsertMultipleFollowersAsFixture(names);
@SuppressWarnings("unchecked")
List<Follower> followers = (List<Follower>) getSqlMapClientTemplate().queryForList(
"com.alibaba.cobar.client.entities.Follower.findAll");
assertTrue(CollectionUtils.isNotEmpty(followers));
assertEquals(names.length, followers.size());
for (Follower f : followers) {
assertTrue(ArrayUtils.contains(names, f.getName()));
}
}
/**
* although records are inserted onto patition2, but since the query is
* against all of the data sources, so all of the records will be returned
* as expected.
*/
public void testQueryForListOnCobarSqlMapClientTemplateWithoutDefaultPartitionData() {
String[] names = { "Aaron", "Amily", "Aragon", "Darren", "Darwin" };
batchInsertMultipleFollowersAsFixtureWithJdbcTemplate(names, jt2m);
@SuppressWarnings("unchecked")
List<Follower> followers = (List<Follower>) getSqlMapClientTemplate().queryForList(
"com.alibaba.cobar.client.entities.Follower.findAll");
assertTrue(CollectionUtils.isNotEmpty(followers));
assertEquals(names.length, followers.size());
for (Follower f : followers) {
assertTrue(ArrayUtils.contains(names, f.getName()));
}
}
/**
* insert records onto partition1, but the
* 'com.alibaba.cobar.client.entities.Follower.finaByName' will be performed
* against partition2 as per the routing rule, so no record will be
* returned.
*/
public void testQueryForObjectOnCobarSqlMapClientTemplateWithDefaultPartition() {
String[] names = { "Aaron", "Amily", "Aragon", "Darren", "Darwin" };
batchInsertMultipleFollowersAsFixture(names);
for (String name : names) {
Follower f = (Follower) getSqlMapClientTemplate().queryForObject(
"com.alibaba.cobar.client.entities.Follower.finaByName", name);
assertNull(f);
}
}
/**
* we insert records onto partition2, and the
* 'com.alibaba.cobar.client.entities.Follower.finaByName' action will be
* performed against partition2 too, so each record will be returned as
* expected.
*/
public void testQueryForObjectOnCobarSqlMapClientTemplateWithFillingDataOntoPartition2() {
String[] names = { "Aaron", "Amily", "Aragon", "Darren", "Darwin" };
batchInsertMultipleFollowersAsFixtureWithJdbcTemplate(names, jt2m);
for (String name : names) {
Follower f = (Follower) getSqlMapClientTemplate().queryForObject(
"com.alibaba.cobar.client.entities.Follower.finaByName", name);
assertNotNull(f);
assertTrue(ArrayUtils.contains(names, f.getName()));
}
}
/**
* WARNING: don't do stupid things such like below, we do this because we
* can guarantee the shard id will NOT change. if you want to use cobar
* client corretly, make sure you are partitioning you databases with shard
* id that will not be changed once it's created!!!
* <br>
* with data fixtures setting up on default data source, and update with
* CobarSqlMapClientTemplate.
*/
public void testUpdateOnCobarSqlMapClientTemplateNormally() {
String[] names = { "Aaron", "Amily", "Aragon", "Darren", "Darwin" };
batchInsertMultipleFollowersAsFixture(names);
for(String name:names)
{
Follower f = (Follower)jt1m.queryForObject("select * from followers where name=?",new Object[]{name}, new RowMapper(){
public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
Follower fl = new Follower();
fl.setId(rs.getLong(1));
fl.setName(rs.getString(2));
return fl;
}});
assertNotNull(f);
int updatedCount = getSqlMapClientTemplate().update("com.alibaba.cobar.client.entities.Follower.update", f);
assertEquals(1, updatedCount);
}
}
/**
* WARNING: don't do stupid things such like below, we do this because we
* can guarantee the shard id will NOT change. if you want to use cobar
* client corretly, make sure you are partitioning you databases with shard
* id that will not be changed once it's created!!!
* <br>
* with data fixtures setting up on another data source, and update with
* CobarSqlMapClientTemplate.
*/
public void testUpdateOnCobarSqlMapClientTemplateAbnormally() {
String[] names = { "Aaron", "Amily", "Aragon", "Darren", "Darwin" };
batchInsertMultipleFollowersAsFixtureWithJdbcTemplate(names, jt2m);
for(String name:names)
{
Follower f = (Follower) getSqlMapClientTemplate().queryForObject(
"com.alibaba.cobar.client.entities.Follower.finaByName", name);
assertNotNull(f); // this sql action is performed against partition2 as per routing rule
// sql action below will be performed against default data source(partition1), so will not affect any records on partition2
int updatedCount = getSqlMapClientTemplate().update("com.alibaba.cobar.client.entities.Follower.update", f);
assertEquals(0, updatedCount);
}
}
}