在我的情况下,如何使用枚举执行弹簧数据JPA查询?

发布于 2025-01-21 23:06:34 字数 3871 浏览 0 评论 0原文

首先,这很长,但我想提供所有可能的信息。

我正在研究一个更大的查询,这将基于此基础,因此我没有采用更轻松或其他方法。此外,我无法真正改变我们实现DB和域对象的方式。

我的问题是我无法获得弹簧数据JPA查询来与枚举一起使用。该领域也是DB中的枚举。这是缩写的代码。

2个表的SQL:

CREATE TABLE my_order (
    id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
    creation_date TIMESTAMP NOT NULL,
);

CREATE TYPE ORDER_STATE as ENUM ('new', 'open', 'closed');
CREATE CAST (CHARACTER VARYING AS ORDER_STATE) WITH INOUT AS IMPLICIT;

CREATE TABLE my_order_history (
    id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
    order_date TIMESTAMP NOT NULL,
    order_state ORDER_STATE NOT NULL,
    order_id INT REFERENCES my_order
);

这是相应的域对象:

@Entity
@Table(name = "my_order")
public class Order {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;

    @Column(name = "creation_date")
    private Date creationDate;

    @OneToMany(mappedBy = "order", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private List<OrderHistory> orderHistories;
}

@Entity
@Table(name = "my_order_history")
public class OrderHistory {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;

    @Column(name = "order_date ")
    private Date orderDate;

    @Column(name = "order_state")
    @Convert(converter = OrderStateConverter.class)
    private OrderState orderState

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "order_id", nullable = false)
    private Order order;
}

这是转换器:

@Component
@Converter(autoApply = true)
public class OrderStateConverter implement AttributeConverter<OrderState, String> {
   @Override
   public String convertToDatabaseColumn(OrderState attribute) {
       return attribute.getValue;
   }

   @Override
   public OrderState convertToEntityAttribute(String dbData) {
      return OrderState.fromValue(dbData);
   }
}

这是枚举:

public enum OrderState {
   NEW("new"), OPEN("open"), CLOSED("closed");

   @Getter
   private String value;

   private OrderState(String value) {
      this.value = value;
   }

   public static OrderState fromValue(String value) {
      for (OrderState orderState : values()) {
         if (orderState.getValue().equals(value)) {
             return orderState;
         }
      }
      return null;
   }
}

这是我的弹簧存储库。我将尝试的三种方法放在下面,然后在下面给您每个人都会收到的例外:

@Repository
public interface OrderRepository extends PagingAndSortingRepository<Order, Long> {
   @Query("SELECT o FROM Order o JOIN o.orderHistories oh WHERE oh.orderState = :orderState")
   List<Order> getOrdersByOrderState1(@Param("orderState") OrderState orderState);

   @Query("SELECT o FROM Order o JOIN o.orderHistories oh WHERE oh.orderState = :orderState")
   List<Order> getOrdersByOrderState2(@Param("orderState") String orderState);

   @Query("SELECT o FROM Order o JOIN o.orderHistories oh WHERE oh.orderState = :#(#orderState?.getValue())")
   List<Order> getOrdersByOrderState3(@Param("orderState") OrderState orderState);
}

对于#1,当我提供一个阶层枚举时,我会得到以下例外:

Caused by: org.postgres.util.PSQLException: ERROR: operator does not exist: order_state = character varying
   Hint: No operator matches the given name and argument types. You might need explicit type casts.

对于#2,当我提供Orderstate.getValue()时,这是一个字符串,我会得到以下例外:

java.jang.IllegalArgumentException: Parameter value [new] did not match expected type [com.testing.enums.OrderState (n/a)]

对于#3,当我提供一个阶梯枚举时,我会得到以下例外(与#2相同):

java.jang.IllegalArgumentException: Parameter value [new] did not match expected type [com.testing.enums.OrderState (n/a)]

基本上,我尝试发送枚举并获得错误,但我也得到了一个当我尝试发送字符串时,错误。有什么我能做的吗?到底发生了什么?

First sorry this is long but I wanted to provide all information possible.

I am working on a much larger query that will build on this hence the reason I am not taking an easier or other approaches. In addition I can't really change the way we implemented the DB and Domain Objects.

My problem is I can't get a Spring Data JPA Query to work with an Enum. The field is an Enum in the DB as well. Here is the abbreviated code.

The SQL for the 2 tables:

CREATE TABLE my_order (
    id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
    creation_date TIMESTAMP NOT NULL,
);

CREATE TYPE ORDER_STATE as ENUM ('new', 'open', 'closed');
CREATE CAST (CHARACTER VARYING AS ORDER_STATE) WITH INOUT AS IMPLICIT;

CREATE TABLE my_order_history (
    id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
    order_date TIMESTAMP NOT NULL,
    order_state ORDER_STATE NOT NULL,
    order_id INT REFERENCES my_order
);

Here is the corresponding Domain Objects:

@Entity
@Table(name = "my_order")
public class Order {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;

    @Column(name = "creation_date")
    private Date creationDate;

    @OneToMany(mappedBy = "order", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private List<OrderHistory> orderHistories;
}

@Entity
@Table(name = "my_order_history")
public class OrderHistory {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;

    @Column(name = "order_date ")
    private Date orderDate;

    @Column(name = "order_state")
    @Convert(converter = OrderStateConverter.class)
    private OrderState orderState

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "order_id", nullable = false)
    private Order order;
}

Here is the converter:

@Component
@Converter(autoApply = true)
public class OrderStateConverter implement AttributeConverter<OrderState, String> {
   @Override
   public String convertToDatabaseColumn(OrderState attribute) {
       return attribute.getValue;
   }

   @Override
   public OrderState convertToEntityAttribute(String dbData) {
      return OrderState.fromValue(dbData);
   }
}

Here is the Enum:

public enum OrderState {
   NEW("new"), OPEN("open"), CLOSED("closed");

   @Getter
   private String value;

   private OrderState(String value) {
      this.value = value;
   }

   public static OrderState fromValue(String value) {
      for (OrderState orderState : values()) {
         if (orderState.getValue().equals(value)) {
             return orderState;
         }
      }
      return null;
   }
}

Here is my Spring Repo. I am putting the 3 ways I have tried and then below I will give you the exceptions I am receiving with each:

@Repository
public interface OrderRepository extends PagingAndSortingRepository<Order, Long> {
   @Query("SELECT o FROM Order o JOIN o.orderHistories oh WHERE oh.orderState = :orderState")
   List<Order> getOrdersByOrderState1(@Param("orderState") OrderState orderState);

   @Query("SELECT o FROM Order o JOIN o.orderHistories oh WHERE oh.orderState = :orderState")
   List<Order> getOrdersByOrderState2(@Param("orderState") String orderState);

   @Query("SELECT o FROM Order o JOIN o.orderHistories oh WHERE oh.orderState = :#(#orderState?.getValue())")
   List<Order> getOrdersByOrderState3(@Param("orderState") OrderState orderState);
}

For #1 when I provide an OrderState enum I get the following exception:

Caused by: org.postgres.util.PSQLException: ERROR: operator does not exist: order_state = character varying
   Hint: No operator matches the given name and argument types. You might need explicit type casts.

For #2 when I provide OrderState.getValue(), which is a String, I get the following exception:

java.jang.IllegalArgumentException: Parameter value [new] did not match expected type [com.testing.enums.OrderState (n/a)]

For #3 when I provide an OrderState enum I get the following exception (same as #2):

java.jang.IllegalArgumentException: Parameter value [new] did not match expected type [com.testing.enums.OrderState (n/a)]

Basically I try to send in the enum and get an error but I also get an error when I try to send in a String. Is there anything I can do? What is exactly happening?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文