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.SQLException; import java.util.List; import org.apache.commons.lang.ArrayUtils; import org.springframework.dao.DataAccessException; import org.springframework.jdbc.JdbcUpdateAffectedIncorrectNumberOfRowsException; import org.springframework.orm.ibatis.SqlMapClientCallback; import org.testng.annotations.Test; import com.alibaba.cobar.client.entities.Follower; import com.alibaba.cobar.client.entities.Tweet; import com.alibaba.cobar.client.support.utils.CollectionUtils; import com.ibatis.sqlmap.client.SqlMapExecutor; @Test(sequential=true) public class CobarSqlMapClientTemplateWithNamespaceRouterTest extends AbstractTestNGCobarClientTest { public CobarSqlMapClientTemplateWithNamespaceRouterTest() { super(new String[] { "META-INF/spring/cobar-client-appctx.xml", "META-INF/spring/datasources-appctx.xml", "META-INF/spring/namespace-router-appctx.xml" }); } /** * since {@link CobarSqlMapClientTemplate#execute(SqlMapClientCallback)}, * {@link CobarSqlMapClientTemplate#executeWithListResult(SqlMapClientCallback) * )} and * {@link CobarSqlMapClientTemplate#executeWithMapResult(SqlMapClientCallback) * )} don't support partitioning behaviors, we can unit test them together * and use one of them as their representation. */ public void testExecutePrefixMethodsOnCobarSqlMapClientTemplate() { getSqlMapClientTemplate().execute(new SqlMapClientCallback() { public Object doInSqlMapClient(SqlMapExecutor executor) throws SQLException { Follower f = new Follower("fname"); return executor.insert("com.alibaba.cobar.client.entities.Follower.create", f); } }); String confirmSQL = "select name from followers where name='fname'"; // execute method doesn't support partitioning behavior, so the entity will be inserted into default data source, that's , partition1, not partition2 as the rules state. verifyEntityExistenceOnSpecificDataSource(confirmSQL, jt1m); verifyEntityNonExistenceOnSpecificDataSource(confirmSQL, jt1s); verifyEntityNonExistenceOnSpecificDataSource(confirmSQL, jt2m); verifyEntityNonExistenceOnSpecificDataSource(confirmSQL, jt2s); } public void testInsertOnCobarSqlMapClientTemplate() { Tweet t = new Tweet("tcontent"); getSqlMapClientTemplate().insert("com.alibaba.cobar.client.entities.Tweet.create", t); String confirmSQL = "select tweet from tweets where tweet='tcontent'"; verifyEntityExistenceOnSpecificDataSource(confirmSQL, jt1m); verifyEntityNonExistenceOnSpecificDataSource(confirmSQL, jt1s); verifyEntityNonExistenceOnSpecificDataSource(confirmSQL, jt2m); verifyEntityNonExistenceOnSpecificDataSource(confirmSQL, jt2s); Follower f = new Follower("fname"); getSqlMapClientTemplate().insert("com.alibaba.cobar.client.entities.Follower.create", f); confirmSQL = "select name from followers where name='fname'"; verifyEntityNonExistenceOnSpecificDataSource(confirmSQL, jt1m); verifyEntityNonExistenceOnSpecificDataSource(confirmSQL, jt1s); verifyEntityExistenceOnSpecificDataSource(confirmSQL, jt2m); verifyEntityNonExistenceOnSpecificDataSource(confirmSQL, jt2s); } public void testInsertInBatchOnCobarSqlMapClientTemplate() { String[] names = { "Aaron", "Amily", "Aragon", "Darren", "Darwin" }; batchInsertMultipleFollowersAsFixture(names); for (String name : names) { String sql = "select name from followers where name='" + name + "'"; verifyEntityNonExistenceOnSpecificDataSource(sql, jt1m); verifyEntityNonExistenceOnSpecificDataSource(sql, jt1s); verifyEntityExistenceOnSpecificDataSource(sql, jt2m); verifyEntityNonExistenceOnSpecificDataSource(sql, jt2s); } } public void testDeleteOnCobarSqlMapClientTemplate() { Follower f = new Follower("fname"); getSqlMapClientTemplate().insert("com.alibaba.cobar.client.entities.Follower.create", f); String confirmSQL = "select name from followers where name='fname'"; 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); } public void testDeleteWithExpectedResultSizeOnCobarSqlMapClientTemplate() { Follower f = new Follower("fname"); getSqlMapClientTemplate().insert("com.alibaba.cobar.client.entities.Follower.create", f); String confirmSQL = "select name from followers where name='fname'"; 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(); } } 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(5, resultList.size()); 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())); } } public void testQueryForMapOnCobarSqlMapClientTemplate() { // TODO low priority } /** * although we use queryForObject by querying on name column, but it doesn't * mean 'name' column is unique, it's because of the data fixture we set up * to use. */ 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); assertNotNull(follower); } } public void testQueryWithRowHandlerOnCobarSqlMapClientTemplate() { // TODO low priority } /** * 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) { 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()); } } }