/* * Copyright 2004-2015 the Seasar Foundation and the Others. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. See the License for the specific language * governing permissions and limitations under the License. */ package org.seasar.extension.jdbc.query; import java.sql.PreparedStatement; import java.sql.SQLException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.Map; import javax.persistence.EntityExistsException; import javax.persistence.Lob; import javax.persistence.Temporal; import javax.persistence.TemporalType; import junit.framework.TestCase; import org.seasar.extension.jdbc.JdbcContext; import org.seasar.extension.jdbc.SqlLogRegistry; import org.seasar.extension.jdbc.SqlLogRegistryLocator; import org.seasar.extension.jdbc.dialect.StandardDialect; import org.seasar.extension.jdbc.exception.QueryTwiceExecutionRuntimeException; import org.seasar.extension.jdbc.manager.JdbcManagerImpl; import org.seasar.extension.jdbc.parameter.LobParameter; import org.seasar.extension.jdbc.parameter.Parameter; import org.seasar.extension.jdbc.parameter.TemporalParameter; import org.seasar.extension.jdbc.types.ValueTypes; import org.seasar.extension.jta.TransactionManagerImpl; import org.seasar.extension.jta.TransactionSynchronizationRegistryImpl; import org.seasar.extension.sql.VariableSqlNotAllowedRuntimeException; import org.seasar.framework.exception.ResourceNotFoundRuntimeException; import org.seasar.framework.mock.sql.MockDataSource; import org.seasar.framework.mock.sql.MockPreparedStatement; import org.seasar.framework.util.tiger.CollectionsUtil; import static java.util.Arrays.*; import static org.seasar.extension.jdbc.parameter.Parameter.*; /** * @author taedium * */ public class SqlFileBatchUpdateImplTest extends TestCase { private static final String PATH_SIMPLE = SqlFileBatchUpdateImplTest.class .getName() + "_update_simpleType"; private static final String PATH_DTO = SqlFileBatchUpdateImplTest.class .getName() + "_update_dto"; private static final String PATH_VARIABLE = SqlFileBatchUpdateImplTest.class .getName() + "_update_variable"; private JdbcManagerImpl manager; private int addedBatch; private int executedBatch; private boolean preparedBindVariables; @Override protected void setUp() throws Exception { manager = new JdbcManagerImpl(); manager.setSyncRegistry(new TransactionSynchronizationRegistryImpl( new TransactionManagerImpl())); manager.setDataSource(new MockDataSource()); manager.setDialect(new StandardDialect()); } @Override protected void tearDown() throws Exception { SqlLogRegistry regisry = SqlLogRegistryLocator.getInstance(); regisry.clear(); manager = null; } /** * */ public void testCallerClass() { SqlFileBatchUpdateImpl<Object> query = new SqlFileBatchUpdateImpl<Object>( manager, "aaa.sql", new ArrayList<Object>()); assertSame(query, query.callerClass(getClass())); assertEquals(getClass(), query.callerClass); } /** * */ public void testCallerMethodName() { SqlFileBatchUpdateImpl<Object> query = new SqlFileBatchUpdateImpl<Object>( manager, "aaa.sql", new ArrayList<Object>()); assertSame(query, query.callerMethodName("hoge")); assertEquals("hoge", query.callerMethodName); } /** * */ public void testQueryTimeout() { SqlFileBatchUpdateImpl<Object> query = new SqlFileBatchUpdateImpl<Object>( manager, "aaa.sql", new ArrayList<Object>()); assertSame(query, query.queryTimeout(100)); assertEquals(100, query.queryTimeout); } /** * */ public void testParameterList() { SqlFileBatchUpdateImpl<String> query = new SqlFileBatchUpdateImpl<String>( manager, "aaa.sql", asList("hoge", "hoge2")); assertEquals(2, query.parameterList.size()); Object param = query.parameterList.get(0); assertEquals("hoge", param); param = query.parameterList.get(1); assertEquals("hoge2", param); } /** * */ public void testPrepareNode() { SqlFileBatchUpdateImpl<String> query = new SqlFileBatchUpdateImpl<String>( manager, PATH_SIMPLE, asList("foo", "bar")); query.prepareCallerClassAndMethodName("execute"); query.prepareNode(); assertNotNull(query.node); } /** * */ public void testPrepareNode_resourceNotFound() { SqlFileBatchUpdateImpl<String> query = new SqlFileBatchUpdateImpl<String>( manager, "xxx", asList("foo", "bar")); query.prepareCallerClassAndMethodName("execute"); try { query.prepareNode(); fail(); } catch (ResourceNotFoundRuntimeException e) { System.out.println(e); assertEquals("xxx", e.getPath()); } } /** * */ public void testPrepareNode_disallowVariableSqlForBatch() { manager.setAllowVariableSqlForBatchUpdate(false); SqlFileBatchUpdateImpl<String> query = new SqlFileBatchUpdateImpl<String>( manager, PATH_VARIABLE, asList("foo", "bar")); query.prepareCallerClassAndMethodName("execute"); try { query.prepareNode(); fail(); } catch (VariableSqlNotAllowedRuntimeException expected) { expected.printStackTrace(); } } /** * */ public void testExecuteBatch_simpleType() { SqlFileBatchUpdateImpl<String> query = new SqlFileBatchUpdateImpl<String>( manager, PATH_SIMPLE, asList("foo", "bar")) { @Override protected PreparedStatement getPreparedStatement( JdbcContext jdbcContext) { assertNotNull(executedSql); MockPreparedStatement ps = new MockPreparedStatement(null, null) { @Override public void addBatch() throws SQLException { ++addedBatch; super.addBatch(); } @Override public int[] executeBatch() throws SQLException { ++executedBatch; return new int[] { 1, 1 }; } }; return ps; } @Override protected void prepareInParams(PreparedStatement ps) { preparedBindVariables = true; super.prepareInParams(ps); } }; int[] ret = query.execute(); assertEquals(2, ret.length); assertEquals(2, addedBatch); assertEquals(1, executedBatch); assertTrue(preparedBindVariables); assertEquals("update aaa set name = ? where id = 1", query.sqlContext .getSql()); SqlLogRegistry sqlLogRegistry = SqlLogRegistryLocator.getInstance(); assertEquals(2, sqlLogRegistry.getSize()); assertEquals("update aaa set name = 'foo' where id = 1", sqlLogRegistry .get(0).getCompleteSql()); assertEquals("update aaa set name = 'bar' where id = 1", sqlLogRegistry .get(1).getCompleteSql()); try { query.execute(); fail(); } catch (QueryTwiceExecutionRuntimeException expected) { } } /** * */ public void testExecuteBatch_simpleType_clob() { SqlFileBatchUpdateImpl<LobParameter> query = new SqlFileBatchUpdateImpl<LobParameter>( manager, PATH_SIMPLE, asList(lob("hoge"), lob("foo"))) { @Override protected PreparedStatement getPreparedStatement( JdbcContext jdbcContext) { assertNotNull(executedSql); MockPreparedStatement ps = new MockPreparedStatement(null, null) { @Override public int[] executeBatch() throws SQLException { return new int[] { 1, 1 }; } }; return ps; } @Override protected void resetParams() { assertEquals(1, getParamSize()); assertEquals(ValueTypes.CLOB, getParam(0).valueType); super.resetParams(); } }; query.execute(); } /** * * @throws Exception */ public void testExecuteBatch_simpleType_date() throws Exception { Date date = new SimpleDateFormat("HH:mm:dd").parse("12:11:10"); SqlFileBatchUpdateImpl<TemporalParameter> query = new SqlFileBatchUpdateImpl<TemporalParameter>( manager, PATH_SIMPLE, asList(time(date), time(date))) { @Override protected PreparedStatement getPreparedStatement( JdbcContext jdbcContext) { assertNotNull(executedSql); MockPreparedStatement ps = new MockPreparedStatement(null, null) { @Override public int[] executeBatch() throws SQLException { return new int[] { 1, 1 }; } }; return ps; } @Override protected void resetParams() { assertEquals(1, getParamSize()); assertEquals(ValueTypes.DATE_TIME, getParam(0).valueType); super.resetParams(); } }; query.execute(); } /** * */ public void testExecuteBatch_simpleType_bindNull() { SqlFileBatchUpdateImpl<String> query = new SqlFileBatchUpdateImpl<String>( manager, PATH_SIMPLE, asList("foo", "bar")) { @Override protected PreparedStatement getPreparedStatement( JdbcContext jdbcContext) { assertNotNull(executedSql); MockPreparedStatement ps = new MockPreparedStatement(null, null) { @Override public void addBatch() throws SQLException { ++addedBatch; super.addBatch(); } @Override public int[] executeBatch() throws SQLException { ++executedBatch; return new int[] { 1, 1 }; } }; return ps; } @Override protected void prepareInParams(PreparedStatement ps) { preparedBindVariables = true; super.prepareInParams(ps); } }; try { query.prepareParameter(null); fail(); } catch (NullPointerException ignore) { } } /** * */ public void testExecuteBatch_dto() { MyDto dto = new MyDto(); dto.id = 1; dto.name = "foo"; MyDto dto2 = new MyDto(); dto2.id = 2; dto2.name = "bar"; SqlFileBatchUpdateImpl<MyDto> query = new SqlFileBatchUpdateImpl<MyDto>( manager, PATH_DTO, asList(dto, dto2)) { @Override protected PreparedStatement getPreparedStatement( JdbcContext jdbcContext) { assertNotNull(executedSql); MockPreparedStatement ps = new MockPreparedStatement(null, null) { @Override public void addBatch() throws SQLException { ++addedBatch; super.addBatch(); } @Override public int[] executeBatch() throws SQLException { ++executedBatch; return new int[] { 1, 1 }; } }; return ps; } @Override protected void prepareInParams(PreparedStatement ps) { preparedBindVariables = true; super.prepareInParams(ps); } }; int[] ret = query.execute(); assertEquals(2, ret.length); assertEquals(1, executedBatch); assertEquals(2, addedBatch); assertTrue(preparedBindVariables); assertEquals("update aaa set name = ? where id = ?", query.sqlContext .getSql()); SqlLogRegistry sqlLogRegistry = SqlLogRegistryLocator.getInstance(); assertEquals(2, sqlLogRegistry.getSize()); assertEquals("update aaa set name = 'foo' where id = 1", sqlLogRegistry .get(0).getCompleteSql()); assertEquals("update aaa set name = 'bar' where id = 2", sqlLogRegistry .get(1).getCompleteSql()); } /** * */ public void testExecuteBatch_dto_clob() { MyDto2 dto = new MyDto2(); dto.id = 1; dto.name = "foo"; MyDto2 dto2 = new MyDto2(); dto2.id = 2; dto2.name = "bar"; SqlFileBatchUpdateImpl<MyDto2> query = new SqlFileBatchUpdateImpl<MyDto2>( manager, PATH_DTO, asList(dto, dto2)) { @Override protected PreparedStatement getPreparedStatement( JdbcContext jdbcContext) { assertNotNull(executedSql); MockPreparedStatement ps = new MockPreparedStatement(null, null) { @Override public int[] executeBatch() throws SQLException { return new int[] { 1, 1 }; } }; return ps; } @Override protected void resetParams() { assertEquals(2, getParamSize()); assertEquals(ValueTypes.CLOB, getParam(0).valueType); assertEquals(ValueTypes.INTEGER, getParam(1).valueType); super.resetParams(); } }; query.execute(); } /** * * @throws Exception */ public void testExecuteBatch_dto_date() throws Exception { Date date = new SimpleDateFormat("HH:mm:dd").parse("12:11:10"); MyDto3 dto = new MyDto3(); dto.id = 1; dto.name = date; MyDto3 dto2 = new MyDto3(); dto2.id = 2; dto2.name = date; SqlFileBatchUpdateImpl<MyDto3> query = new SqlFileBatchUpdateImpl<MyDto3>( manager, PATH_DTO, asList(dto, dto2)) { @Override protected PreparedStatement getPreparedStatement( JdbcContext jdbcContext) { assertNotNull(executedSql); MockPreparedStatement ps = new MockPreparedStatement(null, null) { @Override public int[] executeBatch() throws SQLException { return new int[] { 1, 1 }; } }; return ps; } @Override protected void resetParams() { assertEquals(2, getParamSize()); assertEquals(ValueTypes.DATE_TIME, getParam(0).valueType); assertEquals(ValueTypes.INTEGER, getParam(1).valueType); super.resetParams(); } }; query.execute(); } /** * */ public void testExecuteBatch_map() { Map<String, Object> map1 = CollectionsUtil.newHashMap(); map1.put("id", 1); map1.put("name", "foo"); Map<String, Object> map2 = CollectionsUtil.newHashMap(); map2.put("id", 2); map2.put("name", "bar"); @SuppressWarnings("unchecked") SqlFileBatchUpdateImpl<Map<String, Object>> query = new SqlFileBatchUpdateImpl<Map<String, Object>>( manager, PATH_DTO, asList(map1, map2)) { @Override protected PreparedStatement getPreparedStatement( JdbcContext jdbcContext) { assertNotNull(executedSql); MockPreparedStatement ps = new MockPreparedStatement(null, null) { @Override public void addBatch() throws SQLException { ++addedBatch; super.addBatch(); } @Override public int[] executeBatch() throws SQLException { ++executedBatch; return new int[] { 1, 1 }; } }; return ps; } @Override protected void prepareInParams(PreparedStatement ps) { preparedBindVariables = true; super.prepareInParams(ps); } }; int[] ret = query.execute(); assertEquals(2, ret.length); assertEquals(1, executedBatch); assertEquals(2, addedBatch); assertTrue(preparedBindVariables); assertEquals("update aaa set name = ? where id = ?", query.sqlContext .getSql()); SqlLogRegistry sqlLogRegistry = SqlLogRegistryLocator.getInstance(); assertEquals(2, sqlLogRegistry.getSize()); assertEquals("update aaa set name = 'foo' where id = 1", sqlLogRegistry .get(0).getCompleteSql()); assertEquals("update aaa set name = 'bar' where id = 2", sqlLogRegistry .get(1).getCompleteSql()); } /** * */ public void testExecuteBatch_map_clob() { Map<String, Object> map1 = CollectionsUtil.newHashMap(); map1.put("id", 1); map1.put("name", Parameter.lob("foo")); Map<String, Object> map2 = CollectionsUtil.newHashMap(); map2.put("id", 2); map2.put("name", Parameter.lob("bar")); @SuppressWarnings("unchecked") SqlFileBatchUpdateImpl<Map<String, Object>> query = new SqlFileBatchUpdateImpl<Map<String, Object>>( manager, PATH_DTO, asList(map1, map2)) { @Override protected PreparedStatement getPreparedStatement( JdbcContext jdbcContext) { assertNotNull(executedSql); MockPreparedStatement ps = new MockPreparedStatement(null, null) { @Override public int[] executeBatch() throws SQLException { return new int[] { 1, 1 }; } }; return ps; } @Override protected void resetParams() { assertEquals(2, getParamSize()); assertEquals(ValueTypes.CLOB, getParam(0).valueType); assertEquals(ValueTypes.INTEGER, getParam(1).valueType); super.resetParams(); } }; query.execute(); } /** * * @throws Exception */ public void testExecuteBatch_map_date() throws Exception { Date date = new SimpleDateFormat("HH:mm:dd").parse("12:11:10"); Map<String, Object> map1 = CollectionsUtil.newHashMap(); map1.put("id", 1); map1.put("name", Parameter.time(date)); Map<String, Object> map2 = CollectionsUtil.newHashMap(); map2.put("id", 2); map2.put("name", Parameter.time(date)); @SuppressWarnings("unchecked") SqlFileBatchUpdateImpl<Map<String, Object>> query = new SqlFileBatchUpdateImpl<Map<String, Object>>( manager, PATH_DTO, asList(map1, map2)) { @Override protected PreparedStatement getPreparedStatement( JdbcContext jdbcContext) { assertNotNull(executedSql); MockPreparedStatement ps = new MockPreparedStatement(null, null) { @Override public int[] executeBatch() throws SQLException { return new int[] { 1, 1 }; } }; return ps; } @Override protected void resetParams() { assertEquals(2, getParamSize()); assertEquals(ValueTypes.DATE_TIME, getParam(0).valueType); assertEquals(ValueTypes.INTEGER, getParam(1).valueType); super.resetParams(); } }; query.execute(); } /** * */ public void testExecuteBatch_entityExists() { SqlFileBatchUpdateImpl<String> query = new SqlFileBatchUpdateImpl<String>( manager, PATH_SIMPLE, asList("foo", "bar")) { @Override protected PreparedStatement getPreparedStatement( JdbcContext jdbcContext) { assertNotNull(executedSql); MockPreparedStatement ps = new MockPreparedStatement(null, null) { @Override public int[] executeBatch() throws SQLException { throw new SQLException("hoge", "23"); } }; return ps; } @Override protected void prepareInParams(PreparedStatement ps) { preparedBindVariables = true; super.prepareInParams(ps); } }; try { query.execute(); fail(); } catch (EntityExistsException expected) { expected.printStackTrace(); } } /** * */ public void testExecuteBatch_batchSize1() { SqlFileBatchUpdateImpl<String> query = new SqlFileBatchUpdateImpl<String>( manager, PATH_SIMPLE, asList("foo", "bar", "baz")) { @Override protected PreparedStatement getPreparedStatement( JdbcContext jdbcContext) { assertNotNull(executedSql); MockPreparedStatement ps = new MockPreparedStatement(null, null) { @Override public void addBatch() throws SQLException { ++addedBatch; super.addBatch(); } @Override public int[] executeBatch() throws SQLException { ++executedBatch; return executedBatch == 1 ? new int[] { 1, 2 } : new int[] { 3 }; } }; return ps; } @Override protected void prepareInParams(PreparedStatement ps) { preparedBindVariables = true; super.prepareInParams(ps); } }; int[] ret = query.batchSize(2).execute(); assertEquals(3, addedBatch); assertEquals(2, executedBatch); assertEquals(3, ret.length); assertEquals(1, ret[0]); assertEquals(2, ret[1]); assertEquals(3, ret[2]); assertTrue(preparedBindVariables); assertEquals("update aaa set name = ? where id = 1", query.sqlContext .getSql()); SqlLogRegistry sqlLogRegistry = SqlLogRegistryLocator.getInstance(); assertEquals(3, sqlLogRegistry.getSize()); assertEquals("update aaa set name = 'foo' where id = 1", sqlLogRegistry .get(0).getCompleteSql()); assertEquals("update aaa set name = 'bar' where id = 1", sqlLogRegistry .get(1).getCompleteSql()); assertEquals("update aaa set name = 'baz' where id = 1", sqlLogRegistry .get(2).getCompleteSql()); } /** * */ public void testExecuteBatch_batchSize2() { SqlFileBatchUpdateImpl<String> query = new SqlFileBatchUpdateImpl<String>( manager, PATH_SIMPLE, asList("hoge", "foo", "bar", "baz")) { @Override protected PreparedStatement getPreparedStatement( JdbcContext jdbcContext) { assertNotNull(executedSql); MockPreparedStatement ps = new MockPreparedStatement(null, null) { @Override public void addBatch() throws SQLException { ++addedBatch; super.addBatch(); } @Override public int[] executeBatch() throws SQLException { ++executedBatch; return executedBatch == 1 ? new int[] { 1, 2 } : new int[] { 3, 4 }; } }; return ps; } @Override protected void prepareInParams(PreparedStatement ps) { preparedBindVariables = true; super.prepareInParams(ps); } }; int[] ret = query.batchSize(2).execute(); assertEquals(4, addedBatch); assertEquals(2, executedBatch); assertEquals(4, ret.length); assertEquals(1, ret[0]); assertEquals(2, ret[1]); assertEquals(3, ret[2]); assertEquals(4, ret[3]); assertTrue(preparedBindVariables); assertEquals("update aaa set name = ? where id = 1", query.sqlContext .getSql()); SqlLogRegistry sqlLogRegistry = SqlLogRegistryLocator.getInstance(); assertEquals(3, sqlLogRegistry.getSize()); assertEquals("update aaa set name = 'foo' where id = 1", sqlLogRegistry .get(0).getCompleteSql()); assertEquals("update aaa set name = 'bar' where id = 1", sqlLogRegistry .get(1).getCompleteSql()); assertEquals("update aaa set name = 'baz' where id = 1", sqlLogRegistry .get(2).getCompleteSql()); } private static class MyDto { /** * */ public Integer id; /** * */ public String name; } private static class MyDto2 { /** * */ public Integer id; /** * */ @Lob public String name; } private static class MyDto3 { /** * */ public Integer id; /** * */ @Temporal(TemporalType.TIME) public Date name; } }