JPA里自定义SQL查询的一些问题

本文分享了一次使用SpringData JPA进行数据库操作时遇到的问题:因前端返回的ID与实体类中属性命名差异导致的查询失败案例。通过调整命名规则解决了系统错误,并介绍了如何避免下划线引起的误解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

接着上次的图书管理系统

还书的时候不仅要在还书的数据表添加新纪录
还要去把借书表中对应的内容删除

但是因为前端我写的时候只返回了book_id和client_id
所以在还书的Service里还要根据这两个id去查出对应的借书记录,并删掉

这里可以用Spring data 里的自定义查询来实现
自定义查询以及Spring data JPA的使用方法可以在这里 有相关的介绍

因为我在设定Rent这个实体类了里设定的是book_id和client_id
所以在机智的IDEA的帮助下,我写了这么一句在repository里写了这么一句

     
1
     
Rent findByClient_idAndBook_id(Integer client_id, Integer book_id);

哈哈,这不是简单吗
然后运行
报错
哦,我天呐,来看看控制台的信息吧

     
1
     
No property client found for type Rent!

我来简单翻译下
在Rent里找不到client属性

client? 不是client_id 吗

经过查找,终于在文档里发现 一个下划线 _ 会被认为是And的意思
所以findByClient_idAndBook_id 就被理解为 根据client 和 id 和 book 和 id 来查找
然后系统在Rent里找不到client 所以就报错了

该怎么办呢?

嗯,所以命名时候就不要用_ 下划线就好了(IDEA 还挺 ‘机智’的)
现在去改应该还来的及
不说了,现在去改了..

### 如何在 JPA 中使用自定义 SQL 查询 #### 方法一:通过 `@Query` 注解使用 JPQL 或原生 SQL 可以利用 `@Query` 注解来编写自定义查询语句。如果需要执行标准的 JPQL 查询,则直接书写 JPQL;如果是复杂的场景或者数据库特定的功能需求,可以选择使用原生 SQL。 以下是基于 JPQL 的示例: ```java @Repository public interface UserRepository extends JpaRepository<User, Long> { @Query("SELECT u FROM User u WHERE u.email = ?1") List<User> findUsersByEmail(String email); } ``` 对于更复杂的情况,比如涉及多个表联结或其他高级功能时,可采用原生 SQL 并设置 `nativeQuery=true` 参数[^1]: ```java @Repository public interface UserRepository extends JpaRepository<User, Long> { @Query(value = "SELECT * FROM users WHERE email = ?1", nativeQuery = true) List<User> findUsersByEmailNative(String email); } ``` --- #### 方法二:通过实体管理器 (`EntityManager`) 创建动态查询查询逻辑较为复杂且无法完全由接口方法名推断出来时,可以通过注入 `EntityManager` 实现灵活控制。这种方式允许手动构建 SQL 字符串并绑定参数。 下面是一个例子展示了如何实现带条件过滤的动态查询[^2]: ```java @Service public class UserService { @PersistenceContext private EntityManager entityManager; public List<UserInfo> queryUserInfoByUserNo(String userNo) { StringBuilder sqlBuilder = new StringBuilder("SELECT * FROM t_user WHERE user_no = :userNo"); Query nativeQuery = entityManager.createNativeQuery(sqlBuilder.toString(), UserInfo.class); nativeQuery.setParameter("userNo", userNo); return nativeQuery.getResultList(); } } ``` 此方式适合于那些需要频繁调整查询结构的应用场合,例如分页、排序以及多种筛选组合等情形下尤为有用。 --- #### 方法三:扩展 Repository 接口以支持更多操作模式 除了基本 CRUD 功能外,还可以让自己的 DAO 层继承额外的能力类如 `JpaSpecificationExecutor<T>` ,从而获得更加丰富的 API 支持用于处理定制化请求[^3]: ```java @Repository public interface ToolsSysDao extends JpaRepository<ToolsSysEntity, String>, JpaSpecificationExecutor<ToolsSysEntity> { // 定义按名称检索记录,并按照顺序号降序排列的结果集返回函数 List<ToolsSysEntity> findAllBySysNameOrderByOrderNumDesc(String sysName); } ``` 这种设计不仅简化了业务层调用过程中的编码工作量,同时也增强了系统的可维护性和灵活性。 --- ### 注意事项 - 如果选择使用原生 SQL,请记得开启 `nativeQuery=true` 配置项以便框架能够识别所传入的是非 JPQL 形式的命令。 - 对外部输入数据务必做好校验与清理措施以防潜在的安全隐患诸如 SQL 注入攻击等问题发生。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值