首页 > 解决方案 > 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条建议!!!

标签: mybatis

解决方案


是的。它不起作用。

请看一下mapper.dtd

foreach-tag 不支持/提供以下属性statementkeyProperty 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提供属性idMyInfoadDate

编辑 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@SelectKeyList<?>

例子

假设您要保存 anAdvertisement及其AdvertisementDetails

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);
}

( DataAccessObjectDAO) 可能看起来像这样

@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();
        }
    }
}

推荐阅读