mybatis - MyBatis ...在循环“foreach”中获取最后一个插入ID
问题描述
谢谢你的帮助 :)
我试图获得最后一个 id,并阅读了很多关于它的帖子,但我没有到达我的案例中应用它。
头等舱
private Date date;
private List<AdsEntity> adsDetails;
... getters and setters
第二类(AdsEntity)
private int id;
private String description;
有我尝试获取最后一个 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);
在调试模式下,当我观看 List 时,我看到 id 仍然为 0 并且没有得到任何 id。
所以我写的东西没有锻炼:(
解决方案尝试使用@Roman Konoval 的答案:
@Roman Konoval
我应用了你所说的,并且桌子已经设置好了:)还有一个问题,ID不满足
@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);
}
}
感谢您的帮助 :)
解决方案添加到来自@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 = "adsDetail.id", resultType = int.class )
void saveAdsDetails(@Param("adsDetail") AdsDetailsEntity adsDetail);
default void saveManyAdsDetails(@Param("adsDetails") List<AdsDetailsEntity> adsDetails)
{
for(AdsDetailsEntity adsDetail:adsDetails) {
saveAdsDetails(adsDetail);
}
}
谢谢大家的3条建议!!!
解决方案
是的。它不起作用。
请看一下mapper.dtd
foreach
-tag 不支持/提供以下属性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>
-tag 只允许作为<insert>
and的直接子级<update>
。它指的Object
是传递给映射器方法并声明为的单个parameterType
。
它只执行一次,它的order
属性告诉 myBatis 是在插入/更新语句之前还是之后执行它。
在您的情况下,<script>
创建一个发送到数据库并由数据库处理的语句。
允许在and内部与 and@Insert
结合。但 myBatis 不会拦截/观察/监视处理给定语句的数据库。并且如前所述,仅在执行之前或之后执行一次。因此,在您的特定情况下,返回最后插入元素的 id。如果您的脚本插入十个元素,则只会返回第十个元素的新生成的 id。但需要一个带有 getter 和 setter 的类属性来将选定的 id 放入 - 这不提供。<script>
<foreach>
@SelectKey
@SelectKey
@Insert
@SelectKey
@SelectKey
List<?>
例子
假设您要保存 anAdvertisement
及其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-mapper 可能看起来像这样。@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();
}
}
}
推荐阅读
- c++ - 如何在可变参数模板函数中使用 source_location?
- html - 如何在导航中垂直居中徽标?
- python - 在一次试验中更新数据并再次使用更新数据的功能
- django - 如何正确更新 django 中的用户配置文件
- python - Beautifulsoup 是否有可以删除所有空格的功能
- node.js - 我在使用 npm install express 时遇到问题
- docker - 无法连接到 docker 容器
- node.js - 业务逻辑nodejs放在哪里
- npm - 端口 4200 已在使用中。使用“--port”指定不同的端口
- python - ValueError:检查目标时出错:预期dense_1的形状为(16、1、2)但得到的数组形状为(2、1、1)