使用Hibernate遇到的各种异常坑

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_22067469/article/details/85221699

前言

今天使用SpringBoot整合Hibernate的时候测试的时候遇到一些异常问题,准备总结一下。把问题记录下来,希望能够帮助大家解决。

整合环境

  • SpringBoot 2.1.1
  • JDK1.8
  • Hibernate5.3.7

异常一

异常信息如下
org.springframework.dao.InvalidDataAccessApiUsageException: org.hibernate.QueryException: Legacy-style query parameters (`?`) are no longer supported;
use JPA-style ordinal parameters (e.g., `?1`) instead : FROM com.wip.hibernate.dao.entity.Article as a WHERE a.title = ? and a.category = ? [FROM com.wip.hibernate.dao.entity.Article as a WHERE a.title = ? and a.category = ?];
nested exception is java.lang.IllegalArgumentException: org.hibernate.QueryException: Legacy-style query parameters (`?`) are no longer supported;
use JPA-style ordinal parameters (e.g., `?1`) instead : FROM com.wip.hibernate.dao.entity.Article as a WHERE a.title = ? and a.category = ? [FROM com.wip.hibernate.dao.entity.Article as a WHERE a.title = ? and a.category = ?]
Caused by: org.hibernate.QueryException: Legacy-style query parameters (`?`) are no longer supported;

use JPA-style ordinal parameters (e.g., `?1`) instead : FROM com.wip.hibernate.dao.entity.Article as a WHERE a.title = ? and a.category = ? [FROM com.wip.hibernate.dao.entity.Article as a WHERE a.title = ? and a.category = ?]
 
Caused by: org.hibernate.QueryException: Legacy-style query parameters (`?`) are no longer supported; use JPA-style ordinal parameters (e.g., `?1`) instead : FROM com.wip.hibernate.dao.entity.Article as a WHERE a.title = ? and a.category = ?
代码如下(Dao)

下面代码主要写了一个查询,查询文章标题和分类是否同时间存在,用的是点位设置参数的方式,在其他博主看到说Hibernate4.1之后对于HQL中查询的点位符做了改进,由于我这里是使用的老式的点位符所以报了上面的异常。

public boolean articleExists(String title, String category) {
    String hql = "FROM Article as a WHERE a.title = ? and a.category = ?";
    int count = entityManager.createQuery(hql).setParameter(0, title)
            .setParameter(1, category).getResultList().size();
    return count > 0;
}
解决办法

从告警提示信息中可以看出,它建议用命名参数或者JPA占位符两中种方法来代替老的占位符查询方法。

  • 方法一,改成命名参数的方式
public boolean articleExists(String title, String category) {
    String hql = "FROM Article as a WHERE a.title = :title and a.category = :category";
    int count = entityManager.createQuery(hql).setParameter("title", title)
            .setParameter("category", category).getResultList().size();
    return count > 0;
}
  • 方法二:改成JPA点位符的方式
public boolean articleExists(String title, String category) {
    String hql = "FROM Article as a WHERE a.title = ?0 and a.category = ?1";
    int count = entityManager.createQuery(hql).setParameter(0, title)
            .setParameter(1, category).getResultList().size();
    return count > 0;
}
  • 注意:其中 "?" 后面的 "0"代表索引位置,在HQL名句中可以重复出现,并不一定是从0开始,可以是任何数字,只是参数要与期对应上。
  • 采用后面两种查询方法修改后就不会有异常产生了,个人推荐使用方法一,看起来更直观一点,性能方面相对也会好一点。
  • 日志打印成功SQL语句
    select
       article0_.article_id as article_1_0_,
       article0_.category as category2_0_,
       article0_.title as title3_0_ 
    from
       articles article0_ 
    where
       article0_.title=? 
       and article0_.category=?
    

异常二

异常信息如下
org.springframework.dao.InvalidDataAccessApiUsageException: No EntityManager with actual transaction available for current thread - cannot reliably process 'persist' call;
nested exception is javax.persistence.TransactionRequiredException: No EntityManager with actual transaction available for current thread - cannot reliably process 'persist' call
Caused by: javax.persistence.TransactionRequiredException: No EntityManager with actual transaction available for current thread - cannot reliably process 'persist' call
代码如下(Service)

下面代码先是判断文章文章是否存在,不存在则执行添加方法。

public synchronized boolean addArticle(Article article) {
    if (articleDao.articleExists(article.getTitle(),article.getCategory())) {
        return false;
    } else {
        articleDao.addArticle(article);
        return true;
    }
}
解决办法

由于使用EntityManager的时候在进行增删改的时候需要添加事务Transactional,由于我这里没有加所以出现上面异常。

  • 添加 @Transactional即可
@Transactional
public synchronized boolean addArticle(Article article) {
    if (articleDao.articleExists(article.getTitle(),article.getCategory())) {
        return false;
    } else {
        articleDao.addArticle(article);
        return true;
    }
}
  • 注意,添加事务可以直接在方法上添加,也可以直接在类上添加,在类上添加的话代表每个方法都代有事务。
  • 日志打印添加成功SQL语句
    insert 
    into
        articles
        (category, title) 
    values
        (?, ?)
    

异常三

异常信息如下
org.springframework.dao.InvalidDataAccessResourceUsageException: error performing isolated work;
SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: error performing isolated work
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'bucket_test.hibernate_sequence' doesn't exist
代码如下

这里同样是执行添加方法的时候出错的,看到其它博主说是ID自增的问题,我这里设置的是GenerationType.AUTO,所以会出现上面异常。

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "article_id")
private int articleId;
解决办法

在实体类上修改@GeneratedValue的strategy即可,将AUTO属性改成IDENTITY属性。

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "article_id")
private int articleId;
  • 最后完美解决。
以上是我遇到的一些坑,后续会持续更新,有问题欢迎留言,看到第一时间回复。

最后附上:SpringBoot整合全家桶 欢迎star谢谢你的支持。

================================================================================
感谢阅读,写得不好的地方请指教,能帮助到你是对我最好的回报,不卑不亢,加油。
请你记住比你优秀的一定比你努力,比你努力的人一定比你优秀。
================================================================================

猜你喜欢

转载自blog.csdn.net/qq_22067469/article/details/85221699