【问题标题】:How to query using an Enum parameter mapped as ORDINAL using JPA and Hibernate如何使用 JPA 和 Hibernate 映射为 ORDINAL 的枚举参数进行查询
【发布时间】:2014-11-24 05:44:09
【问题描述】:

我需要按枚举类型从数据库中获取数据。 我有以下枚举:

public enum ShopType {
    VANS("VANS"), ATTICUS("ATTICUS"), FAMOUS("FAMOUS")

    ShopType(String label) {
        this.label = label;
    }

    private String label;

    public String getLabel() {
        return label;
    }

    public void setLabel(String label) {
        this.label = label;
    }
}

在我的 DAO 类中,我有一个方法可以在 jsp 页面上按选定类型返回对象列表。在jsp 页面上,我发送选定的值,例如String,对吗?

我的方法看起来如何

@Transactional
public List<Shop> findByType(String type) {
    return sessionFactory.getCurrentSession().createQuery("from Shop where type=" + .....  .list();
}

我不知道如何创建正确的查询。我像 tinyint 一样存储在数据库中的枚举。

这是一个模型。

@Column(name = "type")
@Enumerated(EnumType.ORDINAL)
private ShopType type;

【问题讨论】:

    标签: java hibernate jpa enums hibernate-mapping


    【解决方案1】:

    当您将枚举设置为序数时,在查询中您应该使用序数。示例;

    @Transactional
    public List<Shop> findByType(String type) {
        return sessionFactory.getCurrentSession().createQuery("from Shop where type=" + ShopType.valueOf(type).ordinal()).list();
    }
    

    如果您更改@Enumerated(EnumType.STRING),那么您的查询将如下所示;

    @Transactional
    public List<Shop> findByType(String type) {
        return sessionFactory.getCurrentSession().createQuery("from Shop where type=" + ShopType.valueOf(type).name()).list();
    }
    

    ShopType.valueOf(type),这仅在字符串类型与枚举名称相同时才有效。 此外,如果您的标签与枚举名称相同,那么您不需要标签。 ShopType.VANS.name()is equals"VANS"name() 方法是最终的,你可以确定不能被覆盖。

    【讨论】:

    • 结果应该取决于接收 findByType 方法的类型参数,你只是硬编码了 VANS 类型
    【解决方案2】:

    只需将 String 转换为 Enum 并使用命名查询参数

    @Transactional
    public List<Shop> findByType(String type) {
        ShopType enumType = shopTypeFromString(type);
        return sessionFactory.getCurrentSession().createQuery("from Shop where type=:p_type")
            .setParameter("p_type", enumType).list();
    }
    
    private ShopType shopTypeFromString(String type) {
        // You can implement this convertion in your own way
        return ShopType.valueOf(type);
    }
    

    【讨论】:

    • 我猜这不太好=)
    【解决方案3】:

    您的查询中的问题是您连接了绑定参数值,这除了导致您的问题外,还可能将您的应用程序暴露给SQL injection attacks

    如果您使用绑定参数值编写查询:

    Post post = entityManager.createQuery(
        "select p " +
        "from Post p " +
        "where p.status = :status", Post.class)
    .setParameter("status", PostStatus.PENDING)
    .getSingleResult();
    
    assertEquals("High-Performance Java Persistence", post.getTitle());
    

    Hibernate 将在 SQL 查询中正确使用 ORDINAL 值:

    Query:["
        select 
            p.id as id1_0_,
            p.status as status2_0_, 
            p.title as title3_0_ 
        from 
            post p 
        where 
            p.status=?
    "], 
    Params:[
        0
    ]
    

    有关工作示例,请查看我的 high-performance-java-persistence GitHub repository 中的 EnumOrdinalTest

    【讨论】:

      猜你喜欢
      • 2023-03-20
      • 2018-04-11
      • 2016-12-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-21
      • 2012-03-18
      相关资源
      最近更新 更多