【问题标题】:Exception when save in a JPA definition with Spring Boot + Spring data JPA使用 Spring Boot + Spring data JPA 保存在 JPA 定义中时出现异常
【发布时间】:2015-06-13 04:43:15
【问题描述】:

我在使用 Spring Boot + Spring Data JPA 定义 JPA 时遇到问题,我已经定义了下一个实体:

CommerceCnae.java

@Entity
public class CommerceCnae implements Serializable {

    private static final long serialVersionUID = -5071526484444404982L;

    @Id
    private String name;

    @OneToMany( mappedBy = "commerce", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<AddressCnae> addresses;

    @OneToMany( mappedBy = "commerceCategory", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<CategoryCnae> categories;

    /**
     * @return the name
     */
    public String getName() {
        return name;
    }

    /**
     * @param name
     *            the name to set
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * @return the addresses
     */
    public List<AddressCnae> getAddresses() {
        return addresses;
    }

    /**
     * @param addresses
     *            the addresses to set
     */
    public void setAddresses(List<AddressCnae> addresses) {
        this.addresses = addresses;
    }

    /**
     * @return the categories
     */
    public List<CategoryCnae> getCategories() {
        return categories;
    }

    /**
     * @param categories
     *            the categories to set
     */
    public void setCategories(List<CategoryCnae> categories) {
        this.categories = categories;
    }

}

CategoryCnae.java

@Entity
public class CategoryCnae implements Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = 3889422753757007724L;
    @Id
    private String id;
    private String description;

    @ManyToOne
    @JoinColumn(name = "name", nullable = false)
    private CommerceCnae commerceCategory;

    /**
     * @return the id
     */
    public String getId() {
        return id;
    }

    /**
     * @param id
     *            the id to set
     */
    public void setId(String id) {
        this.id = id;
    }

    /**
     * @return the description
     */
    public String getDescription() {
        return description;
    }

    /**
     * @param description
     *            the description to set
     */
    public void setDescription(String description) {
        this.description = description;
    }

    /**
     * @return the commerceCategory
     */
    public CommerceCnae getCommerceCategory() {
        return commerceCategory;
    }

    /**
     * @param commerceCategory
     *            the commerceCategory to set
     */
    public void setCommerceCategory(CommerceCnae commerceCategory) {
        this.commerceCategory = commerceCategory;
    }

}

AddressCnae.java

@Entity
public class AddressCnae implements Serializable {
    /**
     * 
     */
    private static final long serialVersionUID = 7387779987115612860L;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long addressCnaeId = 0;

    private String city;
    private String address;

    @ManyToOne
    @JoinColumn(name = "name", nullable = false)
    private CommerceCnae commerce;

    /**
     * @return the city
     */
    public String getCity() {
        return city;
    }

    /**
     * @param city
     *            the city to set
     */
    public void setCity(String city) {
        this.city = city;
    }

    /**
     * @return the address
     */
    public String getAddress() {
        return address;
    }

    /**
     * @param address
     *            the address to set
     */
    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public boolean equals(Object obj) {
        if ((obj instanceof AddressCnae)) {
            AddressCnae addressCnaeObj = (AddressCnae) obj;
            return (addressCnaeObj.getAddress().equals(this.getAddress()) && addressCnaeObj.getCity().equals(this.city));
        } else {
            return false;

        }
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + this.address.hashCode() + this.city.hashCode();
        return result;
    }

    /**
     * @return the commerce
     */
    public CommerceCnae getCommerce() {
        return commerce;
    }

    /**
     * @param commerce
     *            the commerce to set
     */
    public void setCommerce(CommerceCnae commerce) {
        this.commerce = commerce;
    }

    /**
     * @return the addressCnaeId
     */
    public long getAddressCnaeId() {
        return addressCnaeId;
    }

    /**
     * @param addressCnaeId
     *            the addressCnaeId to set
     */
    public void setAddressCnaeId(long addressCnaeId) {
        this.addressCnaeId = addressCnaeId;
    }

}

这是我的存储库:

@Repository
public interface CommerceRepository extends JpaRepository<CommerceCnae, String> {

}

但是当保存时我有下一个异常:

2015-04-08 11:22:31.320 DEBUG 18145 --- [nio-8080-exec-1] o.h.engine.jdbc.spi.SqlExceptionHelper   : could not execute statement [n/a]

java.sql.SQLException: Field 'commerce' doesn't have a default value
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:996)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3887)

是双向关系,我的配置是下一个:

#DATASOURCE CONFIGURATION

spring.datasource.url=jdbc:mysql://XXXXX/somthing
spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.username=XXXXX
spring.datasource.password=XXXXX
spring.datasource.continueOnError=false
spring.datasource.max-active=5

#JPA CONFIGURATION
spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect
spring.jpa.generate-ddl=true
spring.jpa.hibernate.hbm2ddl.auto=create-drop

怎么了?

感谢您的帮助!

编辑:

要保存的数据:

{  
   "@type":"es.domain.jpa.commerce.CommerceCnae",
   "name":"LAICOS S A",
   "addresses":{  
      "@type":"java.util.ArrayList",
      "@items":[  
         {  
            "@type":"es.domain.jpa.commerce.AddressCnae",
            "addressCnaeId":0,
            "city":"31200 ESTELLA - ",
            "address":"CL WITHOUTNUMBER 00033",
            "commerce":null
         }
      ]
   },
   "categories":{  
      "@type":"java.util.ArrayList",
      "@items":[  
         {  
            "@type":"es.domain.jpa.commerce.CategoryCnae",
            "id":"6441",
            "description":"OTHER DESCRIPTION.",
            "commerceCategory":null
         }
      ]
   }
}

我输入了 nullable = true ,但不起作用。同样的错误。

用求解编辑:

问题在于初始化,当你把@ManyToOne 或@OneToMany 关系和选项spring.jpa.hibernate.hbm2ddl.auto=create-drop 时发生了一些奇怪的事情。我删除了数据库并使用 spring.jpa.hibernate.hbm2ddl.auto=update 进行了初始化。解决了!!谢谢你的帮助!!

【问题讨论】:

  • 不确定,但这是 bcoz 您在 SQL 脚本中指定了 not null 和/或 default value 约束,而不是在 POJO 中。 尝试通过 Hibernate 自动重新生成表 &然后检查是否相同。然后比较两个 SQL 脚本 & 你得到了真正的原因。
  • 尝试初始化列表,例如:private List&lt;AddressCnae&gt; addresses = new ArrayList&lt;&gt;();
  • 你在commerce 上有nullable = false,你可能没有设置任何值...
  • 初始化列表不起作用,添加了保存对象在JSON中的表示。
  • 我输入了nullable = true ,但不起作用。同样的错误。谢谢!

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


【解决方案1】:

查看您的示例数据和 cmets,它们几乎没有问题。

您的 JSON 数据代表 CommerceCae 树:

  • 有一个 id 为 0 的地址,并且没有对实际 CommerceCae 的反向引用(commerce == null)
  • 有一类 id 6441 并且没有反向引用实际的 CommerceCae

现在在 JPA 配置中,您设置多对一关系处理(映射)地址或类别实体。所以必须在持久化之前设置商业价值。输入数据没有它们,所以你得到了你的 SQL 异常,因为连接列有 null 值,这是不允许的(顺便说一句,你应该再次带上 nullable=false 并重新生成表,乞求你刚刚处理了对象就可以了错误的)。

因此,在您读取 JSON 数据后,您必须修复关系:

CommerceCnae c = ....
for (AddressCnae a : c.getAddresses()) a.setCommerce(c);
for (CategoryCnae cat : c.getCategories()) cat.setCommerceCategory(c);
....
EM.persist(c);

这会解决你的java.sql.SQLException: Field 'commerce' doesn't have a default value

现在,在您的 CommerceCnae 中没有 ID 生成策略,因此在持久化之前您必须手动分配 ID。由于您的 JSON 数据似乎没有 ID 字段,我想这是一个简单的遗漏,您希望 JPA 生成 ID,因此将 @GeneratedValue(strategy = GenerationType.AUTO) 添加到 Commerce Id 字段。

您的 Category 类没有正确的 ID 生成策略,因为您的 JSON 数据已经包含 ID 值。 但是您的 JSON 数据具有地址 ID,但您选择了由 JPA 在其 POJO 对象中自动生成的 ID。不知道是故意还是巧合。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-08
    • 2017-05-09
    相关资源
    最近更新 更多