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 static org.testng.AssertJUnit.fail;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang.ArrayUtils;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.JdbcUpdateAffectedIncorrectNumberOfRowsException;
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;
import com.alibaba.cobar.client.support.vo.BatchInsertTask;
@Test(sequential=true)
public class CobarSqlMapClientTemplateWithNamespaceShardingRouterTest extends
AbstractTestNGCobarClientTest {
private String insertSQLAction = "com.alibaba.cobar.client.entities.Follower.create";
private String batchInsertSQLAction = "com.alibaba.cobar.client.entities.Follower.batchInsert";
public CobarSqlMapClientTemplateWithNamespaceShardingRouterTest() {
super(new String[] { "META-INF/spring/cobar-client-appctx.xml",
"META-INF/spring/datasources-appctx.xml",
"META-INF/spring/namespace-sharding-router-appctx.xml" });
}
public void testInsertOnCobarSqlMapClientTemplateWithSingleEntityNormally() {
String name = "Darren"; // shard standard
Follower f = new Follower(name);
getSqlMapClientTemplate().insert(insertSQLAction, f);
String sql = "select name from followers where name='" + name + "'";
verifyEntityNonExistenceOnSpecificDataSource(sql, jt1m);
verifyEntityNonExistenceOnSpecificDataSource(sql, jt1s);
verifyEntityExistenceOnSpecificDataSource(sql, jt2m);
verifyEntityNonExistenceOnSpecificDataSource(sql, jt2s);
name = "Aaron";
f = new Follower(name);
getSqlMapClientTemplate().insert(insertSQLAction, f);
sql = "select name from followers where name='" + name + "'";
verifyEntityExistenceOnSpecificDataSource(sql, jt1m);
verifyEntityNonExistenceOnSpecificDataSource(sql, jt2m);
verifyEntityNonExistenceOnSpecificDataSource(sql, jt1s);
verifyEntityNonExistenceOnSpecificDataSource(sql, jt2s);
}
public void testInsertOnCobarSqlMapClientTemplateWithMultipleEntities() {
String[] names = { "Aaron", "Amily", "Aragon", "Darren", "Darwin" };
List<Follower> followers = new ArrayList<Follower>();
for (String name : names) {
followers.add(new Follower(name));
}
/**
* NOTE: if the sqlmap is drafted with invalid format, data access
* exception will be raised, usually, the information of exception
* doesn't tell too much.
*/
getSqlMapClientTemplate().insert(batchInsertSQLAction, new BatchInsertTask(followers));
for (String name : names) {
String sql = "select name from followers where name='" + name + "'";
if (name.startsWith("A")) {
verifyEntityExistenceOnSpecificDataSource(sql, jt1m);
verifyEntityNonExistenceOnSpecificDataSource(sql, jt1s);
verifyEntityNonExistenceOnSpecificDataSource(sql, jt2m);
verifyEntityNonExistenceOnSpecificDataSource(sql, jt2s);
} else {
verifyEntityNonExistenceOnSpecificDataSource(sql, jt1m);
verifyEntityNonExistenceOnSpecificDataSource(sql, jt1s);
verifyEntityExistenceOnSpecificDataSource(sql, jt2m);
verifyEntityNonExistenceOnSpecificDataSource(sql, jt2s);
}
}
}
/**
* if no rule is found for current data access request, the data access
* request will be performed on default data source, that's, partition1.
*/
public void testInsertWithoutFindingRuleOnCobarSqlMapClientTemplate() {
String nameStartsWithS = "Sara";
Follower follower = new Follower(nameStartsWithS);
getSqlMapClientTemplate().insert(insertSQLAction, follower);
String confirmSQL = "select name from followers where name='" + nameStartsWithS + "'";
verifyEntityExistenceOnSpecificDataSource(confirmSQL, jt1m);
verifyEntityNonExistenceOnSpecificDataSource(confirmSQL, jt1s);
verifyEntityNonExistenceOnSpecificDataSource(confirmSQL, jt2m);
verifyEntityNonExistenceOnSpecificDataSource(confirmSQL, jt2s);
}
public void testDeleteOnCobarSqlMapClientTemplate() {
Follower f = new Follower("Darren");
getSqlMapClientTemplate().insert("com.alibaba.cobar.client.entities.Follower.create", f);
String confirmSQL = "select name from followers where name='Darren'";
verifyEntityNonExistenceOnSpecificDataSource(confirmSQL, jt1m);
verifyEntityNonExistenceOnSpecificDataSource(confirmSQL, jt1s);
verifyEntityExistenceOnSpecificDataSource(confirmSQL, jt2m);
verifyEntityNonExistenceOnSpecificDataSource(confirmSQL, jt2s);
getSqlMapClientTemplate().delete("com.alibaba.cobar.client.entities.Follower.deleteByName", f);
verifyEntityNonExistenceOnSpecificDataSource(confirmSQL, jt1m);
verifyEntityNonExistenceOnSpecificDataSource(confirmSQL, jt1s);
verifyEntityNonExistenceOnSpecificDataSource(confirmSQL, jt2m);
verifyEntityNonExistenceOnSpecificDataSource(confirmSQL, jt2s);
}
/**
* MARK!!!
*/
public void testDeleteWithExpectedResultSizeOnCobarSqlMapClientTemplate() {
Follower f = new Follower("Darren");
getSqlMapClientTemplate().insert("com.alibaba.cobar.client.entities.Follower.create", f);
String confirmSQL = "select name from followers where name='Darren'";
verifyEntityNonExistenceOnSpecificDataSource(confirmSQL, jt1m);
verifyEntityNonExistenceOnSpecificDataSource(confirmSQL, jt1s);
verifyEntityExistenceOnSpecificDataSource(confirmSQL, jt2m);
verifyEntityNonExistenceOnSpecificDataSource(confirmSQL, jt2s);
try {
getSqlMapClientTemplate().delete("com.alibaba.cobar.client.entities.Follower.deleteByName",
f, 2);
fail("only one row will be affected in fact.");
} catch (DataAccessException e) {
assertTrue(e instanceof JdbcUpdateAffectedIncorrectNumberOfRowsException);
JdbcUpdateAffectedIncorrectNumberOfRowsException ex = (JdbcUpdateAffectedIncorrectNumberOfRowsException) e;
assertEquals(1, ex.getActualRowsAffected());
}
// although JdbcUpdateAffectedIncorrectNumberOfRowsException is raised, but the delete does performed successfully.
verifyEntityNonExistenceOnSpecificDataSource(confirmSQL, jt1m);
verifyEntityNonExistenceOnSpecificDataSource(confirmSQL, jt1s);
verifyEntityNonExistenceOnSpecificDataSource(confirmSQL, jt2m);
verifyEntityNonExistenceOnSpecificDataSource(confirmSQL, jt2s);
try {
getSqlMapClientTemplate().delete("com.alibaba.cobar.client.entities.Follower.deleteByName",
f, 0);
} catch (DataAccessException e) {
fail();
}
f = new Follower("Amanda");
try {
getSqlMapClientTemplate().delete("com.alibaba.cobar.client.entities.Follower.deleteByName",
f, 0);
} catch (DataAccessException e) {
fail();
}
}
public void testQueryForListOnCobarSqlMapClientTemplate() {
// 1. initialize data
String[] names = { "Aaron", "Amily", "Aragon", "Darren", "Darwin" };
batchInsertMultipleFollowersAsFixture(names);
// 2. perform assertion
@SuppressWarnings("unchecked")
List<Follower> resultList = (List<Follower>) getSqlMapClientTemplate().queryForList(
"com.alibaba.cobar.client.entities.Follower.findAll");
assertTrue(CollectionUtils.isNotEmpty(resultList));
assertEquals(3, resultList.size()); // no rule match 'findAll', so query is performed against default data source - partition1
for (Follower f : resultList) {
assertTrue(ArrayUtils.contains(names, f.getName()));
}
// 3. perform assertion with another different query
@SuppressWarnings("unchecked")
List<Follower> followersWithNameStartsWithA = (List<Follower>) getSqlMapClientTemplate()
.queryForList("com.alibaba.cobar.client.entities.Follower.finaByNameAlike", "A");
assertTrue(CollectionUtils.isNotEmpty(followersWithNameStartsWithA));
assertEquals(3, followersWithNameStartsWithA.size());
for (Follower f : followersWithNameStartsWithA) {
assertTrue(ArrayUtils.contains(names, f.getName()));
}
@SuppressWarnings("unchecked")
List<Follower> followersWithNameStartsWithD = (List<Follower>) getSqlMapClientTemplate()
.queryForList("com.alibaba.cobar.client.entities.Follower.finaByNameAlike", "D");
assertTrue(CollectionUtils.isEmpty(followersWithNameStartsWithD));
}
/**
* adapted from {@link CobarSqlMapClientTemplateWithNamespaceRouterTest}
* with some adjustments.
*/
public void testQueryForObjectOnCobarSqlMapClientTemplate() {
// 1. initialize data
String[] names = { "Aaron", "Amily", "Aragon", "Darren", "Darwin" };
batchInsertMultipleFollowersAsFixture(names);
// 2. assertion.
for (String name : names) {
Follower follower = (Follower) getSqlMapClientTemplate().queryForObject(
"com.alibaba.cobar.client.entities.Follower.finaByName", name);
if (name.startsWith("A")) {
assertNotNull(follower);
} else {
assertNull(follower);
}
}
}
/**
* 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!!!
*/
public void testUpdateOnCobarSqlMapClientTemplate() {
String[] names = { "Aaron", "Amily", "Aragon", "Darren", "Darwin" };
batchInsertMultipleFollowersAsFixture(names);
String nameSuffix = "Wang";
for (String name : names) {
if (name.startsWith("A")) {
Follower follower = (Follower) getSqlMapClientTemplate().queryForObject(
"com.alibaba.cobar.client.entities.Follower.finaByName", name);
assertNotNull(follower);
follower.setName(follower.getName() + nameSuffix);
getSqlMapClientTemplate().update(
"com.alibaba.cobar.client.entities.Follower.update", follower);
Long id = follower.getId();
follower = null;
follower = (Follower) getSqlMapClientTemplate().queryForObject(
"com.alibaba.cobar.client.entities.Follower.finaByName", name);
assertNull(follower);
follower = (Follower) getSqlMapClientTemplate().queryForObject(
"com.alibaba.cobar.client.entities.Follower.load", id);
assertNotNull(follower);
assertEquals(name + nameSuffix, follower.getName());
} else {
String sql = "select * from followers where name=?";
RowMapper rowMapper = new RowMapper() {
public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
Follower f = new Follower();
f.setId(rs.getLong(1));
f.setName(rs.getString(2));
return f;
}
};
Follower follower = (Follower) jt2m.queryForObject(sql, new Object[] { name },
rowMapper);
assertNotNull(follower);
follower.setName(follower.getName() + nameSuffix);
getSqlMapClientTemplate().update(
"com.alibaba.cobar.client.entities.Follower.update", follower);
Long id = follower.getId();
follower = null;
try {
follower = (Follower) jt2m
.queryForObject(sql, new Object[] { name }, rowMapper);
fail();
} catch (DataAccessException e) {
assertTrue(e instanceof EmptyResultDataAccessException);
}
follower = (Follower) jt2m.queryForObject("select * from followers where id=?",
new Object[] { id }, rowMapper);
assertNotNull(follower);
assertEquals(name + nameSuffix, follower.getName());
}
}
}
}