【问题标题】:How could I identify whether to insert or update the record with Spring jpa我如何确定是否使用 Spring jpa 插入或更新记录
【发布时间】:2017-10-19 13:05:06
【问题描述】:

我在我的 inventory 春季项目中遇到了一种情况,我想在包含以下字段的 Item 表中插入项目。

  1. 姓名
  2. 颜色
  3. 说明
  4. 数量
  5. buying_price
  6. 销售价格。

现在我在请求中发送一个 json

{
    "name":"iphone 5s cover",
    "buyingPrice": 300,
    "color":"white",
    "description":"Hard cover for iphone",
    "sellingPrice":400,
    "quantity":30
 }

这个东西会在我添加的表中插入新记录 Id auto-increment。 现在,当我要添加具有不同 数量 的相同项目时,它应该更新数量而不是添加新记录。

我现在可以做的是检查请求的每一个内容,如果它存在于它发送 Id 的表中,或者更新该特定 ID 处的记录。

或者在 Spring Boot 中还有其他更好的方法可以识别自己来更新此记录。 或者我能做些什么来处理这种情况。

尝试使用@ClassId 注释创建复合键,但出现异常

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.MappingException: property-ref [_com_was_inventory_model_Sale_items] not found on entity [com.was.inventory.model.Sale]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1628) ~[spring-beans-4.3.11.RELEASE.jar:4.3.11.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555) ~[spring-beans-4.3.11.RELEASE.jar:4.3.11.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483) ~[spring-beans-4.3.11.RELEASE.jar:4.3.11.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) ~[spring-beans-4.3.11.RELEASE.jar:4.3.11.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) ~[spring-beans-4.3.11.RELEASE.jar:4.3.11.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) ~[spring-beans-4.3.11.RELEASE.jar:4.3.11.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) ~[spring-beans-4.3.11.RELEASE.jar:4.3.11.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1078) ~[spring-context-4.3.11.RELEASE.jar:4.3.11.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) ~[spring-context-4.3.11.RELEASE.jar:4.3.11.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) ~[spring-context-4.3.11.RELEASE.jar:4.3.11.RELEASE]
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122) ~[spring-boot-1.5.7.RELEASE.jar:1.5.7.RELEASE]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) [spring-boot-1.5.7.RELEASE.jar:1.5.7.RELEASE]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) [spring-boot-1.5.7.RELEASE.jar:1.5.7.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) [spring-boot-1.5.7.RELEASE.jar:1.5.7.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1118) [spring-boot-1.5.7.RELEASE.jar:1.5.7.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1107) [spring-boot-1.5.7.RELEASE.jar:1.5.7.RELEASE]
    at com.was.inventory.InventoryApplication.main(InventoryApplication.java:10) [classes/:na]
Caused by: org.hibernate.MappingException: property-ref [_com_was_inventory_model_Sale_items] not found on entity [com.was.inventory.model.Sale]
    at org.hibernate.mapping.PersistentClass.getReferencedProperty(PersistentClass.java:413) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.boot.internal.InFlightMetadataCollectorImpl$DelayedPropertyReferenceHandlerAnnotationImpl.process(InFlightMetadataCollectorImpl.java:1229) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processPropertyReferences(InFlightMetadataCollectorImpl.java:1938) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processSecondPasses(InFlightMetadataCollectorImpl.java:1625) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:278) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:847) ~[hibernate-entitymanager-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:874) ~[hibernate-entitymanager-5.0.12.Final.jar:5.0.12.Final]
    at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60) ~[spring-orm-4.3.11.RELEASE.jar:4.3.11.RELEASE]
    at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:353) ~[spring-orm-4.3.11.RELEASE.jar:4.3.11.RELEASE]
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:370) ~[spring-orm-4.3.11.RELEASE.jar:4.3.11.RELEASE]
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:359) ~[spring-orm-4.3.11.RELEASE.jar:4.3.11.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1687) ~[spring-beans-4.3.11.RELEASE.jar:4.3.11.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1624) ~[spring-beans-4.3.11.RELEASE.jar:4.3.11.RELEASE]
    ... 16 common frames omitted
Caused by: org.hibernate.MappingException: property [_com_was_inventory_model_Sale_items] not found on entity [com.was.inventory.model.Sale]
    at org.hibernate.mapping.PersistentClass.getRecursiveProperty(PersistentClass.java:469) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.mapping.PersistentClass.getReferencedProperty(PersistentClass.java:409) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    ... 28 common frames omitted 

这里是实体

@Entity
@Table(name = "Item")
@IdClass(ItemsKey.class)
public class Item implements Serializable {


   private Integer id;

    private String name;

    private Category category;

    private String description;

    private String color;

    private Long sellingPrice;

    private Long buyingPrice;

    private Integer quantity;

    private String pictureLink;

    private Set<Sale> sales;

    private Set<Orders> orders;

    private Set<Purchase> purchases;


    public Item() {
    }

    public Item(String name, Category category, String description, String color, Long sellingPrice, Long buyingPrice, Integer quantity) {
        this.name = name;
        this.category = category;
        this.description = description;
        this.color = color;
        this.sellingPrice = sellingPrice;
        this.buyingPrice = buyingPrice;
        this.quantity = quantity;
    }



    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    @Id
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @ManyToOne
    @JoinColumn(name = "CategoryId")
    public Category getCategory() {
        return category;
    }

    public void setCategory(Category category) {
        this.category = category;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    @Id
    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public Long getSellingPrice() {
        return sellingPrice;
    }

    public void setSellingPrice(Long sellingPrice) {
        this.sellingPrice = sellingPrice;
    }

    public Long getBuyingPrice() {
        return buyingPrice;
    }

    public void setBuyingPrice(Long buyingPrice) {
        this.buyingPrice = buyingPrice;
    }

    public Integer getQuantity() {
        return quantity;
    }

    public void setQuantity(Integer quantity) {
        this.quantity = quantity;
    }

    public String getPictureLink() {
        return pictureLink;
    }

    public void setPictureLink(String pictureLink) {
        this.pictureLink = pictureLink;
    }

    @ManyToMany(mappedBy = "items")
    public Set<Sale> getSales() {
        return sales;
    }

    public void setSales(Set<Sale> sales) {
        this.sales = sales;
    }

    @ManyToMany(cascade = CascadeType.ALL)
    @JoinTable(name = "ItemOrders", joinColumns = @JoinColumn(name = "Item_id",
            referencedColumnName = "id"),
            inverseJoinColumns = @JoinColumn(name = "Orders_id", referencedColumnName = "id"))
    public Set<Orders> getOrders() {
        return orders;
    }

    public void setOrders(Set<Orders> orders) {
        this.orders = orders;
    }

    @ManyToMany(mappedBy = "items")
    public Set<Purchase> getPurchases() {
        return purchases;
    }

    public void setPurchases(Set<Purchase> purchases) {
        this.purchases = purchases;
    }


    @Override
    public int hashCode() {
        return super.hashCode();
    }

    @Override
    public boolean equals(Object obj) {
        return super.equals(obj);
    }

}

这是 Id 类。

public class ItemsKey implements Serializable {

    private String name;

    private String color;

    public ItemsKey() {
    }

    public ItemsKey(String name, String color) {
        this.name = name;
        this.color = color;
    }

    /**
     * getters and setters
     **/

    @Column(name = "name", nullable = false)
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Column(name = "color", nullable = false)
    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }
}

此实体与其他一些实体存在关系,它在不添加复合主键的情况下工作正常。

我错了。 我想将 id 作为主要元素,将 namecolor 作为复合元素。 这对实现这个目标有意义吗。 感谢:)

【问题讨论】:

  • 我相信 JPA 会在 save 方法上自动执行此操作。它表现为创建或更新。重要的部分是ID。如果要更新,还需要使用对象模型将正确的 ID 传递给 save 方法。
  • 这是它自动增量获取 id 我必须根据颜色和名称获取对象的问题。有没有更好的办法。
  • 听起来您希望颜色 + 名称成为唯一键?
  • 也有同样的想法来制作它们的复合键。创建一个可嵌入的 Id
  • 是的,您需要将其作为您的密钥。如果颜色和名称已经定义了一个唯一的对象,你就不需要自动生成 ID

标签: java mysql spring-boot spring-data-jpa


【解决方案1】:

您需要先通过其 id 获取 Item,如下所示

Item item = itemRepository.findById(YOUR_ID);

那么你需要像这样更新它的状态

item.setQuantity(YOUR_QUANTITY);

然后最后像这样更新数据库中的Item

item = itemRepository.save(item); //Now the item object contains the updated quantity.

【讨论】:

  • 我没有id,因为不知道之前有没有插入过。
  • 必须有一些唯一标识您的Item实体的键!!
  • 我已经定义了组合键 colorname 现在使用 id class 注释,但它抛出了我和 mapping 的异常,如 property A_item not found in entity A
  • 也发布您的实体。看起来虫子就在那里。
  • 异常日志显示您的_com_was_inventory_model_Sale_items 实体类中没有属性Sales
猜你喜欢
  • 1970-01-01
  • 2021-09-13
  • 1970-01-01
  • 2011-04-09
  • 1970-01-01
  • 2012-06-15
  • 2014-08-14
  • 1970-01-01
  • 2010-09-24
相关资源
最近更新 更多