1 package jp.sourceforge.ea2ddl.dao.allcommon.s2dao;
\r
3 import java.lang.reflect.Method;
\r
4 import java.lang.reflect.ParameterizedType;
\r
5 import java.lang.reflect.Type;
\r
6 import java.sql.Connection;
\r
7 import java.sql.DatabaseMetaData;
\r
8 import java.sql.PreparedStatement;
\r
9 import java.sql.ResultSet;
\r
10 import java.sql.SQLException;
\r
11 import java.sql.Statement;
\r
12 import java.util.ArrayList;
\r
13 import java.util.List;
\r
15 import javax.sql.DataSource;
\r
17 import org.seasar.dao.BeanEnhancer;
\r
18 import org.seasar.dao.BeanMetaData;
\r
19 import org.seasar.dao.BeanMetaDataFactory;
\r
20 import org.seasar.dao.ColumnNaming;
\r
21 import org.seasar.dao.PropertyTypeFactoryBuilder;
\r
22 import org.seasar.dao.RelationPropertyTypeFactoryBuilder;
\r
23 import org.seasar.dao.RelationRowCreator;
\r
24 import org.seasar.dao.RowCreator;
\r
25 import org.seasar.dao.SqlCommand;
\r
26 import org.seasar.dao.TableNaming;
\r
27 import org.seasar.dao.dbms.DbmsManager;
\r
28 import org.seasar.dao.impl.BeanMetaDataImpl;
\r
29 import org.seasar.dao.impl.DaoMetaDataImpl;
\r
30 import org.seasar.dao.impl.ResultSetHandlerFactoryImpl;
\r
31 import org.seasar.dao.impl.SelectDynamicCommand;
\r
32 import org.seasar.dao.impl.UpdateAutoStaticCommand;
\r
33 import org.seasar.extension.jdbc.ResultSetHandler;
\r
34 import org.seasar.extension.jdbc.StatementFactory;
\r
35 import org.seasar.extension.jdbc.ValueType;
\r
36 import org.seasar.extension.jdbc.types.ValueTypes;
\r
37 import org.seasar.framework.beans.MethodNotFoundRuntimeException;
\r
38 import org.seasar.framework.beans.factory.BeanDescFactory;
\r
39 import org.seasar.framework.util.MethodUtil;
\r
41 import jp.sourceforge.ea2ddl.dao.allcommon.BehaviorSelector;
\r
42 import jp.sourceforge.ea2ddl.dao.allcommon.Entity;
\r
43 import jp.sourceforge.ea2ddl.dao.allcommon.annotation.OutsideSql;
\r
44 import jp.sourceforge.ea2ddl.dao.allcommon.cbean.ConditionBean;
\r
45 import jp.sourceforge.ea2ddl.dao.allcommon.cbean.ConditionBeanContext;
\r
46 import jp.sourceforge.ea2ddl.dao.allcommon.cbean.outsidesql.OutsideSqlContext;
\r
47 import jp.sourceforge.ea2ddl.dao.allcommon.dbmeta.DBMeta;
\r
48 import jp.sourceforge.ea2ddl.dao.allcommon.exception.EntityAlreadyDeletedException;
\r
49 import jp.sourceforge.ea2ddl.dao.allcommon.exception.BatchEntityAlreadyUpdatedException;
\r
50 import jp.sourceforge.ea2ddl.dao.allcommon.exception.EntityDuplicatedException;
\r
51 import jp.sourceforge.ea2ddl.dao.allcommon.jdbc.CursorHandler;
\r
52 import jp.sourceforge.ea2ddl.dao.allcommon.s2dao.internal.rshandler.InternalBeanListMetaDataResultSetHandler;
\r
53 import jp.sourceforge.ea2ddl.dao.allcommon.s2dao.internal.rshandler.InternalBeanArrayMetaDataResultSetHandler;
\r
54 import jp.sourceforge.ea2ddl.dao.allcommon.s2dao.internal.sqlcommand.InternalDeleteAutoStaticCommand;
\r
55 import jp.sourceforge.ea2ddl.dao.allcommon.s2dao.internal.sqlcommand.InternalDeleteBatchAutoStaticCommand;
\r
56 import jp.sourceforge.ea2ddl.dao.allcommon.s2dao.internal.sqlcommand.InternalDeleteQueryAutoDynamicCommand;
\r
57 import jp.sourceforge.ea2ddl.dao.allcommon.s2dao.internal.sqlcommand.InternalInsertAutoDynamicCommand;
\r
58 import jp.sourceforge.ea2ddl.dao.allcommon.s2dao.internal.sqlcommand.InternalInsertBatchAutoStaticCommand;
\r
59 import jp.sourceforge.ea2ddl.dao.allcommon.s2dao.internal.sqlcommand.InternalProcedureCommand;
\r
60 import jp.sourceforge.ea2ddl.dao.allcommon.s2dao.internal.sqlcommand.InternalUpdateAutoDynamicCommand;
\r
61 import jp.sourceforge.ea2ddl.dao.allcommon.s2dao.internal.sqlcommand.InternalUpdateBatchAutoStaticCommand;
\r
62 import jp.sourceforge.ea2ddl.dao.allcommon.s2dao.internal.sqlcommand.InternalUpdateDynamicCommand;
\r
63 import jp.sourceforge.ea2ddl.dao.allcommon.s2dao.internal.sqlcommand.InternalUpdateModifiedOnlyCommand;
\r
64 import jp.sourceforge.ea2ddl.dao.allcommon.s2dao.internal.sqlcommand.InternalUpdateQueryAutoDynamicCommand;
\r
65 import jp.sourceforge.ea2ddl.dao.allcommon.s2dao.internal.sqlhandler.InternalBasicHandler.SQLExceptionHandler;
\r
66 import jp.sourceforge.ea2ddl.dao.allcommon.s2dao.internal.sqlhandler.InternalUpdateBatchAutoHandler;
\r
67 import jp.sourceforge.ea2ddl.dao.allcommon.s2dao.internal.sqlhandler.InternalDeleteBatchAutoHandler;
\r
68 import jp.sourceforge.ea2ddl.dao.allcommon.s2dao.internal.various.InternalProcedureMetaData;
\r
69 import jp.sourceforge.ea2ddl.dao.allcommon.s2dao.internal.various.InternalProcedureMetaDataFactory;
\r
70 import jp.sourceforge.ea2ddl.dao.allcommon.s2dao.internal.various.InternalRowCreator;
\r
71 import jp.sourceforge.ea2ddl.dao.allcommon.s2dao.internal.various.InternalRelationRowCreator;
\r
72 import jp.sourceforge.ea2ddl.dao.allcommon.util.SimpleSystemUtil;
\r
75 * The extension of DaoMetaDataImpl for DBFlute.
\r
76 * @author DBFlute(AutoGenerator)
\r
78 @SuppressWarnings("unchecked")
\r
79 public class S2DaoMetaDataExtension extends DaoMetaDataImpl {
\r
81 // ===================================================================================
\r
84 /** Log instance. */
\r
85 private static final org.apache.commons.logging.Log _log = org.apache.commons.logging.LogFactory.getLog(S2DaoMetaDataExtension.class);
\r
87 // ===================================================================================
\r
90 /** Bean enhancer. */
\r
91 protected BeanEnhancer beanEnhancer;
\r
93 /** The factory of annotation reader. */
\r
94 protected org.seasar.dao.AnnotationReaderFactory annotationReaderFactory;
\r
96 /** The naming of column. {After S2Dao-1.0.47} */
\r
97 protected ColumnNaming columnNaming;
\r
99 /** The builder of property type factory. {After S2Dao-1.0.47} */
\r
100 protected PropertyTypeFactoryBuilder propertyTypeFactoryBuilder;
\r
102 /** The builder of relation property type factory. {After S2Dao-1.0.47} */
\r
103 protected RelationPropertyTypeFactoryBuilder relationPropertyTypeFactoryBuilder;
\r
105 /** The builder of table naming. {After S2Dao-1.0.47} */
\r
106 protected TableNaming tableNaming;
\r
108 // -----------------------------------------------------
\r
109 // DBFlute Extension
\r
110 // -----------------
\r
111 /** The selector of behavior. {Since DBFlute-0.7.1} */
\r
112 protected BehaviorSelector _behaviorSelector;
\r
114 /** The lock monitor of method initialization. */
\r
115 protected Object _methodInitializationLockMonitor = new Object();
\r
117 /** The determination of internal debug. {Since DBFlute-0.6.2} */
\r
118 protected boolean _internalDebug;
\r
120 // ===================================================================================
\r
123 public S2DaoMetaDataExtension() {
\r
126 // ===================================================================================
\r
127 // Initialize Override
\r
128 // ===================
\r
130 public void initialize() {
\r
131 beanClass = daoAnnotationReader.getBeanClass();
\r
132 daoInterface = getDaoInterface(daoClass);
\r
133 daoBeanDesc = BeanDescFactory.getBeanDesc(daoClass);
\r
134 final Connection conn = getConnection();// It is first impact to Database!
\r
136 final DatabaseMetaData dbMetaData = getMetaData(conn);
\r
137 dbms = DbmsManager.getDbms(getDatabaseProductName(dbMetaData));
\r
141 this.beanMetaData = beanMetaDataFactory.createBeanMetaData(daoInterface, beanClass);
\r
142 checkSingleRowUpdateForAll = daoAnnotationReader.isCheckSingleRowUpdate();
\r
144 // Comment out for lazy-load!
\r
145 // setupSqlCommand();
\r
148 // ===================================================================================
\r
149 // SqlCommand Setup Override
\r
150 // =========================
\r
152 public SqlCommand getSqlCommand(String methodName) throws MethodNotFoundRuntimeException {
\r
153 SqlCommand cmd = (SqlCommand) sqlCommands.get(methodName);
\r
157 synchronized (_methodInitializationLockMonitor) {
\r
158 cmd = (SqlCommand) sqlCommands.get(methodName);
\r
160 if (_log.isDebugEnabled()) {
\r
161 _log.debug("...Getting sqlCommand as cache because the previous thread have already initilized.");
\r
165 if (_log.isDebugEnabled()) {
\r
166 _log.debug("...Initializing sqlCommand for " + methodName + "().");
\r
168 cmd = initializeSqlCommand(methodName);
\r
173 protected SqlCommand initializeSqlCommand(String methodName) throws MethodNotFoundRuntimeException {
\r
174 if (OutsideSqlContext.isExistOutsideSqlContextOnThread()) {
\r
175 final OutsideSqlContext outsideSqlContext = OutsideSqlContext.getOutsideSqlContextOnThread();
\r
176 if (outsideSqlContext != null && outsideSqlContext.isSpecifiedOutsideSql()) {
\r
177 return initializeSpecifiedOutsideSqlCommand(methodName, outsideSqlContext);
\r
180 final Method[] methods = daoBeanDesc.getMethods(methodName);
\r
181 if (methods.length == 1 && MethodUtil.isAbstract(methods[0])) {
\r
182 setupMethod(methods[0]);
\r
184 final SqlCommand cmd = (SqlCommand) sqlCommands.get(methodName);
\r
188 throw new MethodNotFoundRuntimeException(daoClass, methodName, null);
\r
191 protected SqlCommand initializeSpecifiedOutsideSqlCommand(String sqlCommandKey, OutsideSqlContext outsideSqlContext) throws MethodNotFoundRuntimeException {
\r
192 final Method[] methods = daoBeanDesc.getMethods(outsideSqlContext.getMethodName());// By real method name.
\r
193 if (methods.length == 1 && org.seasar.framework.util.MethodUtil.isAbstract(methods[0])) {
\r
194 final Method method = methods[0];
\r
195 if (isOutsideSqlDaoMethodSelect(method)) {
\r
196 setupSpecifiedOutsideSqlSelectCommand(sqlCommandKey, method, outsideSqlContext);
\r
197 } else if (isOutsideSqlDaoMethodCall(method)) {
\r
198 setupSpecifiedOutsideSqlCallCommand(sqlCommandKey, method, outsideSqlContext);
\r
200 setupSpecifiedOutsideSqlExecuteCommand(sqlCommandKey, method, outsideSqlContext);
\r
203 final SqlCommand cmd = (SqlCommand) sqlCommands.get(sqlCommandKey);
\r
207 String msg = "Internal Error! The sql-command is not found:";
\r
208 msg = msg + " sqlCommandKey=" + sqlCommandKey;
\r
209 msg = msg + " sqlCommands=" + sqlCommands;
\r
210 throw new IllegalStateException(msg);
\r
213 protected boolean isOutsideSqlDaoMethodSelect(Method method) {
\r
214 return method.getName().startsWith("select");
\r
217 protected boolean isOutsideSqlDaoMethodCall(Method method) {
\r
218 return method.getName().startsWith("call");
\r
221 // ===================================================================================
\r
225 protected void setupMethodByAnnotation(Class daoInterface, Method method) {
\r
226 final String sql = daoAnnotationReader.getSQL(method, dbms.getSuffix());
\r
227 assertSQLAnnotationUnsupported(method, sql);
\r
228 super.setupMethodByAnnotation(daoInterface, method);
\r
231 protected void assertSQLAnnotationUnsupported(final Method method, String sql) {
\r
233 throwS2DaoSQLAnnotationUnsupportedException(method, sql);
\r
237 protected void throwS2DaoSQLAnnotationUnsupportedException(final Method method, String sql) {
\r
238 String msg = "Look! Read the message below." + getLineSeparator();
\r
239 msg = msg + "/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *" + getLineSeparator();
\r
240 msg = msg + "Sorry, the SQL annotation of S2Dao is unsupported on DBFlute!" + getLineSeparator();
\r
241 msg = msg + getLineSeparator();
\r
242 msg = msg + "[Advice]" + getLineSeparator();
\r
243 msg = msg + "Please use outside-sql of behavior." + getLineSeparator();
\r
244 msg = msg + " For example:" + getLineSeparator();
\r
245 msg = msg + " memberBhv.outsideSql().selectList(...)" + getLineSeparator();
\r
246 msg = msg + getLineSeparator();
\r
247 msg = msg + "If you've got to use it, you can set the property:" + getLineSeparator();
\r
248 msg = msg + "{torque.isCompatibleS2DaoSQLAnnotationValid = true}" + getLineSeparator();
\r
249 msg = msg + "But pay attention to version up of DBFlute" + getLineSeparator();
\r
250 msg = msg + " because the property will not always supported at the future." + getLineSeparator();
\r
251 msg = msg + getLineSeparator();
\r
252 msg = msg + "[Method]" + getLineSeparator() + method + getLineSeparator();
\r
253 msg = msg + getLineSeparator();
\r
254 msg = msg + "[SQL]" + getLineSeparator() + sql + getLineSeparator();
\r
255 msg = msg + "* * * * * * * * * */";
\r
256 throw new UnsupportedOperationException(msg);
\r
260 protected void setupMethodByAuto(Method method) {
\r
261 final OutsideSql outsideSql = method.getAnnotation(OutsideSql.class);
\r
262 if (outsideSql != null) {
\r
263 String msg = "This method '" + method.getName() + "()' should use Outside Sql but the file was not found!";
\r
264 msg = msg + " Expected sql file name is '" + method.getDeclaringClass().getSimpleName() + "_" + method.getName() + ".sql'";
\r
265 throw new IllegalStateException(msg);
\r
267 super.setupMethodByAuto(method);
\r
270 // ===================================================================================
\r
271 // ConditionBean Override
\r
272 // ======================
\r
274 protected void setupSelectMethodByAuto(final Method method) {
\r
275 if (setupInternalSelectMethodSequenceNextVal(method)) { // For sequence
\r
278 if (setupInternalSelectMethodEntityByIdsForBuri(method)) { // For Buri
\r
282 // Assert unsupported
\r
283 final String query = daoAnnotationReader.getQuery(method);
\r
284 assertQueryAnnotationUnsupported(method, query);
\r
285 final String[] argNames = daoAnnotationReader.getArgNames(method);
\r
286 assertAutoQueryByArgsAnnotationUnsupported(method, argNames);
\r
288 // Here it is the only method that the argument is DTO.
\r
289 final ResultSetHandler handler = createResultSetHandler(method);
\r
290 final SqlCommand cmd = setupInternalNonQuerySelectMethodByDto(method, handler);
\r
292 putSqlCommand(method.getName(), cmd);
\r
295 protected boolean setupInternalSelectMethodSequenceNextVal(final Method method) { // For sequence
\r
296 if (!"selectNextVal".equals(method.getName())) {
\r
299 final DBMeta dbmeta = findDBMeta();
\r
300 if (!dbmeta.hasSequence()) {
\r
301 String msg = "If the method 'selectNextVal()' exists, DBMeta.hasSequence() should return true:";
\r
302 msg = msg + " dbmeta.hasSequence()=" + dbmeta.hasSequence() + " method=" + method;
\r
303 throw new IllegalStateException(msg);
\r
305 final String nextValSql = dbmeta.getSequenceNextValSql();
\r
306 if (nextValSql == null) {
\r
307 String msg = "If the method 'selectNextVal()' exists, DBMeta.getSequenceNextValSql() should not return null:";
\r
308 msg = msg + " dbmeta.getSequenceNextValSql()=" + dbmeta.getSequenceNextValSql() + " method=" + method;
\r
309 throw new IllegalStateException(msg);
\r
311 setupSelectMethodByManual(method, nextValSql);
\r
315 protected boolean setupInternalSelectMethodEntityByIdsForBuri(final Method method) { // For Buri
\r
316 if (!"getEntityByIds".equals(method.getName())) {
\r
319 final ResultSetHandler handler = createResultSetHandler(method);
\r
320 final String[] argNames = daoAnnotationReader.getArgNames(method);
\r
321 final String query = daoAnnotationReader.getQuery(method);
\r
322 if (query == null) {
\r
323 String msg = "The method 'getEntityByIds()' should have QUERY annotation:";
\r
324 msg = msg + " method=" + method;
\r
325 throw new IllegalStateException(msg);
\r
327 final Class[] types = method.getParameterTypes();
\r
328 final SelectDynamicCommand cmd = createSelectDynamicCommand(handler, query);
\r
329 cmd.setArgNames(argNames);
\r
330 cmd.setArgTypes(types);
\r
331 putSqlCommand(method.getName(), cmd);
\r
335 protected void assertQueryAnnotationUnsupported(final Method method, String query) {
\r
336 if (query != null) {
\r
337 String msg = "Sorry! The QUERY annotation of S2Dao is unsupported on DBFlute:";
\r
338 msg = msg + " query=" + query + " method=" + method;
\r
339 throw new UnsupportedOperationException(msg);
\r
343 protected void assertAutoQueryByArgsAnnotationUnsupported(final Method method, String[] argNames) {
\r
344 if (!isAutoSelectSqlByDto(method, argNames)) {
\r
345 String msg = "Sorry! The auto query by ARGS annotation of S2Dao is unsupported on DBFlute:";
\r
346 msg = msg + " argNames=" + argNames + " method=" + method;
\r
347 throw new UnsupportedOperationException(msg);
\r
351 // For condition-bean!
\r
352 protected SqlCommand setupInternalNonQuerySelectMethodByDto(Method method, ResultSetHandler handler) {
\r
353 final Class[] argTypes = method.getParameterTypes();
\r
354 assertAutoQueryByDtoUnsupported(method, argTypes);
\r
355 final S2DaoSelectDynamicCommand cmd = createCustomizeSelectDynamicCommand(handler);
\r
356 cmd.setArgNames(new String[] { "dto" });
\r
357 cmd.setArgTypes(argTypes);
\r
361 protected void assertAutoQueryByDtoUnsupported(final Method method, Class[] argTypes) {
\r
362 final Class firstArgType = argTypes[0];
\r
363 if (!ConditionBeanContext.isTheTypeConditionBean(firstArgType)) {
\r
364 String msg = "Sorry! The auto query by DTO of S2Dao is unsupported on DBFlute:";
\r
365 msg = msg + " dto=" + firstArgType + " method=" + method;
\r
366 throw new UnsupportedOperationException(msg);
\r
370 // ===================================================================================
\r
371 // Insert and Update and Delete By Auto Override
\r
372 // =============================================
\r
373 // -----------------------------------------------------
\r
377 protected void setupInsertMethodByAuto(final Method method) {
\r
378 checkAutoUpdateMethod(method);
\r
379 final String[] propertyNames = getPersistentPropertyNames(method);
\r
380 final SqlCommand command;
\r
381 if (isUpdateSignatureForBean(method)) {
\r
382 final InternalInsertAutoDynamicCommand cmd = new InternalInsertAutoDynamicCommand();
\r
383 cmd.setBeanMetaData(getBeanMetaData());
\r
384 cmd.setDataSource(dataSource);
\r
386 // It is unnecessary for DBFlute!
\r
387 // cmd.setNotSingleRowUpdatedExceptionClass(getNotSingleRowUpdatedExceptionClass(method));
\r
389 cmd.setPropertyNames(propertyNames);
\r
390 cmd.setStatementFactory(statementFactory);
\r
391 cmd.setCheckSingleRowUpdate(isCheckSingleRowUpdate(method));
\r
394 boolean returningRows = false;
\r
395 if (int[].class.isAssignableFrom(method.getReturnType())) {
\r
396 returningRows = true;
\r
398 final InternalInsertBatchAutoStaticCommand cmd = new InternalInsertBatchAutoStaticCommand(
\r
399 dataSource, statementFactory, getBeanMetaData(),
\r
400 propertyNames, returningRows);
\r
403 putSqlCommand(method.getName(), command);
\r
406 // -----------------------------------------------------
\r
410 protected void setupUpdateMethodByAuto(final Method method) {
\r
411 if (isFirstArgumentConditionBean(method)) {
\r
412 final SqlCommand cmd = new InternalUpdateQueryAutoDynamicCommand(dataSource, statementFactory);
\r
413 putSqlCommand(method.getName(), cmd);
\r
416 checkAutoUpdateMethod(method);
\r
417 final String[] propertyNames = getPersistentPropertyNames(method);
\r
419 if (isUpdateSignatureForBean(method)) {
\r
420 if (isUnlessNull(method.getName())) {
\r
421 cmd = createInternalUpdateAutoDynamicCommand(method, propertyNames);
\r
422 } else if (isModifiedOnly(method.getName())) {
\r
423 cmd = createInternalUpdateModifiedOnlyCommand(method, propertyNames);
\r
425 cmd = createInternalUpdateAutoStaticCommand(method, propertyNames);
\r
428 boolean returningRows = false;
\r
429 if (int[].class.isAssignableFrom(method.getReturnType())) {
\r
430 returningRows = true;
\r
432 cmd = createInternalUpdateBatchAutoStaticCommand(method, propertyNames, returningRows);
\r
434 putSqlCommand(method.getName(), cmd);
\r
437 protected UpdateAutoStaticCommand createInternalUpdateAutoStaticCommand(final Method method, final String[] propertyNames) {
\r
438 final UpdateAutoStaticCommand cmd = new UpdateAutoStaticCommand(dataSource, statementFactory, beanMetaData, propertyNames);
\r
439 cmd.setCheckSingleRowUpdate(isCheckSingleRowUpdate(method));
\r
443 protected InternalUpdateAutoDynamicCommand createInternalUpdateAutoDynamicCommand(Method method, String[] propertyNames) {
\r
444 final InternalUpdateAutoDynamicCommand cmd = newUpdateAutoDynamicCommand(method, dataSource, statementFactory);
\r
445 cmd.setBeanMetaData(createBeanMetaData4UpdateDeleteByAuto(method));// Extension Point!
\r
446 cmd.setPropertyNames(propertyNames);
\r
447 cmd.setCheckSingleRowUpdate(!isNonstrictMethod(method));
\r
449 // It is unnecessary for DBFlute!
\r
450 // cmd.setNotSingleRowUpdatedExceptionClass(getNotSingleRowUpdatedExceptionClass(method));
\r
452 cmd.setVersionNoAutoIncrementOnMemory(isUpdateVersionNoAutoIncrementOnMemory(method));
\r
456 protected InternalUpdateAutoDynamicCommand newUpdateAutoDynamicCommand(Method method, DataSource ds, StatementFactory sf) {
\r
457 return new InternalUpdateAutoDynamicCommand(ds, sf);
\r
460 protected InternalUpdateModifiedOnlyCommand createInternalUpdateModifiedOnlyCommand(final Method method, final String[] propertyNames) {
\r
461 final InternalUpdateModifiedOnlyCommand cmd = newInternalUpdateModifiedOnlyCommand(method, dataSource, statementFactory);
\r
462 cmd.setBeanMetaData(createBeanMetaData4UpdateDeleteByAuto(method));// Extension Point!
\r
463 cmd.setPropertyNames(propertyNames);
\r
464 cmd.setCheckSingleRowUpdate(!isNonstrictMethod(method));
\r
466 // It is unnecessary for DBFlute!
\r
467 // cmd.setNotSingleRowUpdatedExceptionClass(getNotSingleRowUpdatedExceptionClass(method));
\r
469 cmd.setVersionNoAutoIncrementOnMemory(isUpdateVersionNoAutoIncrementOnMemory(method));
\r
473 protected InternalUpdateModifiedOnlyCommand newInternalUpdateModifiedOnlyCommand(Method method, DataSource ds, StatementFactory sf) {
\r
474 return new InternalUpdateModifiedOnlyCommand(ds, sf);
\r
477 protected InternalUpdateBatchAutoStaticCommand createInternalUpdateBatchAutoStaticCommand(final Method method, final String[] propertyNames, boolean returningRows) {
\r
478 return new InternalUpdateBatchAutoStaticCommand(dataSource, statementFactory
\r
479 , createBeanMetaData4UpdateDeleteByAuto(method), propertyNames, returningRows
\r
480 , isUpdateVersionNoAutoIncrementOnMemory(method)) {
\r
482 protected InternalUpdateBatchAutoHandler newInternalBatchAutoHandler() {
\r
483 return new InternalUpdateBatchAutoHandler(getDataSource(), getStatementFactory(), getBeanMetaData(), getPropertyTypes()) {
\r
485 protected int[] executeBatch(PreparedStatement ps, List<?> list) {
\r
486 final int[] result = super.executeBatch(ps, list);
\r
488 handleBatchUpdateResultWithOptimisticLock(ps, list, result, method);
\r
489 } catch (SQLException e) {
\r
490 handleSQLException(e, ps, false);
\r
491 return null;// Unreachable!
\r
500 // -----------------------------------------------------
\r
504 protected void setupDeleteMethodByAuto(final Method method) {
\r
505 if (isFirstArgumentConditionBean(method)) {
\r
506 final SqlCommand cmd = new InternalDeleteQueryAutoDynamicCommand(dataSource, statementFactory);
\r
507 putSqlCommand(method.getName(), cmd);
\r
510 checkAutoUpdateMethod(method);
\r
511 final String[] propertyNames = getPersistentPropertyNames(method);
\r
512 final SqlCommand cmd;
\r
513 if (isUpdateSignatureForBean(method)) {
\r
514 cmd = createInternalDeleteAutoStaticCommand(method, propertyNames);
\r
516 boolean returningRows = false;
\r
517 if (int[].class.isAssignableFrom(method.getReturnType())) {
\r
518 returningRows = true;
\r
520 cmd = createInternalDeleteBatchAutoStaticCommand(method, propertyNames, returningRows);
\r
522 putSqlCommand(method.getName(), cmd);
\r
525 protected InternalDeleteAutoStaticCommand createInternalDeleteAutoStaticCommand(final Method method, final String[] propertyNames) {
\r
526 final InternalDeleteAutoStaticCommand cmd = new InternalDeleteAutoStaticCommand(dataSource, statementFactory, createBeanMetaData4UpdateDeleteByAuto(method), propertyNames);
\r
527 cmd.setCheckSingleRowUpdate(!isNonstrictMethod(method));
\r
531 protected InternalDeleteBatchAutoStaticCommand createInternalDeleteBatchAutoStaticCommand(final Method method, final String[] propertyNames, boolean returningRows) {
\r
532 return new InternalDeleteBatchAutoStaticCommand(dataSource, statementFactory, createBeanMetaData4UpdateDeleteByAuto(method), propertyNames, returningRows) {
\r
534 protected InternalDeleteBatchAutoHandler newInternalBatchAutoHandler() {
\r
535 return new InternalDeleteBatchAutoHandler(getDataSource(), getStatementFactory(), getBeanMetaData(), getPropertyTypes()) {
\r
537 protected int[] executeBatch(PreparedStatement ps, List<?> list) {
\r
538 final int[] result = super.executeBatch(ps, list);
\r
540 handleBatchUpdateResultWithOptimisticLock(ps, list, result, method);
\r
541 } catch (SQLException e) {
\r
542 handleSQLException(e, ps, false);
\r
543 return null;// Unreachable!
\r
552 // -----------------------------------------------------
\r
555 protected BeanMetaData createBeanMetaData4UpdateDeleteByAuto(Method method) {
\r
556 if (isNonstrictMethod(method)) {
\r
557 return createNonConcurrencyBmdFactory().createBeanMetaData(getBeanClass());
\r
559 return getBeanMetaData();
\r
563 protected boolean isUpdateVersionNoAutoIncrementOnMemory(Method method) {
\r
564 return !isNonstrictMethod(method);
\r
567 protected boolean isNonstrictMethod(Method method) {
\r
568 return method.getName().contains("Nonstrict");
\r
571 protected BeanMetaDataFactory createNonConcurrencyBmdFactory() {
\r
572 final S2BeanMetaDataFactoryImpl nonConcurrencyBmdFactory = new S2BeanMetaDataFactoryImpl() {
\r
573 protected BeanMetaDataImpl createBeanMetaDataImpl() {
\r
574 return new BeanMetaDataImpl() {
\r
575 public boolean hasVersionNoPropertyType() {
\r
579 public boolean hasTimestampPropertyType() {
\r
585 nonConcurrencyBmdFactory.setAnnotationReaderFactory(this.annotationReaderFactory);
\r
586 nonConcurrencyBmdFactory.setPropertyTypeFactoryBuilder(this.propertyTypeFactoryBuilder);
\r
587 nonConcurrencyBmdFactory.setRelationPropertyTypeFactoryBuilder(this.relationPropertyTypeFactoryBuilder);
\r
588 nonConcurrencyBmdFactory.setTableNaming(this.tableNaming);
\r
589 nonConcurrencyBmdFactory.setDataSource(this.dataSource);
\r
590 nonConcurrencyBmdFactory.setDaoNamingConvention(this.daoNamingConvention);
\r
591 nonConcurrencyBmdFactory.setBeanEnhancer(this.beanEnhancer);
\r
592 return nonConcurrencyBmdFactory;
\r
595 protected boolean isFirstArgumentConditionBean(final Method method) {
\r
596 final Class<?>[] pmbTypes = method.getParameterTypes();
\r
597 return pmbTypes.length > 0 && ConditionBean.class.isAssignableFrom(pmbTypes[0]);
\r
600 protected void handleBatchUpdateResultWithOptimisticLock(PreparedStatement ps, List<?> list, int[] result, Method method) throws SQLException {
\r
601 if (ConditionBeanContext.isOracle()) {
\r
602 final int updateCount = ps.getUpdateCount();
\r
603 handleBatchUpdateResultWithOptimisticLockByUpdateCount(list, updateCount, method);
\r
605 handleBatchUpdateResultWithOptimisticLockByResult(list, result, method);
\r
609 protected void handleBatchUpdateResultWithOptimisticLockByUpdateCount(List<?> list, int updateCount, Method method) {
\r
610 if (list.isEmpty()) {
\r
611 return;// for Safety!
\r
613 if (updateCount < 0) {
\r
614 return;// for Safety!
\r
616 final int entityCount = list.size();
\r
617 if (updateCount < entityCount) {
\r
618 if (isNonstrictMethod(method)) {
\r
619 String msg = "The entity have already deleted:";
\r
620 msg = msg + " updateCount=" + updateCount;
\r
621 msg = msg + " entityCount=" + entityCount;
\r
622 msg = msg + " allEntities=" + list;
\r
623 throw new EntityAlreadyDeletedException(msg);
\r
625 throw new BatchEntityAlreadyUpdatedException(list.get(0), 0, updateCount);
\r
630 protected void handleBatchUpdateResultWithOptimisticLockByResult(List<?> list, Object result, Method method) {
\r
631 if (list.isEmpty()) {
\r
632 return;// for Safety!
\r
634 if (!(result instanceof int[])) {
\r
635 return;// for Safety!
\r
637 final int[] updatedCountArray = (int[])result;
\r
638 final int entityCount = list.size();
\r
640 boolean alreadyUpdated = false;
\r
641 for (int oneUpdateCount : updatedCountArray) {
\r
642 if (entityCount <= index) {
\r
643 break;// for Safety!
\r
645 if (oneUpdateCount == 0) {
\r
646 alreadyUpdated = true;
\r
648 } else if (oneUpdateCount > 1) {
\r
649 String msg = "The entity updated two or more records in batch update:";
\r
650 msg = msg + " entity=" + list.get(index);
\r
651 msg = msg + " updatedCount=" + oneUpdateCount;
\r
652 msg = msg + " allEntities=" + list;
\r
653 throw new EntityDuplicatedException(msg);
\r
657 if (alreadyUpdated) {
\r
658 int updateCount = 0;
\r
659 for (int oneUpdateCount : updatedCountArray) {
\r
660 updateCount = updateCount + oneUpdateCount;
\r
662 if (isNonstrictMethod(method)) {
\r
663 String msg = "The entity have already deleted:";
\r
664 msg = msg + " entity=" + list.get(index);
\r
665 msg = msg + " updateCount=" + updateCount;
\r
666 msg = msg + " allEntities=" + list;
\r
667 throw new EntityAlreadyDeletedException(msg);
\r
669 throw new BatchEntityAlreadyUpdatedException(list.get(index), 0, updateCount);
\r
674 // ===================================================================================
\r
675 // OutsideSql Override
\r
676 // ===================
\r
677 // -----------------------------------------------------
\r
678 // Normal OutsideSql
\r
679 // -----------------
\r
681 protected void setupSelectMethodByManual(Method method, String sql) {
\r
682 final Class<?>[] pmbTypes = method.getParameterTypes();
\r
683 final String[] argNames = this.daoAnnotationReader.getArgNames(method);
\r
684 final Class<?>[] argTypes;
\r
685 if (pmbTypes != null && pmbTypes.length > 0
\r
686 && CursorHandler.class.isAssignableFrom(pmbTypes[pmbTypes.length-1])) {
\r
687 argTypes = new Class<?>[pmbTypes.length - 1];
\r
688 for (int i=0; i < pmbTypes.length - 1; i++) {
\r
689 argTypes[i] = pmbTypes[i];
\r
692 argTypes = pmbTypes;
\r
694 final BeanMetaData myBeanMetaData = getOutsideSqlBeanMetaData(method);
\r
695 registerSqlCommand(method.getName(), method, sql, argNames, argTypes, myBeanMetaData);
\r
698 protected BeanMetaData getOutsideSqlBeanMetaData(Method method) {
\r
699 final Class beanClass4SelectMethodByManual = getOutsideSqlDefaultBeanClass(method);
\r
700 if (beanClass4SelectMethodByManual.equals(getBeanClass())) {
\r
701 return getBeanMetaData();
\r
703 return createOutsideSqlCustomizeBeanMetaDataFactory().createBeanMetaData(getOutsideSqlDefaultBeanClass(method));
\r
707 protected void setupUpdateMethodByManual(Method method, final String sql) {
\r
708 // DBFlute Extesion does not exist. Because DBFlute methods don't use this!
\r
709 // The insert/update/delete methods on DAO interface as outside SQL are target.
\r
710 // And especially NonPrimaryInsertMethod uses this for using S2Dao's BindVariableNode.
\r
711 super.setupUpdateMethodByManual(method, sql);
\r
714 // -----------------------------------------------------
\r
715 // Specified OutsideSql
\r
716 // --------------------
\r
717 // - - - - - - - - - - - -
\r
720 protected void setupSpecifiedOutsideSqlSelectCommand(String sqlCommandKey, Method method, OutsideSqlContext outsideSqlContext) {
\r
721 // - - - - - - - - - - - - - - - - - - - - - - -
\r
722 // The attribute of Specified-OutsideSqlContext.
\r
723 // - - - - - - - - - - - - - - - - - - - - - - -
\r
724 final String sql = outsideSqlContext.readFilteredOutsideSql(getSqlFileEncoding(), dbms.getSuffix());
\r
725 final Object pmb = outsideSqlContext.getParameterBean();
\r
726 final Object resultTypeSpecification = outsideSqlContext.getResultTypeSpecification();
\r
728 // - - - - - - - - - - - - - - -
\r
729 // The attribute of SqlCommand.
\r
730 // - - - - - - - - - - - - - - -
\r
731 final String[] argNames = (pmb != null ? new String[] {"pmb"} : new String[]{});
\r
732 final Class<?>[] argTypes = (pmb != null ? new Class<?>[] {pmb.getClass()} : new Class<?>[]{});
\r
734 // - - - - - - - - - - - - - - - -
\r
735 // Create customized BeanMetaData.
\r
736 // - - - - - - - - - - - - - - - -
\r
737 final Class<?> lastestArguementType = method.getParameterTypes()[method.getParameterTypes().length-1];
\r
738 final ResultSetHandler myResultSetHandler;
\r
739 if (Class.class.isAssignableFrom(lastestArguementType)) {
\r
743 final Class<?> customizeEntityType = (Class<?>)resultTypeSpecification;
\r
744 final BeanMetaData myBeanMetaData = createSpecifiedOutsideSqlCustomizeBeanMetaData(customizeEntityType);
\r
745 if (List.class.isAssignableFrom(method.getReturnType())) {
\r
746 myResultSetHandler = createSpecifiedOutsideSqlCustomizeBeanListResultSetHandler(myBeanMetaData, customizeEntityType);
\r
748 throw new UnsupportedOperationException("The return type of method is unsupported: method.getReturnType()=" + method.getReturnType());
\r
749 // myResultSetHandler = createSpecifiedOutsideSqlCustomizeBeanResultSetHandler(myBeanMetaData, customizeEntityType);
\r
751 } else if (CursorHandler.class.isAssignableFrom(lastestArguementType)) {
\r
755 final BeanMetaData myBeanMetaData = createSpecifiedOutsideSqlCursorBeanMetaData(method);
\r
756 myResultSetHandler = createSpecifiedOutsideSqlCursorResultSetHandler(myBeanMetaData);
\r
758 String msg = "The lastestArguementType is unsupported:";
\r
759 msg = msg + " lastestArguementType=" + lastestArguementType;
\r
760 msg = msg + " method=" + method;
\r
761 throw new IllegalStateException(msg);
\r
764 // - - - - - - - - - - -
\r
765 // Register Sql-Command.
\r
766 // - - - - - - - - - - -
\r
767 registerSqlCommand(sqlCommandKey, method, sql, argNames, argTypes, myResultSetHandler);
\r
770 protected BeanMetaData createSpecifiedOutsideSqlCustomizeBeanMetaData(Class clazz) {
\r
771 return createOutsideSqlCustomizeBeanMetaDataFactory().createBeanMetaData(clazz);
\r
775 * Create the handler of result set of specified outside-sql for the list of customize bean.
\r
776 * @param specifiedBeanMetaData Specified bean meta data. (NotNull)
\r
777 * @param customizeEntityType The type of customize entity. (NotNull)
\r
778 * @return The handler of result set. (NotNull)
\r
780 protected ResultSetHandler createSpecifiedOutsideSqlCustomizeBeanListResultSetHandler(BeanMetaData specifiedBeanMetaData, Class<?> customizeEntityType) {
\r
781 final ValueType valueType = ValueTypes.getValueType(customizeEntityType);
\r
782 if (valueType == null || !valueType.equals(ValueTypes.OBJECT)) {
\r
783 return new InternalObjectListResultSetHandler(valueType);
\r
785 final InternalRowCreator rowCreator = createSpecifiedOutsideSqlInternalRowCreator(specifiedBeanMetaData);
\r
786 final InternalRelationRowCreator relationRowCreator = createSpecifiedOutsideSqlInternalRelationRowCreator(specifiedBeanMetaData);
\r
787 return new InternalBeanListMetaDataResultSetHandler(specifiedBeanMetaData, rowCreator, relationRowCreator);
\r
790 protected InternalRowCreator createSpecifiedOutsideSqlInternalRowCreator(BeanMetaData bmd) {
\r
791 final Class clazz = bmd.getBeanClass();
\r
792 return InternalRowCreator.createInternalRowCreator(clazz);
\r
795 protected InternalRelationRowCreator createSpecifiedOutsideSqlInternalRelationRowCreator(BeanMetaData bmd) {
\r
796 return new InternalRelationRowCreator();
\r
799 protected class InternalObjectListResultSetHandler implements ResultSetHandler {
\r
800 private ValueType valueType;
\r
801 public InternalObjectListResultSetHandler(ValueType valueType) {
\r
802 this.valueType = valueType;
\r
804 public Object handle(ResultSet rs) throws SQLException {
\r
805 final List<Object> ret = new ArrayList<Object>();
\r
806 while (rs.next()) {
\r
807 ret.add(valueType.getValue(rs, 1));
\r
813 protected BeanMetaData createSpecifiedOutsideSqlCursorBeanMetaData(Method method) {
\r
814 return createOutsideSqlCustomizeBeanMetaDataFactory().createBeanMetaData(getOutsideSqlDefaultBeanClass(method));
\r
817 protected ResultSetHandler createSpecifiedOutsideSqlCursorResultSetHandler(BeanMetaData specifiedBeanMetaData) {
\r
818 return new org.seasar.extension.jdbc.impl.ObjectResultSetHandler();// This is dummy for cursor handling!
\r
821 // - - - - - - - - - - - -
\r
824 protected void setupSpecifiedOutsideSqlExecuteCommand(String sqlCommandKey, Method method, OutsideSqlContext outsideSqlContext) {
\r
825 // - - - - - - - - - - - - - - - - - - - - - - -
\r
826 // The attribute of Specified-OutsideSqlContext.
\r
827 // - - - - - - - - - - - - - - - - - - - - - - -
\r
828 final String sql = outsideSqlContext.readFilteredOutsideSql(getSqlFileEncoding(), dbms.getSuffix());
\r
829 final Object pmb = outsideSqlContext.getParameterBean();
\r
831 // - - - - - - - - - - - - - - -
\r
832 // The attribute of SqlCommand.
\r
833 // - - - - - - - - - - - - - - -
\r
834 final String[] argNames = (pmb != null ? new String[] {"pmb"} : new String[]{});
\r
835 final Class<?>[] argTypes = (pmb != null ? new Class<?>[] {pmb.getClass()} : new Class<?>[]{});
\r
837 final InternalUpdateDynamicCommand cmd = new InternalUpdateDynamicCommand(dataSource, statementFactory) {
\r
839 public Object execute(Object[] args) {
\r
840 if (args.length != 3) {
\r
841 String msg = "Internal Error! OutsideSqlDao.execute() should have 3 arguements: args.length=" + args.length;
\r
842 throw new IllegalStateException(msg);
\r
844 Object arg = args[1];
\r
845 return super.execute(new Object[] {arg});
\r
849 // It is unnecessary for DBFlute!
\r
850 // cmd.setNotSingleRowUpdatedExceptionClass(getNotSingleRowUpdatedExceptionClass(method));
\r
852 registerSqlCommand(sqlCommandKey, method, sql, argNames, argTypes, cmd);
\r
855 // - - - - - - - - - - - -
\r
858 protected void setupSpecifiedOutsideSqlCallCommand(String sqlCommandKey, Method method, OutsideSqlContext outsideSqlContext) {
\r
859 // - - - - - - - - - - - - - - - - - - - - - - -
\r
860 // The attribute of Specified-OutsideSqlContext.
\r
861 // - - - - - - - - - - - - - - - - - - - - - - -
\r
862 final Object pmb = outsideSqlContext.getParameterBean();
\r
863 final String procedureName = outsideSqlContext.getOutsideSqlPath();
\r
865 // - - - - - - - - - - - - - - -
\r
866 // The attribute of SqlCommand.
\r
867 // - - - - - - - - - - - - - - -
\r
868 final InternalProcedureMetaDataFactory factory = createInternalProcedureMetaDataFactory();
\r
869 factory.setValueTypeFactory(valueTypeFactory);
\r
870 final Class<?> pmbType = pmb != null ? pmb.getClass() : null;
\r
871 final InternalProcedureMetaData metaData = factory.createProcedureMetaData(procedureName, pmbType);
\r
872 final InternalProcedureCommand cmd = createInternalProcedureCommand(method, metaData);
\r
873 putSqlCommand(sqlCommandKey, cmd);
\r
876 protected InternalProcedureMetaDataFactory createInternalProcedureMetaDataFactory() {
\r
877 return new InternalProcedureMetaDataFactory();
\r
880 protected InternalProcedureCommand createInternalProcedureCommand(Method method, InternalProcedureMetaData metaData) {
\r
881 final ResultSetHandler resultSetHandler = createResultSetHandler(method);
\r
882 return new InternalProcedureCommand(dataSource, resultSetHandler, statementFactory, metaData);
\r
885 // -----------------------------------------------------
\r
886 // Common of OutsideSql
\r
887 // --------------------
\r
888 protected BeanMetaDataFactory createOutsideSqlCustomizeBeanMetaDataFactory() {
\r
889 final S2BeanMetaDataFactoryImpl originalBmdFactory = new S2BeanMetaDataFactoryImpl() {
\r
890 protected BeanMetaDataImpl createBeanMetaDataImpl() {
\r
891 return newOutsideSqlCustomizeBeanMetaDataImpl();
\r
894 originalBmdFactory.setAnnotationReaderFactory(this.annotationReaderFactory);
\r
895 originalBmdFactory.setPropertyTypeFactoryBuilder(createOutsideSqlPropertyTypeFactoryBuilder());
\r
896 originalBmdFactory.setRelationPropertyTypeFactoryBuilder(this.relationPropertyTypeFactoryBuilder);
\r
897 originalBmdFactory.setTableNaming(this.tableNaming);
\r
898 originalBmdFactory.setDataSource(this.dataSource);
\r
899 originalBmdFactory.setDaoNamingConvention(this.daoNamingConvention);
\r
900 originalBmdFactory.setBeanEnhancer(this.beanEnhancer);
\r
901 return originalBmdFactory;
\r
904 protected BeanMetaDataImpl newOutsideSqlCustomizeBeanMetaDataImpl() {
\r
905 return new OutsideSqlCustomizeBeanMetaDataImpl();
\r
908 protected static class OutsideSqlCustomizeBeanMetaDataImpl extends BeanMetaDataImpl {
\r
909 // Though nothing to override, it uses original class just in case.
\r
912 protected S2DaoPropertyTypeFactoryBuilderExtension createOutsideSqlPropertyTypeFactoryBuilder() {
\r
913 final S2DaoPropertyTypeFactoryBuilderExtension impl = new S2DaoPropertyTypeFactoryBuilderExtension();
\r
914 if (columnNaming == null) {
\r
915 String msg = "Internal Error! The columnNaming should not be null! {Failed to Injection!}";
\r
916 throw new IllegalStateException(msg);
\r
918 impl.setColumnNaming(columnNaming);
\r
919 impl.setValueTypeFactory(valueTypeFactory);
\r
923 protected Class getOutsideSqlDefaultBeanClass(Method method) {
\r
924 final Class retType = method.getReturnType();
\r
925 if (java.util.List.class.isAssignableFrom(retType)) {
\r
926 final Class elementType = InternalMethodUtil.getElementTypeOfListFromReturnMethod(method);
\r
927 if (elementType != null) {
\r
928 return elementType;
\r
930 return getBeanClass();
\r
932 } else if (retType.isArray()) {
\r
933 return retType.getComponentType();
\r
934 } else if (retType.isPrimitive() || !ValueTypes.getValueType(retType).equals(ValueTypes.OBJECT)) {
\r
935 return getBeanClass();
\r
941 protected void registerSqlCommand(String sqlCommandKey, Method method, String sql, String[] argNames, Class[] argTypes, BeanMetaData myBeanMetaData) {
\r
942 registerSqlCommand(sqlCommandKey, method, sql, argNames, argTypes, createResultSetHandler(myBeanMetaData, method));
\r
945 protected void registerSqlCommand(String sqlCommandKey, Method method, String sql, String[] argNames, Class[] argTypes, ResultSetHandler myResultSetHandler) {
\r
946 final S2DaoSelectDynamicCommand cmd = createCustomizeSelectDynamicCommand(myResultSetHandler);
\r
947 registerSqlCommand(sqlCommandKey, method, sql, argNames, argTypes, cmd);
\r
950 protected void registerSqlCommand(String sqlCommandKey, Method method, String sql, String[] argNames, Class[] argTypes, S2DaoSelectDynamicCommand cmd) {
\r
952 cmd.setArgNames(argNames);
\r
953 cmd.setArgTypes(argTypes);
\r
954 this.sqlCommands.put(sqlCommandKey, cmd);
\r
957 protected void registerSqlCommand(String sqlCommandKey, Method method, String sql, String[] argNames, Class[] argTypes, InternalUpdateDynamicCommand cmd) {
\r
959 cmd.setArgNames(argNames);
\r
960 cmd.setArgTypes(argTypes);
\r
961 this.sqlCommands.put(sqlCommandKey, cmd);
\r
964 // ===================================================================================
\r
968 protected void putSqlCommand(String methodName, SqlCommand cmd) {
\r
969 sqlCommands.put(methodName, cmd);
\r
972 protected boolean isCheckSingleRowUpdate(Method method) {
\r
973 return checkSingleRowUpdateForAll & daoAnnotationReader.isCheckSingleRowUpdate(method);
\r
976 // ===================================================================================
\r
977 // Customize SelectDynamicCommand Creation
\r
978 // =======================================
\r
980 * Create the customize select dynamic command that is for all select SQL on DBFlute.
\r
981 * @param handler The handler of result set. (NotNull)
\r
982 * @return The customize select dynamic command. (NotNull)
\r
984 protected S2DaoSelectDynamicCommand createCustomizeSelectDynamicCommand(ResultSetHandler handler) {
\r
985 return new S2DaoSelectDynamicCommand(dataSource, statementFactory, handler);
\r
988 // ===================================================================================
\r
989 // ResultSetHandler Override
\r
990 // =========================
\r
992 protected ResultSetHandler createResultSetHandler(Method method) {
\r
993 return this.resultSetHandlerFactory.getResultSetHandler(daoAnnotationReader, beanMetaData, method);
\r
996 protected ResultSetHandler createResultSetHandler(BeanMetaData specifiedBeanMetaData, Method method) {// For specified BeanMetaData
\r
997 return this.resultSetHandlerFactory.getResultSetHandler(daoAnnotationReader, specifiedBeanMetaData, method);
\r
1000 // ===================================================================================
\r
1003 protected Connection getConnection() {
\r
1004 if (dataSource == null) {
\r
1005 throw new IllegalStateException("The dataSource should not be null!");
\r
1008 return dataSource.getConnection();
\r
1009 } catch (SQLException e) {
\r
1010 handleSQLException(e, null);
\r
1011 return null;// Unreachable!
\r
1015 protected DatabaseMetaData getMetaData(Connection conn) {
\r
1017 return conn.getMetaData();
\r
1018 } catch (SQLException e) {
\r
1019 handleSQLException(e, null);
\r
1020 return null;// Unreachable!
\r
1024 protected String getDatabaseProductName(DatabaseMetaData dbMetaData) {
\r
1026 return dbMetaData.getDatabaseProductName();
\r
1027 } catch (SQLException e) {
\r
1028 handleSQLException(e, null);
\r
1029 return null;// Unreachable!
\r
1033 protected void close(Connection conn) {
\r
1034 if (conn == null) {
\r
1039 } catch (SQLException e) {
\r
1040 handleSQLException(e, null);
\r
1044 // ===================================================================================
\r
1045 // Exception Handlnig
\r
1046 // ==================
\r
1047 protected void handleSQLException(SQLException e, Statement statement) {
\r
1048 new SQLExceptionHandler().handleSQLException(e, statement);
\r
1051 // ===================================================================================
\r
1052 // ResultSetHandlerFactoryImpl Extension
\r
1053 // =====================================
\r
1054 public static class ResultSetHandlerFactoryExtension extends ResultSetHandlerFactoryImpl {
\r
1055 public ResultSetHandlerFactoryExtension() {
\r
1060 protected RowCreator createRowCreator() { // [DAO-118] (2007/08/25)
\r
1061 return createInternalRowCreator(null);
\r
1065 protected RelationRowCreator createRelationRowCreator() {
\r
1066 return createInternalRelationRowCreator(null);
\r
1070 protected ResultSetHandler createBeanListMetaDataResultSetHandler(BeanMetaData bmd) { // DBFlute Target
\r
1071 final InternalRowCreator rowCreator = createInternalRowCreator(bmd);
\r
1072 final InternalRelationRowCreator relationRowCreator = createInternalRelationRowCreator(bmd);
\r
1073 return new InternalBeanListMetaDataResultSetHandler(bmd, rowCreator, relationRowCreator);
\r
1077 protected ResultSetHandler createBeanArrayMetaDataResultSetHandler(BeanMetaData bmd) { // DBFlute Target
\r
1078 final InternalRowCreator rowCreator = createInternalRowCreator(bmd);
\r
1079 final InternalRelationRowCreator relationRowCreator = createInternalRelationRowCreator(bmd);
\r
1080 return new InternalBeanArrayMetaDataResultSetHandler(bmd, rowCreator, relationRowCreator);
\r
1083 protected InternalRowCreator createInternalRowCreator(BeanMetaData bmd) {
\r
1084 final Class<?> clazz = bmd != null ? bmd.getBeanClass() : null;
\r
1085 return InternalRowCreator.createInternalRowCreator(clazz);
\r
1088 protected InternalRelationRowCreator createInternalRelationRowCreator(BeanMetaData bmd) {
\r
1089 return new InternalRelationRowCreator(); // Not yet implemented about performance tuning!
\r
1093 // ===================================================================================
\r
1096 protected static class InternalMethodUtil {
\r
1097 public static Class getElementTypeOfListFromReturnMethod(Method method) {
\r
1098 return InternalReflectionUtil.getElementTypeOfListFromReturnType(method);
\r
1101 protected static class InternalReflectionUtil {
\r
1102 public static Class<?> getElementTypeOfList(final Type parameterizedList) {
\r
1103 if (!(parameterizedList instanceof ParameterizedType)) {
\r
1106 final ParameterizedType parameterizedType = ParameterizedType.class.cast(parameterizedList);
\r
1107 final Type rawType = parameterizedType.getRawType();
\r
1108 if (!(rawType instanceof Class)) {
\r
1111 final Class<?> rawClass = Class.class.cast(rawType);
\r
1112 if (!rawClass.isAssignableFrom(List.class)) {
\r
1115 final Type[] actualTypeArgument = parameterizedType.getActualTypeArguments();
\r
1116 if (actualTypeArgument == null || actualTypeArgument.length != 1) {
\r
1119 if (!(actualTypeArgument[0] instanceof Class)) {
\r
1122 return Class.class.cast(actualTypeArgument[0]);
\r
1124 public static Class<?> getElementTypeOfListFromParameterType(final Method method, final int parameterPosition) {
\r
1125 final Type[] pmbTypes = method.getGenericParameterTypes();
\r
1126 return getElementTypeOfList(pmbTypes[parameterPosition]);
\r
1128 public static Class<?> getElementTypeOfListFromReturnType(final Method method) {
\r
1129 return getElementTypeOfList(method.getGenericReturnType());
\r
1133 // ===================================================================================
\r
1136 protected DBMeta findDBMeta() {
\r
1137 final Class<?> beanType = getBeanClass();
\r
1138 if (beanType == null) {
\r
1141 if (!Entity.class.isAssignableFrom(beanType)) {
\r
1144 final Entity entity;
\r
1146 entity = (Entity)beanType.newInstance();
\r
1147 } catch (InstantiationException e) {
\r
1148 throw new IllegalStateException(e);
\r
1149 } catch (IllegalAccessException e) {
\r
1150 throw new IllegalStateException(e);
\r
1152 return entity.getDBMeta();
\r
1155 // ===================================================================================
\r
1158 protected String getLineSeparator() {
\r
1159 return SimpleSystemUtil.getLineSeparator();
\r
1162 // ===================================================================================
\r
1165 // -----------------------------------------------------
\r
1166 // Sql File Encoding
\r
1167 // -----------------
\r
1168 public String getSqlFileEncoding() {
\r
1169 return sqlFileEncoding;
\r
1172 // -----------------------------------------------------
\r
1175 public BeanEnhancer getBeanEnhancer() {
\r
1176 return beanEnhancer;
\r
1179 public void setBeanEnhancer(final BeanEnhancer beanEnhancer) {
\r
1180 this.beanEnhancer = beanEnhancer;
\r
1183 // -----------------------------------------------------
\r
1184 // Annotation Reader Factory
\r
1185 // -------------------------
\r
1186 public void setAnnotationReaderFactory(org.seasar.dao.AnnotationReaderFactory annotationReaderFactory) {
\r
1187 this.annotationReaderFactory = annotationReaderFactory;
\r
1190 // -----------------------------------------------------
\r
1191 // Version After 1.0.47
\r
1192 // --------------------
\r
1193 public ColumnNaming getColumnNaming() {
\r
1194 return columnNaming;
\r
1197 public void setColumnNaming(final ColumnNaming columnNaming) {
\r
1198 this.columnNaming = columnNaming;
\r
1201 public PropertyTypeFactoryBuilder getPropertyTypeFactoryBuilder() {
\r
1202 return propertyTypeFactoryBuilder;
\r
1205 public void setPropertyTypeFactoryBuilder(final PropertyTypeFactoryBuilder propertyTypeFactoryBuilder) {
\r
1206 this.propertyTypeFactoryBuilder = propertyTypeFactoryBuilder;
\r
1209 public RelationPropertyTypeFactoryBuilder getRelationPropertyTypeFactoryBuilder() {
\r
1210 return relationPropertyTypeFactoryBuilder;
\r
1213 public void setRelationPropertyTypeFactoryBuilder(final RelationPropertyTypeFactoryBuilder relationPropertyTypeFactoryBuilder) {
\r
1214 this.relationPropertyTypeFactoryBuilder = relationPropertyTypeFactoryBuilder;
\r
1217 public TableNaming getTableNaming() {
\r
1218 return tableNaming;
\r
1221 public void setTableNaming(final TableNaming tableNaming) {
\r
1222 this.tableNaming = tableNaming;
\r
1225 // -----------------------------------------------------
\r
1226 // DBFlute Extension
\r
1227 // -----------------
\r
1228 public BehaviorSelector getBehaviorSelector() {
\r
1229 return _behaviorSelector;
\r
1232 public void setBehaviorSelector(final BehaviorSelector behaviorSelector) {
\r
1233 this._behaviorSelector = behaviorSelector;
\r
1236 public boolean isInternalDebug() {
\r
1237 return _internalDebug;
\r
1240 public void setInternalDebug(final boolean internalDebug) {
\r
1241 this._internalDebug = internalDebug;
\r