我正在尝试删除一个具有复合主键的实体,该实体的组成部分是数据库中的其他两个实体(多对多关系,代码如下)。这些实体的主键是 Long 类型的 id,我尝试在没有本机请求的情况下通过这些 id 精确删除(代码再次在下面),但作为响应,我得到以下异常:
jakarta.persistence.TransactionRequiredException: No EntityManager with actual transaction available for current thread - cannot reliably process 'remove' call.
据我了解,没有合适的方法来进行此类删除,尽管对我来说,该方法的名称构造正确。
在这方面,我有一个问题 - 在我的情况下是否可以通过将请求的构造委托给 Spring JPA 来进行删除?
存储库:
@Repository
public interface ServiceOrderRepository extends JpaRepository<ServiceOrder, ServiceOrderPk> {
List<ServiceOrder> findAllByPkOrderId(Long id);
void deleteByPkOrderIdAndPkServiceId(Long orderId, Long serviceId);
}
附注
findAllByPkOrderId
正在工作。
订单实体类:
// annotations skipped
public class Order {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@EqualsAndHashCode.Include
private Long id;
@ManyToOne(
targetEntity = Client.class,
cascade = CascadeType.MERGE,
fetch = FetchType.EAGER
)
@JoinColumn(name = "client_id", referencedColumnName = "id")
private Client client;
@Column(name = "registration_date")
private LocalDateTime registrationDate;
@Column(name = "appointment_date")
private LocalDateTime appointmentDate;
@Column(name = "execution_date")
private LocalDateTime executionDate;
}
服务实体类:
// annotations skipped also
public class Service {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@EqualsAndHashCode.Include
private Long id;
@Column(name = "name")
private String name;
@Column(name = "description")
private String description;
@Column(name = "price")
private BigDecimal price;
}
服务订单主键:
// you know what I want to write
public class ServiceOrderPk implements Serializable {
@ManyToOne(
targetEntity = Order.class,
cascade = CascadeType.MERGE,
fetch = FetchType.LAZY
)
@JoinColumn(name = "order_id")
private Order order;
@ManyToOne(
targetEntity = Service.class,
cascade = CascadeType.MERGE,
fetch = FetchType.LAZY
)
@JoinColumn(name = "service_id")
private Service service;
}
服务订单实体:
// ...
public class ServiceOrder {
@EmbeddedId
@EqualsAndHashCode.Include
private ServiceOrderPk pk;
@Column(name = "price")
private BigDecimal price;
@Column(name = "percent_discount")
private Long percentDiscount;
}
另外:在集合上写
fetch = FetchType.LAZY
有意义吗?
jakarta.persistence.TransactionRequiredException 通常在我们尝试执行无需事务的情况下修改数据库的数据库操作时发生。
检查您在哪里调用deleteByPkOrderIdAndPkServiceId,您应该打开一个活动交易。
请注意,即使您没有在 JPA 中声明事务,findAllByPkOrderId 也可能会起作用,因为只读事务很多时候是由 JDBC 驱动程序自动创建的,具体取决于驱动程序。但依赖于此仍然是一个不好的做法,如果您还没有它,最好也在那里显式声明只读事务。