InvalidDataAccessApiUsageException尝试使用JPA查询Enum值时发生错误。

huangapple go评论82阅读模式
英文:

InvalidDataAccessApiUsageException trying to find using JPA query with Enum value

问题

Enum def -

  1. // 枚举定义
  2. public enum someAccountType {
  3. ACCOUNT_NUMBER("account_number"),
  4. CREDIT_CARD("credit_card");
  5. public final String v;
  6. someAccountType(String value) {
  7. this.v = value;
  8. }
  9. }
  1. @AllArgsConstructor
  2. @Getter
  3. @Entity
  4. @Builder
  5. @Setter
  6. public class SomeDetail {
  7. @Id
  8. @GeneratedValue(strategy = GenerationType.AUTO)
  9. private Long id;
  10. @Enumerated(EnumType.STRING)
  11. @Column(name="accountType")
  12. private Enum.someAccountType accountType;
  13. ..
  14. }

Repository -

  1. // 存储库定义
  2. @Repository
  3. public interface SomeDetailRepository extends JpaRepository<SomeDetail, Long> {
  4. List<SomeDetail> findByEncryptedIfscAndEncryptedAccountNoAndAccountTypeAndIsValid(
  5. String encryptedIfsc, String encryptedAccountNo, String accountType, Boolean isValid);
  6. }

Service call -

  1. // 服务调用
  2. List<SomeDetail> someDetails = someDetailRepository.findByEncryptedIfscAndEncryptedAccountNoAndAccountTypeAndIsValid(
  3. ben.getEncryptedIfsc(), ben.getEncryptedAccountNo(), Enum.someAccountType.CREDIT_CARD.v, isValid);

Exception -

  1. // 异常信息
  2. org.springframework.dao.InvalidDataAccessApiUsageException: Parameter value [credit_card] did not match expected type [Enum$someAccountType (n/a)]; nested exception is java.lang.IllegalArgumentException: Parameter value [credit_card] did not match expected type [Enum$someAccountType (n/a)]
  3. Why is it throwing this exception? I have defined @Enumerated(EnumType.STRING) so it should expect string type stored in db.
英文:

Enum def -

  1. public enum someAccountType {
  2. ACCOUNT_NUMBER(&quot;account_number&quot;),
  3. CREDIT_CARD(&quot;credit_card&quot;);
  4. public final String v;
  5. someAccountType(String value) {
  6. this.v = value;
  7. }
  8. }
  9. @AllArgsConstructor
  10. @Getter
  11. @Entity
  12. @Builder
  13. @Setter
  14. public class SomeDetail {
  15. @Id
  16. @GeneratedValue(strategy = GenerationType.AUTO)
  17. private Long id;
  18. @Enumerated(EnumType.STRING)
  19. @Column(name=&quot;accountType&quot;)
  20. private Enum.someAccountType accountType;
  21. ..
  22. }

Repository -

  1. @Repository
  2. public interface SomeDetailRepository extends JpaRepository&lt;SomeDetail, Long&gt; {
  3. List&lt;someDetail&gt; findByEncryptedIfscAndEncryptedAccountNoAndAccountTypeAndIsValid(
  4. String encryptedIfsc, String encryptedAccountNo, String accountType, Boolean isValid);

Service call -

  1. List&lt;SomeDetail&gt; someDetails = someDetailRepository.findByEncryptedIfscAndEncryptedAccountNoAndAccountTypeAndIsValid(
  2. ben.getEncryptedIfsc(), ben.getEncryptedAccountNo(), Enum.someAccountType.CREDIT_CARD.v, isValid);

Exception -

  1. org.springframework.dao.InvalidDataAccessApiUsageException: Parameter value [credit_card] did not match expected type [Enum$someAccountType (n/a)]; nested exception is java.lang.IllegalArgumentException: Parameter value [credit_card] did not match expected type [Enum$someAccountType (n/a)]

Why is it throwing this exception? I have defined @Enumerated(EnumType.STRING) so it should expect string type stored in db.

答案1

得分: 0

当使用JPA与Enum时,需要依赖于Enum对象,而不是它的属性。
例如,我会像这样更改您的存储库方法:

  1. @Repository
  2. public interface SomeDetailRepository extends JpaRepository<SomeDetail, Long> {
  3. List<SomeDetail> findByEncryptedIfscAndEncryptedAccountNoAndAccountTypeAndIsValid(
  4. String encryptedIfsc, String encryptedAccountNo, Enum.someAccountType accountType, Boolean isValid);

并直接使用枚举值:

  1. List<SomeDetail> someDetails = someDetailRepository.findByEncryptedIfscAndEncryptedAccountNoAndAccountTypeAndIsValid(
  2. ben.getEncryptedIfsc(), ben.getEncryptedAccountNo(), Enum.someAccountType.CREDIT_CARD, isValid);

顺便说一下,在Java中,始终使用大写字母为类、枚举等命名,例如将 someAccountType 改为 SomeAccountType

关于 @Enumerated 的含义:

@Enumerated 允许您指定Hibernate将如何在数据库中存储值。您有两个选项(来自javadoc):

  • EnumType.ORDINAL:将枚举类型属性或字段持久化为整数
  • EnumType.STRING:将枚举类型属性或字段持久化为字符串

但它不会改变您在存储库代码中的使用方式,它只会改变Hibernate如何存储它。

英文:

When using Enum with JPA, you need to rely on the Enum object, not on its attribute.
For instance, I'll change your repository method like this:

  1. @Repository
  2. public interface SomeDetailRepository extends JpaRepository&lt;SomeDetail, Long&gt; {
  3. List&lt;someDetail&gt; findByEncryptedIfscAndEncryptedAccountNoAndAccountTypeAndIsValid(
  4. String encryptedIfsc, String encryptedAccountNo, Enum.someAccountType accountType, Boolean isValid);

And use the enum val directly:

  1. List&lt;SomeDetail&gt; someDetails = someDetailRepository.findByEncryptedIfscAndEncryptedAccountNoAndAccountTypeAndIsValid(
  2. ben.getEncryptedIfsc(), ben.getEncryptedAccountNo(), Enum.someAccountType.CREDIT_CARD, isValid);

By the way, in Java, always name your class, enum ... with a capital letter someAccountType -> SomeAccountType

What means @Enumarated

@Enumerated lets you specify how Hibernate will store the value in DB. You have two options (from the javadoc):

  • EnumType.ORDINAL: Persist enumerated type property or field as an integer
  • EnumType.STRING: Persist enumerated type property or field as a string

But it doesn't change how you use it in your repository code, it is changing only how Hibernate will store it.

huangapple
  • 本文由 发表于 2020年7月28日 16:35:38
  • 转载请务必保留本文链接:https://go.coder-hub.com/63130114.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定