JPA:常见错误解析及其解决方案说明


前言

很多Java开发者在写后端的时候,经常需要涉及到与数据库的数据交互,JPA就是一种常见的方式。
本文介绍了几种JPA开发中常见的错误及其解决方案,拓展说明了nativeQuery=true 的使用用法。


一、java.lang.IllegalStateException: Cannot determine target DataSource for lookup key [null] 问题

出现该问题的主要原因是:Java执行SQL查询语句时,数据库的指向没有明确。

解决方案:执行SQL前,一定要确保切换到了正确且明确的库,不要把库切错了或者干脆没有明确切换到哪个数据库就直接执行SQL查询语句,这样会很容易出问题。

二、javax.persistence.TransactionRequiredException: Executing an update/delete query 问题

出现该问题的主要原因是:JPA要求:没有事务支持,不能执行增删改操作。

解决方案:在Service层或者Repository层上必须加@Transactional,来代表这是一个事务级别的操作,增删改查除了查都是事务级别的。

代码实例:

推荐:Repository层添加@Transactional

@Transactional
@Modifying
@Query("UPDATE Person p SET p.email = :email WHERE p.id = :id")
void updatePersonEmail(@Param("id") Integer id, @Param("email") String email);

也可以:Service层添加@Transactional

@Transactional
public void UpdateInfo(Integer a,String b){
	pubRepository.updateInfo(a,b);
}

三、hibernate.exception.GenericJDBCException: could not extract ResultSet 问题

出错原因:JPA要求:在@Query注解中编写SQL实现 Delete 和 Update 操作的时候必须加上 @Modifying 注解,以通知 Spring Data 这是一个 Delete 或 Update 操作

解决方案:

@Transactional
@Modifying
@Query("UPDATE Person p SET p.email = :email WHERE p.id = :id")
void updatePersonEmail(@Param("id") Integer id, @Param("email") String email);

四、SQLGrammarException: could not extract ResultSet 问题

这个问题和第四个问题有点相似,都是could not extract ResultSet,但是原理不太一样。

出错原因:无法提取ResultSet,也就是说SQL返回的结果和实体类不匹配。

解决方案
(1) 检查 SQL 的查询内容和数据库列名是否匹配
(2) hibernate呢必须给实体类指定主键,需要在实体类里面加入注解。其中,@Id用来表示主键,@Basic用来表示非主键,@Column用来表示列名。
(3)JPA的 save 方法,在保存后会返回一个实体,因为没有主键的原因,所以就导致了报错。

代码示例如下:

@Entity
@Table(name = "PUB_BMXX")
@IdClass(BmxxInfoEntityPK.class) //标识实体类的主键说明类
public class BmxxInfoEntity {
    private Integer xh;
    private String bmmc;

    @Id
    @Column(name = "XH")
    public Integer getXh() {
        return xh;
    }

    public void setXh(Integer xh) {
        this.xh= xh;
    }
 
    @Basic
    @Column(name = "BMMC")
    public String getBmmc() {
        return bmmc;
    }

    public void setBmmc(String bmmc) {
        this.bmmc= bmmc;
    }
  
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        BmxxInfoEntity that = (BmxxInfoEntity) o;
        return Objects.equals(xh, that.xh) &&
                Objects.equals(bmmc, that.bmmc);
    }

    @Override
    public int hashCode() {
        return Objects.hash(xh, bmmc);
    }
}

五、拓展:nativeQuery=true 用法说明

解释:nativeQuery = true时,是可以执行原生sql语句,原生sql意思是这段sql拷贝到数据库中,然后把参数值给一下就能运行了(推荐使用!更符合常规使用习惯,和数据库中写的SQL相同)

示例如下:

@Query("select * from pub_ryxx where rymc=?1",nativeQuery=true)
Ryxx findByRymc(@Param("RYMC") String rymc);

其中,pub_ryxx 是数据库中的表名,rymc 是 pub_ryxx 表中的一个字段名称。

nativeQuery = false时,就不支持原生SQL了。

示例如下:

@Query("select rybh from Ryxx where rymc=?1",nativeQuery=false)
String findByRymc(@Param("RYMC") String rymc);

其中,Ryxx 是实体类的类名,rybh、rymc 都是是实体类中的一个字段名。
这种写法不太符合常规使用习惯,不推荐使用,但是两种方式的效果是一样的。


总结

本文介绍了几种JPA开发中常见的错误及其解决方案,拓展说明了nativeQuery=true 的使用用法。
希望对大家有用!

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
无法解析 com.querydsl:querydsl-jpa:${querydsl.version}是因为在引用中使用了变量${querydsl.version}。这种情况通常是在项目的pom.xml文件中定义了一个名为querydsl.version的属性,然后在引用中使用该属性的值。如果没有定义这个属性或者属性的值无法解析,就会出现无法解析的情况。为了解决这个问题,你可以在pom.xml文件中定义querydsl.version属性并赋予一个具体的值,或者直接在引用中使用具体的版本号。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [SpringBoot项目整合JPA+QueryDSL,及apt-maven-plugin报错问题解决](https://blog.csdn.net/weixin_42315600/article/details/103627304)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *3* [java.lang.NoSuchMethodError: com.querydsl.jpa.JPQLSerializer.....Ljava/util jar冲突](https://blog.csdn.net/weixin_38175213/article/details/127266784)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值