如何使用JPA和Hibernate查询使用ORDINAL映射的Enum参数

5

我需要通过枚举类型从数据库中获取数据。 以下是我的枚举:

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页面上,我发送选定的值,例如字符串,这样做正确吗?

以下是我的方法:

@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;
3个回答

8

如果你将枚举设置为序数,那么在查询中应该使用序数。例如:

@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()等于"VANS",并且name()方法是final的,因此您可以确信它不会被覆盖。


根据 findByType 方法接收的 type 参数返回结果,你只是硬编码了 VANS 类型。 - user3127896

6

你查询中的问题在于你将绑定参数值串联起来,除了引起问题外,还可能使你的应用程序遭受SQL注入攻击

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

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存储库中的EnumOrdinalTest


4
只需将字符串转换为枚举类型,然后使用命名查询参数即可。
@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);
}

我猜想这可能不太好=) - user3127896

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接