使用@Query
使用jpa时,如果要手写sql可以使用@Query注解,使用原生sql时参数nativeQuery要置为true。
注入参数的方式
- 方式一:使用?
@Query("select * from block where height > ?2 order by height desc limit ?1", nativeQuery = true)
fun queryForIndex(size: Int, startHeight: Long): List<Block>
- 方式二:使用@Param (org.springframework.data.repository.query.Param)
@Query("select * from block where height > :startHeight order by height desc limit :size", nativeQuery = true)
fun queryForIndex(@Param("size") size: Int, @Param("startheight") startHeight: Long): List<Block>
- 方式三:使用对象
@Query("select * from Block where height > :#{po.startHeight} order by height desc limit :#{po.size}")
fun queryForIndex(po: IndexPO) startHeight: Long): List<Block>
注意:使用对象时,nativeQuery参数为false,实际上我们写的HQL语句,Block是对象名并不是表名。
本猿在jpa项目中也曾遇到需要使用复杂动态sql的情况,最终是在项目中同时引用的jpa和mybatis,觉得写复杂的sql查询(动态条件比较多)时,还是mybatis方便高效些。
修改与删除
使用@Query修改与删除时,需要添加@Modifying、@Transactional。
@Query(value = "delete from contract_url where contract_address = ?1 ", nativeQuery = true)
@Modifying
@Transactional
fun deleteByContractAddress(contractAddress: String)
@Modifying: 当现在修改删除时需要加上此注解。
@Transactional:
默认情况下,repository 接口中的CRUD方法都是被@Transactional注解修饰了的,对于读的操作方法,@Transactional注解的readOnly属性是被设置为true的,即只读;CRUD中的其他方法被@Transactional修饰,即非只读。
如果你需要修改repository 接口中的某些方法的事务属性,可以在该方法上重新加上@Transactional注解,并设置需要的属性。
/**
* {@code true} if the transaction is read-only.
* <p>Defaults to {@code false}.
* <p>This just serves as a hint for the actual transaction subsystem;
* it will <i>not necessarily</i> cause failure of write access attempts.
* A transaction manager which cannot interpret the read-only hint will
* <i>not</i> throw an exception when asked for a read-only transaction
* but rather silently ignore the hint.
* @see org.springframework.transaction.interceptor.TransactionAttribute#isReadOnly()
*/
boolean readOnly() default false;