谢谢您的帮助:)
我试图获取最后一个ID,并阅读了很多有关它的文章,但我没有来此应用。
头等舱
var data = [{monthName:"Jun",name:"web",number:1,month:6},{monthName:"Jul",name:"web",number:2,month:7},{monthName:"Aug",name:"web",number:2,month:8},{monthName:"Jun",name:"sales",number:12,month:6},{monthName:"Jul",name:"sales",number:2,month:7}];
function mergeName(arr) {
let map = data.reduce((a,c) => (a[c.name] = ({...c,
number: a[c.name] && a[c.name].number
? a[c.name].number.push(c.number) && a[c.name].number
: [c.number]}),a),{});
return Object.entries(map).map(o => ({name: o[0], number: o[1].number}))
}
console.log(mergeName(data))
第二类(AdsEntity)
private Date date;
private List<AdsEntity> adsDetails;
... getters and setters
有代码我尝试获取最后一个ID:
映射器
private int id;
private String description;
在调试模式下,当我观看列表时,我看到ID仍为0,并且没有任何ID。
所以我写的东西没有锻炼:(
解决方案尝试使用@Roman Konoval的答案:
@Roman Konoval
我照你说的做了,桌子摆放得很好:) 仍然只是一个问题,ID未填写
@Insert({
"<script>",
"INSERT INTO tb_ads_details (idMyInfo, adDate)"
+ " VALUES"
+ " <foreach item='adsDetails' index='index' collection='adsDetails' separator=',' statement='SELECT LAST_INSERT_ID()' keyProperty='id' order='AFTER' resultType='java.lang.Integer'>"
+ " (#{adsDetails.description, jdbcType=INTEGER}) "
+ " </foreach> ",
"</script>"})
void saveAdsDetails(@Param("adsDetails") List<AdsDetailsEntity> adsDetails);
感谢您的帮助:)
解决方案从@Chris建议添加到@Roman Konoval提案
@Chris和@Roman Konoval
@Insert("INSERT INTO tb_ads_details SET `idMyInfo` = #{adsDetail.idMyInfo, jdbcType=INTEGER}, `adDate` = #{adsDetail.adDate, jdbcType=DATE}")
@SelectKey(statement = "SELECT LAST_INSERT_ID()", before = false, keyColumn = "id", keyProperty = "id", resultType = Integer.class )
void saveAdsDetails(@Param("adsDetail") AdsDetailsEntity adsDetail);
default void saveManyAdsDetails(@Param("adsDetails") List<AdsDetailsEntity> adsDetails)
{
for(AdsDetailsEntity adsDetail:adsDetails) {
saveAdsDetails(adsDetail);
}
}
感谢大家的3条建议!
答案 0 :(得分:2)
是的。它不起作用。
请看一下mapper.dtd
foreach
-标记不支持/提供以下属性statement
,keyProperty
order
和resultType
如果您需要每个插入项的ID,请让DataAccessObject
处理迭代并在MapperInterface中使用类似的内容
@Insert("INSERT INTO tb_ads_details (idMyInfo, adDate) (#{adsDetail.idMyInfo, jdbcType=INTEGER}, #{adsDetail.adDate, jdbcType=DATE})")
@SelectKey(before = false, keyColumn = "ID", keyProperty = "id", resultType = Integer.class, statement = { "SELECT LAST_INSERT_ID()" } )
void saveAdsDetails(@Param("adsDetail") AdsDetailsEntity adsDetail);
请确保AdsDetailsEntity
-Class
提供属性idMyInfo
和adDate
编辑2019-08-21 07:25
一些解释
引用所提到的dtd <selectKey>
标签仅允许作为<insert>
和<update>
的直接子代。它是指传递到映射器方法并声明为Object
的单个parameterType
。
它仅执行一次,并且其order
属性告诉myBatis是否在插入/更新语句之前或之后执行它。
在您的情况下,<script>
创建一个发送到数据库并由数据库处理的单个语句。
允许将@Insert
与<script>
和<foreach>
结合在@SelectKey
内部。但是myBatis不会拦截/观察/监视处理给定语句的数据库。如前所述,@SelectKey
仅在@Insert
执行之前或之后执行一次。因此,在您的特定情况下,@SelectKey
返回最后插入的元素的ID。如果您的脚本插入了十个元素,则仅返回新生成的第十个元素的ID。但是@SelectKey
需要具有getter和setter的类属性,以将所选ID放入List<?>
不提供的ID中。
示例
让我们说您要保存一个Advertisement
及其AdvertisementDetail
s
Advertisement
具有ID,日期和详细信息
public class Advertisement {
private List<AdvertisementDetail> adDetails;
private Date date;
private int id;
public Advertisement() {
super();
}
// getters and setters
}
AdvertisementDetail
有其自己的ID,说明和它所属的Advertisement
的ID
public class AdvertisementDetail {
private String description;
private int id;
private int idAdvertisement;
public AdvertisementDetail() {
super();
}
// getters and setters
}
MyBatis映射器可能看起来像这样。 @Param
未使用,因此可以直接访问属性。
@Mapper
public interface AdvertisementMapper {
@Insert("INSERT INTO tb_ads (date) (#{date, jdbcType=DATE})")
@SelectKey(
before = false,
keyColumn = "ID",
keyProperty = "id",
resultType = Integer.class,
statement = { "SELECT LAST_INSERT_ID()" })
void insertAdvertisement(
Advertisement ad);
@Insert("INSERT INTO tb_ads_details (idAdvertisement, description) (#{idAdvertisement, jdbcType=INTEGER}, #{description, jdbcType=VARCHAR})")
@SelectKey(
before = false,
keyColumn = "ID",
keyProperty = "id",
resultType = Integer.class,
statement = { "SELECT LAST_INSERT_ID()" })
void insertAdvertisementDetail(
AdvertisementDetail adDetail);
}
DataAccessObject
(DAO)可能看起来像这样
@Component
public class DAOAdvertisement {
@Autowired
private SqlSessionFactory sqlSessionFactory;
public DAOAdvertisement() {
super();
}
public void save(
final Advertisement advertisement) {
try (SqlSession session = this.sqlSessionFactory.openSession(false)) {
final AdvertisementMapper mapper = session.getMapper(AdvertisementMapper.class);
// insert the advertisement (if you have to)
// its new generated id is received via @SelectKey
mapper.insertAdvertisement(advertisement);
for (final AdvertisementDetail adDetail : advertisement.getAdDetails()) {
// set new generated advertisement-id
adDetail.setIdAdvertisement(advertisement.getId());
// insert adDetail
// its new generated id is received via @SelectKey
mapper.insertAdvertisementDetail(adDetail);
}
session.commit();
} catch (final PersistenceException e) {
e.printStackTrace();
}
}
}
答案 1 :(得分:1)
Chris关于无法在foreach
中获取ID的内容是正确的。但是,有一种方法可以在映射器中实现id提取,而无需在外部进行。如果您使用say spring并没有单独的DAO层,而mybatis映射器是存储库,则这可能会有所帮助。
您可以使用default interface method(请参阅another tutorial)通过为单个项目插入调用映射器方法来插入项目列表,而单个项目插入方法本身会进行id选择:
interface ItemMapper {
@Insert({"insert into myitem (item_column1, item_column2, ...)"})
@SelectKey(before = false, keyColumn = "ID",
keyProperty = "id", resultType = Integer.class,
statement = { "SELECT LAST_INSERT_ID()" } )
void saveItem(@Param("item") Item item);
default void saveItems(@Param("items") List<Item> items) {
for(Item item:items) {
saveItem(item);
}
}
答案 2 :(得分:1)
如果您的数据库驱动程序通过java.sql.Statement#getGeneratedKeys()
(MS SQL Server,例如,does not support it,ATM),数据库/驱动程序支持多个生成的密钥,则MyBatis可以将生成的密钥分配给列表参数。 。
以下示例已在MySQL 5.7.27 + Connector / J 8.0.17中进行了测试(您应该在问题中包含版本信息)。
请确保使用最新版本的MyBatis(= 3.5.2),因为最近进行了一些规格更改和错误修复。
表定义:
CREATE TABLE le tb_ads_details (
id INT PRIMARY KEY AUTO_INCREMENT,
description VARCHAR(32)
)
POJO:
private class AdsDetailsEntity {
private int id;
private String description;
// getters/setters
}
映射器方法:
@Insert({
"<script>",
"INSERT INTO tb_ads_details (description) VALUES",
"<foreach item='detail' collection='adsDetails' separator=','>",
" (#{detail.description})",
"</foreach>",
"</script>"
})
@Options(useGeneratedKeys = true, keyProperty="adsDetails.id", keyColumn="id")
void saveAdsDetails(@Param("adsDetails") List<AdsDetailsEntity> adsDetails);
注意:插入大量行时,应使用批处理插入(带有ExecutorType.BATCH
)而不是多行插入(= {<foreach/>
)。