Java BatchSqlUpdate-如何获取自动生成的密钥

Java BatchSqlUpdate-如何获取自动生成的密钥,java,mysql,sql,spring,Java,Mysql,Sql,Spring,我正在使用SpringBatchSQLUpdate插入一组行。如何为插入的所有行获取自动生成的键 当做一次单次插入时,我得到的键如下- SqlUpdate sqlUpdate = new SqlUpdate(dataSource, sqlTemplate.toString()); sqlUpdate.setReturnGeneratedKeys(true); KeyHolder keyHolder = new GeneratedKeyHolder(); sqlUpdate.update(new

我正在使用SpringBatchSQLUpdate插入一组行。如何为插入的所有行获取自动生成的键

当做一次单次插入时,我得到的键如下-

SqlUpdate sqlUpdate = new SqlUpdate(dataSource, sqlTemplate.toString());
sqlUpdate.setReturnGeneratedKeys(true);
KeyHolder keyHolder = new GeneratedKeyHolder();
sqlUpdate.update(new Object[] {}, keyHolder);
return keyHolder.getKey().longValue();

谢谢

据我所知,没有提供使用
BatchSqlUpdate
解决此问题的解决方案,但您始终可以

  • 查询插入前的最后一个键
  • 使用此信息,在插入后查询所有新键
    • 模板过程类:

      public abstract class BatchPreparedStatementSetterWithKeyHolder<T> implements BatchPreparedStatementSetter {
          private final List<T> beans;
      
          /**
           * @param datas
           * @param returnGeneratedKeys true设置{@linkplain Statement#RETURN_GENERATED_KEYS}
           */
          public BatchPreparedStatementSetterWithKeyHolder(List<T> beans) {
              this.beans = beans;
          }
      
      
          @Override
          public void setValues(PreparedStatement ps, int i) throws SQLException {
              setValues(ps, beans.get(i));
          }
      
          @Override
          public final int getBatchSize() {
              return beans.size();
          }
      
          public void setPrimaryKey(KeyHolder keyHolder) {
              List<Map<String, Object>> keys = keyHolder.getKeyList();
              for (int i = 0, len = keys.size(); i < len; i++) {
                  setPrimaryKey(keys.get(i), beans.get(i));
              }
          }
      
          protected abstract void setValues(PreparedStatement ps, T bean) throws SQLException;
          protected abstract void setPrimaryKey(Map<String, Object> primaryKey, T bean);
      }
      
      公共抽象类BatchPreparedStatementSetterWithKeyHolder实现BatchPreparedStatementSetter{
      私有最终列表bean;
      /**
      *@param数据
      *@param returnGeneratedKeys true设置{@linkplain语句#返回_生成的_键}
      */
      公共BatchPreparedStatementSetterWithKeyHolder(列表bean){
      这个.豆子=豆子;
      }
      @凌驾
      公共void setValues(PreparedStatement ps,int i)引发SQLException{
      设置值(ps,beans.get(i));
      }
      @凌驾
      公共最终整数getBatchSize(){
      返回beans.size();
      }
      公共无效设置PrimaryKey(钥匙座钥匙座){
      List keys=keyHolder.getKeyList();
      for(int i=0,len=keys.size();i
      一个util方法batchupdate:

      private static void generatedKeys(PreparedStatement ps, KeyHolder keyHolder) throws SQLException {
              List<Map<String, Object>> keys = keyHolder.getKeyList();
              ResultSet rs = ps.getGeneratedKeys();
              if (rs == null) return;
      
              try {
                  keys.addAll(new RowMapperResultSetExtractor<Map<String, Object>>(new ColumnMapRowMapper(), 1).extractData(rs));
              } finally {
                  UtilIO.close(rs);
              }
          }
      
          /**
           * 批量更新
           * @param jdbcTemplate
           * @param sql
           * @param pss
           * @param keyHolder 存储主键,如果要存储主键,就必须传入此对象
           * @return sql执行结果
           * @see JdbcTemplate#batchUpdate(String, org.springframework.jdbc.core.BatchPreparedStatementSetter)
           */
          public static <T> int[] batchUpdateWithKeyHolder(JdbcTemplate jdbcTemplate, final String sql, final BatchPreparedStatementSetterWithKeyHolder<T> pss) {
              return jdbcTemplate.execute(new PreparedStatementCreator() {
                  @Override
                  public PreparedStatement createPreparedStatement(Connection con) throws SQLException {
                      return con.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
                  }
              }, new PreparedStatementCallback<int[]>() {
                  @Override
                  public int[] doInPreparedStatement(PreparedStatement ps) throws SQLException, DataAccessException {
                      try {
                          int batchSize = pss.getBatchSize();
                          InterruptibleBatchPreparedStatementSetter ipss =
                                  (pss instanceof InterruptibleBatchPreparedStatementSetter ?
                                  (InterruptibleBatchPreparedStatementSetter) pss : null);
                          int[] result;
                          KeyHolder keyHolder = new GeneratedKeyHolder();
      
                          try {
                              if (JdbcUtils.supportsBatchUpdates(ps.getConnection())) {
                                  for (int i = 0; i < batchSize; i++) {
                                      pss.setValues(ps, i);
                                      if (ipss != null && ipss.isBatchExhausted(i)) break;
                                      ps.addBatch();
                                  }
                                  result = ps.executeBatch();
      
                                  generatedKeys(ps, keyHolder);
                              } else {
                                  List<Integer> rowsAffected = new ArrayList<Integer>();
                                  for (int i = 0; i < batchSize; i++) {
                                      pss.setValues(ps, i);
                                      if (ipss != null && ipss.isBatchExhausted(i)) break;
      
                                      rowsAffected.add(ps.executeUpdate());
                                      generatedKeys(ps, keyHolder);
                                  }
      
                                  result = UtilObj.tointArray(rowsAffected);
                              }
                          } finally {
                              pss.setPrimaryKey(keyHolder);
                          }
      
                          return result;
                      } finally {
                          if (pss instanceof ParameterDisposer) ((ParameterDisposer) pss).cleanupParameters();
                      }
                  }
              });
          }
      
      private static void generatedKeys(PreparedStatement ps,KeyHolder KeyHolder)抛出SQLException{
      List keys=keyHolder.getKeyList();
      ResultSet rs=ps.getGeneratedKeys();
      如果(rs==null)返回;
      试一试{
      addAll(新的RowMapperResultSetExtractor(新的ColumnMapRowMapper(),1).extractData(rs));
      }最后{
      公用设施关闭(rs);
      }
      }
      /**
      * 批量更新
      *@param jdbc模板
      *@param-sql
      *@param-pss
      *@param钥匙夹存储主键,如果要存储主键,就必须传入此对象
      *@returnsql执行结果
      *@参见JdbcTemplate#batchUpdate(String,org.springframework.jdbc.core.BatchPreparedStatementSetter)
      */
      公共静态int[]batchUpdateWithKeyHolder(JdbcTemplate JdbcTemplate,最终字符串sql,最终BatchPreparedStatementSetterWithKeyHolder pss){
      返回jdbcTemplate.execute(新的PreparedStatementCreator(){
      @凌驾
      公共PreparedStatement createPreparedStatement(连接con)引发SQLException{
      return con.prepareStatement(sql、Statement.return\u生成的\u键);
      }
      },新的PreparedStatementCallback(){
      @凌驾
      public int[]doInPreparedStatement(PreparedStatement ps)抛出SQLException、DataAccessException{
      试一试{
      int batchSize=pss.getBatchSize();
      中断BatchPreparedStatementSetter ipss=
      (pss中断BatchPreparedStatementSetter的实例?
      (InterruptableBatchPreparedStatementSetter)pss:null);
      int[]结果;
      KeyHolder KeyHolder=新生成的KeyHolder();
      试一试{
      if(JdbcUtils.supportsBatchUpdates(ps.getConnection())){
      对于(int i=0;i
      e、 x:

      UtilJdbc.batchUpdateWithKeyHolder(jdbcTemplate,
      插入到tbe_vm_节点(创建者id、主机、ssh_ip、ssh_用户、ssh_密码)+
      “值(?,,,?,?)”,
      新的BatchPreparedStatementSetterWithKeyHolder(vmNodes){
      @凌驾
      受保护的void setValues(PreparedStatement ps,VmNode VmNode)引发SQLException{
      UtilJdbc.setValues(ps,vmNode.getCreatorId(),vmNode.getHost(),
      vmNode.getSshIp(),vmNode.getSshUser(),vmNode.getSshPasswd());
      }
      @凌驾
      受保护的void setPrimaryKey(映射primaryKey、VmNode VmNode){
      setId((长)primaryKey.get(“abc”);
      }
      });
      
      感谢提供的解决方案,我实现了它,效果非常好。但是,您有对私有类(UtilIo、UtilObj)的引用,我必须在其中解释您所做的工作。我将“实用关闭(rs);”替换为:

      我将“result=UtilObj.tointArray(rowsAffected);”替换为以下Java 8代码:

      result = rowsAffected.stream().mapToInt(Integer::intValue).toArray();
      
      谢谢(到目前为止,我问了大约14个问题,其中一半没有答案,我自己回答了一两个。
          KeyHolder keyHolder = new GeneratedKeyHolder();
          BatchSqlUpdate updateBatch = new BatchSqlUpdate();
          updateBatch.setSql("Some INSERT SQL");
          updateBatch.setJdbcTemplate(jdbcTemp);
          updateBatch.setReturnGeneratedKeys(true);
          updateBatch.updateByNamedParam( paramsMap ,keyHolder);
          updateBatch.flush();
      
      if (rs != null) {
          rs.close();
      }
      
      result = rowsAffected.stream().mapToInt(Integer::intValue).toArray();