1、对于支持生成自增主键的数据库:useGenerateKeys和keyProperty。
2、不支持生成自增主键的数据库:<selectKey>。
但是怎对批量插入数据返回自增主键的解决方式网上看到的还是比较少,至少百度的结果比较少。
Mybatis官网资料提供如下:
First, if your database supports auto-generated key fields (eg MySQL and SQL Server), then you can simply set useGeneratedKeys="true" and set the keyProperty to the target property and you're done For example, if the Authortable above had used an auto-generated column type for the id, the statement would be modified as follows:
<insert id="insertAuthor" useGeneratedKeys="true"
keyProperty="id">
insert into Author (username,password,email,bio)
values (#{username},#{password},#{email},#{bio})
</insert>
If your database also supports multi-row insert, you can pass a list or an array of Authors and retrieve the auto-generated keys
<insert id="insertAuthor" useGeneratedKeys="true"
keyProperty="id">
insert into Author (username, password, email, bio) values
<foreach item="item" collection="list" separator=",">
(#{itemusername}, #{itempassword}, #{itememail}, #{itembio})
</foreach>
</insert>
从官网资料可以看出Mybatis是支持批量插入时返回自增主键的。(百度上说不支持的,多打脸 开玩笑的)
但是在本地测试的时候使用上述方式确实不能返回自增id,而且还报错(不认识keyProperty中指定的Id属性),然后在网上找相关资料。终于在Stackoverflow上面找到了一些信息。
解决办法:
1、升级Mybatis版本到331。
2、在Dao中不能使用@param注解。
3、Mapperxml中使用list变量接受Dao中的集合。
参考地址:
>
如下,插入一条记录的时候可以这样返回id(一下代码只是说明事例)://保存一个test对象,并返回该对象 public Test save(Test test){ KeyHolder keyHolder = new GeneratedKeyHolder(); getJdbcTemplate()update(new PreparedStatementCreator() { @Override public PreparedStatement createPreparedStatement( Connection con) throws SQLException { PreparedStatement ps = conprepareStatement("insert into tb_test (name,sex) values (,)", StatementRETURN_GENERATED_KEYS); pssetString(1, testgetName()); pssetString(2, testgetSex()); return ps; } }, keyHolder); //这里可以获得数据库id testsetId(IntegervalueOf(keyHoldergetKeyList()get(0) toString())); return test; } // 批量插入, public List<Test> saveOrUpdateAll(final List<Test> list) { getJdbcTemplate()batchUpdate( "insert into tb_test (name,sex) values (,)", new BatchPreparedStatementSetter() { @Override public void setValues(PreparedStatement ps, int i) throws SQLException { pssetString(1, listget(i)getName()); pssetString(2, listget(i)getSex()); } @Override public int getBatchSize() { return listsize(); } }); //哪个方法可以获得list中每个test对象的id我不想重新进行查询 return list; } 问题补充:飞雪无情 写道你已经写好了插入一个对象的方法,就是public Test save(Test test),批量插入的时候可以直接使用该方法的。# public List<Test> saveOrUpdateAll(final List<Test> list) { List<Test> resultList=new ArrayList<Test>(); for(Test test:list){ resultListadd(save(test)); } return resultList; } 这样就好了。我也考虑过这样的方式,但是把:getJdbcTemplate()update(new PreparedStatementCreator() { @Override public PreparedStatement createPreparedStatement( Connection con) throws SQLException { PreparedStatement ps = conprepareStatement("insert into tb_test (name,sex) values (,)", StatementRETURN_GENERATED_KEYS); pssetString(1, testgetName()); pssetString(2, testgetSex()); return ps; } }, keyHolder); 这么一段代码放在循环里面,会不会性能有些影响吧?Spring既然提供了batchUpdate,该会不会在批处理上有些性能优势呢 问题补充:飞雪无情 写道spring这个批量插入有点限制,比如你这个特殊需要,我感觉它实现不了,所以你用我上面说的那个方法迂回实现。我感觉性能方面应该不会有太大的影响。你看spring的批量插入的时候这个BatchPreparedStatementSetter借口的方法setValues(PreparedStatement ps, int i) ,提供了一个索引i,它肯定也遍历了,要么怎么知道i的值。所以有特殊需求的时候就用上面那种方案,没有的时候推荐用spring提供了批量 *** 作,我们项目中就这么做的。看了Spring这两个方法的源码,觉得这个东西在封装的时候考虑的不是很周全,确实局限性太大了,比如我批量保存的时候有可能一部分是插入,一部分是更新,这个时候也只能按照你说的这种方式了,比较而言还是orm框架持久层用起来的方便。spring的这个两个方法看了源码感觉在设计上确实存在缺陷,灵活性不够,其实返回数据库执行的条数意义根本就不大//其实我想的是这样的一个方法 / @author BAOSJ @date 2010-7-2 @param sql @param values @param batchSize @return @throws Exception / public List<Object> saveOrUpdateAll(String sql, List<Object[]> values, Integer batchSize) throws Exception { ResultSet rs = null; PreparedStatement ps = null; Connection conn = null; // 返回执行对象的id List<Object> ids = new ArrayList<Object>(); try { conn = getConnection(); connsetAutoCommit(false); ps = connprepareStatement(sql, PreparedStatementRETURN_GENERATED_KEYS); for (int i = 0; i < valuessize(); i++) { Object[] objects = valuesget(i); for (int j = 0; j < objectslength; j++) { pssetObject(i + 1, objects[j]); } if (i % batchSize == 0 || valuessize() <= batchSize) { psexecuteBatch(); rs = psgetGeneratedKeys(); int c = 0; while (rsnext()) { idsadd(rsgetObject(c)); c++; } } } conncommit(); } catch (Exception e) { connrollback(); throw e; } finally { destroy(rs, ps, conn); } return ids; } //update源码 public int update(final PreparedStatementCreator psc, final KeyHolder generatedKeyHolder) throws DataAccessException { AssertnotNull(generatedKeyHolder, "KeyHolder must not be null"); loggerdebug("Executing SQL update and returning generated keys"); Integer result = (Integer) execute(psc, new PreparedStatementCallback() { public Object doInPreparedStatement(PreparedStatement ps) throws SQLException { int rows = psexecuteUpdate(); List generatedKeys = generatedKeyHoldergetKeyList(); generatedKeysclear(); ResultSet keys = psgetGeneratedKeys(); if (keys != null) { try { RowMapper rowMapper = getColumnMapRowMapper(); RowMapperResultSetExtractor rse = new RowMapperResultSetExtractor(rowMapper, 1); generatedKeysaddAll((List) rseextractData(keys)); } finally { JdbcUtilscloseResultSet(keys); } } if (loggerisDebugEnabled()) { loggerdebug("SQL update affected " + rows + " rows and returned " + generatedKeyssize() + " keys"); } return new Integer(rows); } }); return resultintValue(); } //batchUpdate源码 public int[] batchUpdate(String sql, final BatchPreparedStatementSetter pss) throws DataAccessException { if (loggerisDebugEnabled()) { loggerdebug("Executing SQL batch update [" + sql + "]"); } return (int[]) execute(sql, new PreparedStatementCallback() { public Object doInPreparedStatement(PreparedStatement ps) throws SQLException { try { int batchSize = pssgetBatchSize(); InterruptibleBatchPreparedStatementSetter ipss = (pss instanceof InterruptibleBatchPreparedStatementSetter (InterruptibleBatchPreparedStatementSetter) pss : null); if (JdbcUtilssupportsBatchUpdates(psgetConnection())) { for (int i = 0; i < batchSize; i++) { psssetValues(ps, i); if (ipss != null && ipssisBatchExhausted(i)) { break; } psaddBatch(); } return psexecuteBatch(); } else { List rowsAffected = new ArrayList(); for (int i = 0; i < batchSize; i++) { psssetValues(ps, i); if (ipss != null && ipssisBatchExhausted(i)) { break; } rowsAffectedadd(new Integer(psexecuteUpdate())); } int[] rowsAffectedArray = new int[rowsAffectedsize()]; for (int i = 0; i < rowsAffectedArraylength; i++) { rowsAffectedArray[i] = ((Integer) rowsAffectedget(i))intValue(); } return rowsAffectedArray; } } finally { if (pss instanceof ParameterDisposer) { ((ParameterDisposer) pss)cleanupParameters(); } } } }); }
以上就是关于mybaitis批量插入怎么得到批量返回的自增ID全部的内容,包括:mybaitis批量插入怎么得到批量返回的自增ID、技术分享 | 关于 MySQL 自增 ID 的事儿、spring JdbcTemplate批量插入 怎么获得数据库自动增长的id等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)