java.lang.IllegalStateException: org.hibernate.TransientPropertyValueException

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25439927/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 08:03:00  来源:igfitidea点击:

java.lang.IllegalStateException: org.hibernate.TransientPropertyValueException

javaspringhibernatespring-mvcjakarta-ee

提问by Laurence Geng

My application has two entity Product and Category. When add product , user choose the category that product belong to. But when save the product to data base i meet the error

我的应用程序有两个实体产品和类别。添加产品时,用户选择产品所属的类别。但是当将产品保存到数据库时,我遇到了错误

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.IllegalStateException: org.hibernate.TransientPropertyValueException: Not-null property references a transient value - transient instance must be saved before current operation

org.springframework.web.util.NestedServletException:请求处理失败;嵌套异常是 java.lang.IllegalStateException: org.hibernate.TransientPropertyValueException: Not-null 属性引用了一个瞬态值 - 在当前操作之前必须保存瞬态实例

the content of entity is Category.java

实体的内容是 Category.java

@Entity
@Table(name="category")
public class Category {

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

@Column(name="category_name")
private String categoryName;

@Column(name="description")
private String description;

@OneToMany(mappedBy = "category", fetch=FetchType.LAZY)
private Set<Product> products;

//getter and setter method
}

Product.java

产品.java

@Entity
@Table(name="product")
public class Product {

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

@Column(name="name")
@NotNull
@NotEmpty
private String name;

@Column(name="description")
private String description;

@Column(name="manufacture")
private String manufacture;

@Column(name="price")
private long price;

@Column(name="image_name")
private String imageName;

@ManyToOne
@JoinColumn(name = "category_id", referencedColumnName = "id", nullable = false)
Category category;

//getter and setter method
}

ProductDAO.java

产品DAO.java

@Repository("ProductDAO")
@Transactional
public class ProductDAO {

@PersistenceContext
private EntityManager entityManager;

public EntityManager getEntityManager() {
    return entityManager;
}

public void setEntityManager(EntityManager entityManager) {
    this.entityManager = entityManager;
}

public void create(Product product) {
    entityManager.merge(product.getCategory());
    entityManager.persist(product);
}
//other method
}

my jsp file

我的jsp文件

<form:form method="post" commandName="product" action="add.html" enctype="multipart/form-data">
    Productname <form:input path="name"/>
                <form:errors path="name" class ="error"/><br>
    description    <form:input   path="description"/><br>
    price    <form:input   path="price"/><br>
    manufacture <form:input path="manufacture"/><br>
    Category
    <form:select path="category">
    <form:options items="${categories}" itemValue="id" itemLabel="categoryName" />
    </form:select>
    <form:errors path="category" class ="error"/><br>
    <br/>
    Product image<input type="file" name="file" />
    <form:errors path="imageName" class ="error"/><br>
    <input type="submit" class="register" value="Save">
</form:form>

my Converter

我的转换器

public class CategoryConverter implements Converter<String, Category>{

    @Autowired
    private CategoryService categoryService;

    public Category convert(String id) {
        return categoryService.findById(Long.valueOf(id));
    }
}

thank for any help

感谢您的帮助

回答by Laurence Geng

please add (cascade=CascadeType.ALL) into category field mapping of Product

请将 (cascade=CascadeType.ALL) 添加到 Product 的类别字段映射中

@ManyToOne(cascade=CascadeType.ALL)
@JoinColumn(name = "category_id", referencedColumnName = "id", nullable = false)
Category category;

and remove this line in ProductDAO:

并在 ProductDAO 中删除此行:

entityManager.merge(product.getCategory());

NOTE: if your product's category is an existing one, you should load it first then set it to your product, this is normal flow. Do not new duplicated Category object.

注意:如果您的产品类别是现有的,您应该先加载它,然后将其设置为您的产品,这是正常流程。不要新建重复的 Category 对象。

回答by Laurence Geng

This my fixed code

这是我的固定代码

@Transactional
public void create(Product product) {
    Category category=categoryDAO.findById(product.getCategory().getId());
    category.getProducts().add(product);
    categoryDAO.edit(category);
    product.setCategory(category);
    this.productDAO.create(product);
}