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

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

InvalidDataAccessApiUsageException trying to find using JPA query with Enum value

问题

Enum def -

// 枚举定义
public enum someAccountType {
    ACCOUNT_NUMBER("account_number"),
    CREDIT_CARD("credit_card");

    public final String v;

    someAccountType(String value) {
        this.v = value;
    }
}
@AllArgsConstructor
@Getter
@Entity
@Builder
@Setter
public class SomeDetail {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    @Enumerated(EnumType.STRING)
    @Column(name="accountType")
    private Enum.someAccountType accountType;
    ..
}

Repository -

// 存储库定义
@Repository
public interface SomeDetailRepository extends JpaRepository<SomeDetail, Long> {

    List<SomeDetail> findByEncryptedIfscAndEncryptedAccountNoAndAccountTypeAndIsValid(
            String encryptedIfsc, String encryptedAccountNo, String accountType, Boolean isValid);
}

Service call -

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

Exception -

// 异常信息
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.
英文:

Enum def -

public enum someAccountType {
	ACCOUNT_NUMBER(&quot;account_number&quot;),
	CREDIT_CARD(&quot;credit_card&quot;);

	public final String v;

	someAccountType(String value) {
		this.v = value;
	}
}

@AllArgsConstructor
@Getter
@Entity
@Builder
@Setter
public class SomeDetail {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    @Enumerated(EnumType.STRING)
	@Column(name=&quot;accountType&quot;)
	private Enum.someAccountType accountType;
    ..
}

Repository -

@Repository
public interface SomeDetailRepository extends JpaRepository&lt;SomeDetail, Long&gt; {

    List&lt;someDetail&gt; findByEncryptedIfscAndEncryptedAccountNoAndAccountTypeAndIsValid(
			String encryptedIfsc, String encryptedAccountNo, String accountType, Boolean isValid);

Service call -

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

Exception -

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对象,而不是它的属性。
例如,我会像这样更改您的存储库方法:

@Repository
public interface SomeDetailRepository extends JpaRepository<SomeDetail, Long> {

    List<SomeDetail> findByEncryptedIfscAndEncryptedAccountNoAndAccountTypeAndIsValid(
            String encryptedIfsc, String encryptedAccountNo, Enum.someAccountType accountType, Boolean isValid);

并直接使用枚举值:

List<SomeDetail> someDetails = someDetailRepository.findByEncryptedIfscAndEncryptedAccountNoAndAccountTypeAndIsValid(
                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:

@Repository
public interface SomeDetailRepository extends JpaRepository&lt;SomeDetail, Long&gt; {

    List&lt;someDetail&gt; findByEncryptedIfscAndEncryptedAccountNoAndAccountTypeAndIsValid(
            String encryptedIfsc, String encryptedAccountNo, Enum.someAccountType accountType, Boolean isValid);

And use the enum val directly:

List&lt;SomeDetail&gt; someDetails = someDetailRepository.findByEncryptedIfscAndEncryptedAccountNoAndAccountTypeAndIsValid(
                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:

确定