1

我正在做一个 Spring Boot 项目,我有两个通过 OneToMany 关系相互关联的表

public class PackGroupEntity{
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String description;
    private Double qty;
    private Integer packingNr;
    @Temporal(TemporalType.TIMESTAMP)
    private Date deliveredTime;
    @OneToMany(mappedBy = "packGroup", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY)
    private List<PackArticlesEntity> packArticles= new ArrayList<>();
}

public class PackArticlesEntity{
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private Double qty;
    private Double confirmedName;
    @Enumerated(EnumType.STRING)
    private ArticleStatus status;
    private Double weight;
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "pack_group_id")
    private PackGroupEntity packGroup;
}

我在这两个表上循环插入数据,首先我按包装号对文章进行分组,我将为此创建一个包含文章列表的 PackGroup:

Map<Integer, List<RecivedArticlesDTO >> groupedArticles =
                    recivedArticlesListDTO.stream().collect(Collectors.groupingBy(RecivedArticlesDTO::getPackingNr));
    for (Map.Entry<Integer, List<RecivedArticlesDTO>> entry : groupedArticles.entrySet()) {

        List<RecivedArticlesDTO > groups = entry.getValue();
        PackGroupEntity packGroup = new PackGroupEntity();
        packGroup.setPackingNr(entry.getKey())
        //some manipulations and setting data for each field 

       List<PackArticlesEntity> listWithArticles = new ArrayList<>();
       groups.forEach(pack -> {
            PackArticlesEntity packArticle= new PackArticlesEntity();
            packArticles.setQty(pack.getQty);
            //some manipulations and setting data for each field 
            listWithArticles.add(packArticles);
      }
      packGroup.setPackArticles(listWithArticles);

      // here I have to save the data using native query 
     packGroupService.savePackGroupData(packGroup);
}

这样,它太慢了,所以我想在本机查询上做。问题是我有很多 packGroups 和很多 packArticles 需要保存。我想以某种方式只与 DB 建立一个连接以发送要保存的包组列表和打包文章,但我不知道如何在本机查询中执行此操作。这仅适用于一个 pack_group 但我不知道如何传递packArticles 本机查询,因为它是一个列表

@Query(value = "insert  into pack_group " +
        "        (id,packing_nr, description, qty, deliveredTime, packArticles) " +
        "       values (1?, 2?, 3?, 4?, 5?, 6?)", nativeQuery = true)
void savePackGroupData(id, packing_nr, description, qty, packArticles);

有人可以帮忙吗?

编辑:我想从插入返回 id

    String query = String.format("insert into pack_group(group, remark, description ) " +
 "values ( %s, %s, %s)", "x","y","z"  );
    Query q = entityManager.createNativeQuery(query );
    BigInteger biid = (BigInteger) q.getSingleResult();
    long id = biid.longValue();

我得到这个错误com.microsoft.sqlserver.jdbc.SQLServerException: The statement did not return a result set.

4

2 回答 2

0

为了加快速度,请考虑使用批量更新。使用弹簧数据使其工作可能有点棘手,但它在工作时确实会大大加快速度。

请参阅如何使用 JpaRepository 进行批量(多行)插入?

如果您希望对插入语句进行更多控制,那么 spring jdbc 可能是一个更好的选择:How to do multiple inserts in database using spring JDBC Template batch?

于 2021-08-11T10:41:28.923 回答
0

这是“我有一个文章列表,我必须在其中使用之前插入的包组的参考 ID”的答案。你能在 SQL 上得到它吗?在评论中。

您有主表和详细表。并且您想先插入 Main,然后再插入 Detail,并插入 Main 的 Id。

您可以使用output insertedSQL Server 仅获取当前插入的行。您可以将它与 string_split 结果连接以插入到详细信息表中。

这是一个例子。

create table Main (
    Id int identity(1, 1),
    Name nvarchar(50)
);
create table Detail (
    MainId int,
    Name nvarchar(50)
);
insert into Main (Name) values ('X'); -- To make new inserted Id starts with 2
declare @MainList nvarchar(1000) = 'A,B,C';
declare @DetailList nvarchar(1000) = 'A2,B2,C2';

declare @IdList table (
    Seq int identity(1, 1),
    Id int
);

-- Insert 3 rows, get all 3 Id using inserted, insert 3 Id to @IdList table
insert into Main (Name)
output inserted.Id into @IdList
select value from string_split(@MainList, ',');

-- Join @IdList table with string_split returned table with Seq
-- Seq of @IdList is auto generated by identity(1, 1)
-- Seq of string_split returned table generated by row_number()
insert into Detail (MainId, Name)
select m.Id MainId, d.value Name
from   @IdList m
       inner join
       (select row_number() over (order by (select 1)) Seq, value
       from    string_split(@DetailList, ',')
       ) d
       on m.Seq = d.Seq;

结果:

select * from Main;
select * from Detail;
Id  Name
--------
1   X
2   A
3   B
4   C

MainId  Name
------------
2   A2
3   B2
4   C2

演示:https ://dbfiddle.uk/?rdbms=sqlserver_2019&fiddle=30213ab0cd59fcb7f541c18c738d4dad

于 2021-08-11T13:39:40.133 回答