spring-data-jpa 使用 @Query 和 @Modifying 插入而不使用 nativeQuery 或 save() 或 saveAndFlush()

Posted

技术标签:

【中文标题】spring-data-jpa 使用 @Query 和 @Modifying 插入而不使用 nativeQuery 或 save() 或 saveAndFlush()【英文标题】:spring-data-jpa to insert using @Query & @Modifying without using nativeQuery or save() or saveAndFlush() 【发布时间】:2018-01-26 14:50:39 【问题描述】:

我看过这些链接

How to use JPA Query to insert data into db? 使用 nativeQuery=true How to insert into db in spring-data? 建议使用内置的保存方法(还有一个 saveAndFulsh() 方法)

我的例子如下:

Person 是一个简单的实体,包含 3 个字段“Long id、String name、Integer age”,并且映射到对应的 Person 表,每个表包含 3 个列)

@Repository
public interface DualRepository extends JpaRepository<Dual,Long> 
    @Modifying
    @Query(? - what goes here - ?)
    public int modifyingQueryInsertPerson(@Param("id")Long id, @Param("name")String name, @Param("age")Integer age);

有没有办法只使用@Query & @Modifying 进行插入(即不使用本机 SQL 查询 & nativeQuery=true,或者,save(),或者,saveAndFlush()?

【问题讨论】:

【参考方案1】:

而不是传递所有参数,您可以传递 java 对象,如下所示

 @Modifying(clearAutomatically = true)
    @Transactional
    @Query(value = "insert into [xx_schema].[shipment_p] (gpn,qty,hscode,country_of_origin,created_date_time,shipment_id) "
            + "VALUES (:##sp.gpn,:##sp.qty,  :##sp.hscode ,:##sp.countryOfOrigin, :##sp.createdDateTime, :##sp.id )", nativeQuery = true)
    public void saveShipmentPRoducts(@Param("sp") ShipmentProducts sp);

【讨论】:

【参考方案2】:

@Query 通常用于创建自定义用户查询以从数据库中获取值

@Query@Modifying 用于在数据库中执行更新操作

save 方法用于插入新记录或更新会话中存在的记录。

【讨论】:

请看我上面的评论。使用 @Query+@Modifying 的 INSERT 将适用于具有虚拟表的数据库(如 Oracle 中的 DUAL),因此我们可以在 SELECT 之后有一个 FROM 子句(这是 HQL 所要求的)。【参考方案3】:

在尝试了几件事之后,有一种方法可以做到这一点,但这取决于您使用的数据库。

下面在 Oracle 中为我工作 & 1 行被插入到表中(使用 Dual 表,因为我可以在“select”之后使用“from Dual”):

@Repository
public interface DualRepository extends JpaRepository<Dual,Long> 
    @Modifying
    @Query("insert into Person (id,name,age) select :id,:name,:age from Dual")
    public int modifyingQueryInsertPerson(@Param("id")Long id, @Param("name")String name, @Param("age")Integer age);

在 MS SqlServer 中,可以有一个没有“from 子句”的“select”,所以“select 10,'name10',100”可以工作,所以下面的内容应该适用于 MS Sqlserver(但还没有测试过)

@Repository
public interface PersonRepository extends JpaRepository<Person,Long> 
    @Modifying
    @Query("insert into Person (id,name,age) select :id,:name,:age")
    public int modifyingQueryInsertPerson(@Param("id")Long id, @Param("name")String name, @Param("age")Integer age);

我没有尝试过使用任何其他数据库。这是一个链接,它显示(最后)哪个 db 支持不带 from 子句的 select stmts:http://modern-sql.com/use-case/select-without-from

【讨论】:

经过进一步测试,它在 MS-SqlServer 中工作,因为 MS-SqlServer 不提供系统虚拟表(如 Oracle 中的 DUAL)。它确实在 Oracle 和 mysql 中工作,因为它们都有一个 DUAL 虚拟表。由于 HQL 在 SELECT 之后需要 FROM,因此仅当底层数据库具有虚拟表(如 Oracle 中的 DUAL)时,上述方法才适用于 INSERT。

以上是关于spring-data-jpa 使用 @Query 和 @Modifying 插入而不使用 nativeQuery 或 save() 或 saveAndFlush()的主要内容,如果未能解决你的问题,请参考以下文章

spring-data-jpa 存储库在 Query 中使用 Collection 作为 @Param

spring-data-jpa 使用 @Query 和 @Modifying 插入而不使用 nativeQuery 或 save() 或 saveAndFlush()

在 spring-data-jpa 中通过布尔属性查询而不使用方法参数

学习Spring-Data-Jpa---定义方法查询

没有 JPQL 查询的 Spring-data-jpa 中的 CURRENT_DATE

Spring-data-jpa:批量插入不起作用