Hibernate 多对多关系正在创建一个我不知道的新实例';我不想

Hibernate 多对多关系正在创建一个我不知道的新实例';我不想,hibernate,spring-data-jpa,Hibernate,Spring Data Jpa,我有两个实体,订单和产品,两者之间的关系是多对多的,我已经设置了关系,但当我尝试使用现有产品集创建新订单时,它会使用新ID创建新产品,而不仅仅是将它们连接到订单产品。 最后,我提供了我的测试截图。 这是我的订单实体: @Entity @Table(name="Orders") public class Orders implements Serializable { @Id @Column(name="idorder") @GeneratedValue(

我有两个实体,订单和产品,两者之间的关系是多对多的,我已经设置了关系,但当我尝试使用现有产品集创建新订单时,它会使用新ID创建新产品,而不仅仅是将它们连接到订单产品。 最后,我提供了我的测试截图。 这是我的订单实体:

@Entity
@Table(name="Orders")
public class Orders implements Serializable {

@Id
@Column(name="idorder")
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator = "orders_sequence")
@SequenceGenerator(name = "orders_sequence")
private Long idOrder;


@Column(name="idclient")
private Long idClient;

@Column(name="idmanager")
private String idManager;


@Column(name="iddeliveryman")
private String idDeliveryMan;


@Column(name="dateorders")
@JsonFormat(pattern="mm-dd-yyyy")
private Date dateOrder;


@Column(name="totalprice")
private double totalPrice;

@ManyToMany(cascade = { CascadeType.ALL } , fetch=FetchType.LAZY)
@JoinTable(
    name = "orders_products", 
    joinColumns = { @JoinColumn(name = "idorder") }, 
    inverseJoinColumns = { @JoinColumn(name = "idproduct") }
)
private List<Products> products_orders ;

//getters and setters
@实体
@表(name=“Orders”)
公共类Orders实现可序列化{
@身份证
@列(name=“idorder”)
@GeneratedValue(策略=GenerationType.SEQUENCE,generator=“orders\u SEQUENCE”)
@SequenceGenerator(name=“orders\u sequence”)
私人长订单;
@列(name=“idclient”)
私人长idc客户端;
@列(name=“idmanager”)
私有字符串管理器;
@列(name=“iddeliveryman”)
私人字符串idDeliveryMan;
@列(name=“dateorders”)
@JsonFormat(pattern=“mm dd yyyy”)
私人日期订单;
@列(name=“totalprice”)
私人双总价;
@ManyToMany(cascade={CascadeType.ALL},fetch=FetchType.LAZY)
@可接合(
name=“订单\产品”,
joinColumns={@JoinColumn(name=“idorder”)},
inverseJoinColumns={@JoinColumn(name=“idproduct”)}
)
私人列表产品和订单;
//接球手和接球手
我的产品实体:

@Entity
@Table(name="Products")
public class Products implements Serializable{

@Id
@Column(name="idproduct")
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator = "products_sequence")
@SequenceGenerator(name = "products_sequence")
private Long idProduct;

@Column(name="labelproduct")
private String label;

@Column(name="priceproduct")
private int priceProduct;

@Column(name="descriptionproduct")
private String descriptionProduct;



@ManyToMany(mappedBy = "products" )
private List<Menu> menus;


@ManyToMany(mappedBy = "products_orders" )
private List<Orders> orders;

//getters and setters
@实体
@表(name=“产品”)
公共类产品实现可序列化{
@身份证
@列(name=“idproduct”)
@GeneratedValue(策略=GenerationType.SEQUENCE,生成器=“产品\序列”)
@SequenceGenerator(name=“产品\序列”)
私人长产品;
@列(name=“labelproduct”)
私有字符串标签;
@列(name=“priceproduct”)
私人产品;
@列(name=“descriptionproduct”)
私有字符串描述产品;
@许多(mappedBy=“产品”)
私人列表菜单;
@许多(mappedBy=“产品\订单”)
私人名单订单;
//接球手和接球手
我的订单管理员:

@RestController
public class OrdersController {

@Autowired
private OrdersRepository ordersRepository;

@Autowired
private ManagersRepository managersRepository;

@Autowired
private DeliveryManRepository deliverymanRepo;

@Autowired
private ClientsRepository clientsRepository;

@Autowired 
private ProductsRepository productsRepos;



@PostMapping("orders/create/{idManager}/{idDeliveryMan}/{idClient}")
public ResponseEntity<?> createOrder(@Valid @RequestBody Orders order ,@PathVariable String idManager 
        ,@PathVariable Long idClient, @PathVariable String idDeliveryMan){
    
    Managers manager= managersRepository.findByEmail(idManager);
    Clients client=clientsRepository.findByPhone(idClient);
    DeliveryMen deliveryMan = deliverymanRepo.findByEmail(idDeliveryMan);
    
    
    double price =0;
    for (Products p: order.getProducts_orders()) {
        price = price + p.getPriceProduct();
    }
    
    order.setIdClient(client.getPhone());
    order.setIdDeliveryMan(deliveryMan.getEmail());
    order.setIdManager(manager.getEmail());     
    order.setTotalPrice(price);     
    Orders newOrder = ordersRepository.save(order);
    
    return new ResponseEntity<Orders>(newOrder,HttpStatus.CREATED);
}
}
@RestController
公共类OrdersController{
@自动连线
私人订单储蓄订单储蓄;
@自动连线
私有管理器存储库管理器存储库;
@自动连线
私人送货员仓库送货员报告;
@自动连线
私人客户储蓄性客户储蓄性;
@自动连线
私人产品替代产品;
@PostMapping(“订单/create/{idManager}/{idDeliveryMan}/{idClient}”)
public ResponseEntity createOrder(@Valid@RequestBody Orders,@PathVariable String idManager
,@PathVariable长idClient,@PathVariable字符串idDeliveryMan){
Managers-manager=managersRepository.findByEmail(idManager);
Clients client=clientsRepository.findByPhone(idClient);
deliveryMan deliveryMan=deliverymanRepo.findByEmail(idDeliveryMan);
双倍价格=0;
对于(产品p:order.getProducts\u orders()){
价格=价格+p.getPriceProduct();
}
order.setIdClient(client.getPhone());
order.setIdDeliveryMan(deliveryMan.getEmail());
order.setIdManager(manager.getEmail());
订单。设置总价(价格);
Orders newOrder=ordersepository.save(订单);
返回新的响应属性(newOrder,HttpStatus.CREATED);
}
}

您的关系不正确,您创建了与
产品的订单
@manytomy
关系,这在理论上是正确的,但您需要与
订单和
订单产品的
@OneToMany
关系

记住,订单有它的行,它们不是真正的产品,但应该由不同的实体来表示

产品是一种主数据,您只需设置一次就可以向用户推荐您的菜单。您的订单行中应该有这方面的参考信息,但直接链接到
订单
会产生类似您的问题

产品应单独创建,不得在系统中下订单

因此,您必须在两者之间有一个实体,可以如下所示:

@Entity
@Table("order_products")
class OrderProduct {
   @Id
   Long id; //Keep the id as per your requirement or type in db
   
   @ManyToOne(fetch=LAZY)
   @JoinColumn(name = "order_id"
   private Order order;

   @ManyToOne(fetch=LAZY)
   @JoinColumn(name = "product_id"
   private Product product;
   
// getters and setter omitted
}

@Table(name = "orders")
class Order {
   
  @OneToMany(
     mappedBy = "order",
     cascade = {CascadeType.ALL}
     orphanRemoval = true
  )
  private Set<OrderProduct> orderProducts = new HashSet<>();
  
  // Other fields as you have already

  // Also add a method to add OrderProduct object to maintain this bidirectional mapping

  public void addOrderProduct(OrderProduct product) {
      orderProducts.add(product);
      product.setOrder(this);
  }
}
@实体
@表(“订购产品”)
类订单产品{
@身份证
Long id;//根据您的要求或在db中键入id
@manytone(fetch=LAZY)
@JoinColumn(name=“订单号”
私人秩序;
@manytone(fetch=LAZY)
@JoinColumn(name=“product\u id”
私人产品;
//省略了getter和setter
}
@表(name=“orders”)
阶级秩序{
@独身癖(
mappedBy=“订单”,
cascade={CascadeType.ALL}
孤立删除=真
)
private Set orderProducts=new HashSet();
//其他字段,如您已经完成的
//还要添加一个方法来添加OrderProduct对象以维护此双向映射
公共无效addOrderProduct(OrderProduct产品){
orderProducts.add(产品);
产品订单(本);
}
}

我认为这是您所需要的,请阅读
createOrder
中的中的更多详细信息。您收到一个类型为
Orders
的传入对象,该对象源自您所做的REST请求。如果您希望此新订单引用现有产品而不是新产品,您当然必须从数据库加载现有产品ase,而不是让Hibernate将(非托管)
订单
对象的持久化级联到其(非托管)
产品
对象列表中

近似

List<Products> products = new ArrayList<>();

for (Products p: order.getProducts_orders()) {
    products.add(productsRepos.findById(p.getId()));
    price = price + p.getPriceProduct();
}

order.setProducts(products);
List products=new ArrayList();
对于(产品p:order.getProducts\u orders()){
products.add(productsRepos.findById(p.getId());
价格=价格+p.getPriceProduct();
}
订单.产品(产品);

编辑:如果没有将
@manytomy
关系设置为
cascade={CascadeType.ALL},这一点会立即变得明显
默认情况下,因为如果您要保存一个
订单
引用非托管
产品的列表
,您将从Hibernate获得一个异常。

它正在工作。谢谢!它正在工作。但它只在提交大量产品时才起作用!我已经有了实体,Spring正在自己处理它,我必须修复我的问题与