1. 程式人生 > >使用Hibernate遇到的各種異常坑

使用Hibernate遇到的各種異常坑

前言

今天使用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謝謝你的支援。

================================================================================
感謝閱讀,寫得不好的地方請指教,能幫助到你是對我最好的回報,不卑不亢,加油。
請你記住比你優秀的一定比你努力,比你努力的人一定比你優秀。
================================================================================