package jef.database; import java.sql.PreparedStatement; import java.sql.SQLException; import java.sql.SQLIntegrityConstraintViolationException; import java.util.ArrayList; import java.util.List; import jef.database.dialect.DatabaseDialect; import jef.database.dialect.type.ColumnMapping; import jef.database.meta.Feature; import jef.database.meta.ITableMetadata; import jef.database.meta.MetaHolder; import jef.database.routing.PartitionResult; import jef.database.support.SqlLog; import jef.database.wrapper.clause.InsertSqlClause; import jef.database.wrapper.processor.InsertStep.OracleRowidKeyCallback; import jef.database.wrapper.variable.BindVariableContext; import jef.tools.ArrayUtils; import jef.tools.StringUtils; abstract class InsertProcessor { protected DbClient db; static InsertProcessor get(DatabaseDialect profile, DbClient db) { return new PreparedImpl(db); } /** * generate a insert SQL. * * @param obj * @param tableName * @param dynamic * @param extreme * @return * @throws SQLException */ abstract InsertSqlClause toInsertSql(IQueryableEntity obj, String tableName, boolean dynamic, PartitionResult pr) throws SQLException; abstract InsertSqlClause toInsertSqlBatch(IQueryableEntity obj, String tableName, boolean dynamic, boolean extreme, PartitionResult pr) throws SQLException; /** * process insert operate * * @param db * @param obj * @param sqls * @param start * @param parse * @throws SQLException */ abstract void processInsert(OperateTarget db, IQueryableEntity obj, InsertSqlClause sqls, long start, long parse) throws SQLException; /** * 构造 * * @param parentDbClient * @param rProcessor */ InsertProcessor(DbClient parentDbClient) { this.db = parentDbClient; } static final class PreparedImpl extends InsertProcessor { PreparedImpl(DbClient parentDbClient) { super(parentDbClient); } @Override InsertSqlClause toInsertSql(IQueryableEntity obj, String tableName, boolean dynamic, PartitionResult pr) throws SQLException { return toInsertSqlBatch(obj, tableName, dynamic, false, pr); } @Override InsertSqlClause toInsertSqlBatch(IQueryableEntity obj, String tableName, boolean dynamic, boolean extreme, PartitionResult pr) throws SQLException { DatabaseDialect profile = pr == null ? db.getProfile(null) : db.getProfile(pr.getDatabase()); List<String> cStr = new ArrayList<String>();// 字段列表 List<String> vStr = new ArrayList<String>();// 值列表 ITableMetadata meta = MetaHolder.getMeta(obj); InsertSqlClause result = new InsertSqlClause(extreme); result.parent = db; result.profile = profile; result.setTableNames(pr); for (ColumnMapping entry : meta.getColumns()) { if(entry.isNotInsert()) continue; entry.processPreparedInsert(obj, cStr, vStr, result, dynamic); } if (profile.has(Feature.SELECT_ROW_NUM) && !extreme) { result.getCallback().addProcessor(new OracleRowidKeyCallback()); } result.setColumnsPart(StringUtils.join(cStr, ',')); result.setValuesPart(StringUtils.join(vStr, ',')); return result; } @Override void processInsert(OperateTarget db, IQueryableEntity obj, InsertSqlClause sqls, long start, long parse) throws SQLException { SqlLog sb = ORMConfig.getInstance().newLogger(); String sql = sqls.getSql(); sb.ensureCapacity(sql.length() + 128); sb.append(sql).append(db); PreparedStatement psmt = null; DatabaseDialect profile = db.getProfile(); try { psmt = sqls.getCallback().doPrepareStatement(db, sql); BindVariableContext context = new BindVariableContext(psmt, profile, sb); context.setInsertVariables(obj, sqls.getFields()); psmt.execute(); sb.append("\nInsert:1\tTime cost([ParseSQL]:", parse - start).append("ms, [DbAccess]:", System.currentTimeMillis() - parse).append("ms)").append(db); sqls.getCallback().callAfter(obj); } catch (SQLIntegrityConstraintViolationException e) { throw e; } catch (SQLException e) { String s = profile.getViolatedConstraintNameExtracter().extractConstraintName(e); if (s != null) { throw new SQLIntegrityConstraintViolationException(s); } else { DbUtils.processError(e, ArrayUtils.toString(sqls.getTable(), true), db); throw e; } } finally { sb.output(); if (psmt != null) psmt.close(); db.releaseConnection(); } } } }