我正在使用带有JPA / Hibernate 4的Spring 3.我在尝试持久化“Product”实体时遇到了IllegalArgumentException。 我在Product和Category之间有一对多的关系,并且有一个复合键ProductId类只有产品和类别的PK。我使用@IdClass注释,因为两个PK都是由DB(MySql)自动生成的。 我的下面的代码将更好地解释它。
我的SQL脚本:
CREATE TABLE IF NOT EXISTS `orangeDB`.`Category` (
`catId` INT NOT NULL AUTO_INCREMENT,
`category` VARCHAR(45) NOT NULL,
`lft` INT NOT NULL,
`rgt` INT NOT NULL,
PRIMARY KEY (`catId`),
UNIQUE INDEX `categoryId_UNIQUE` (`catId` ASC))
ENGINE = InnoDB
AUTO_INCREMENT = 1795327;
CREATE TABLE IF NOT EXISTS `orangeDB`.`Product` (
`prodId` INT(9) NOT NULL AUTO_INCREMENT,
`prefix` CHAR NOT NULL,
`product` VARCHAR(45) NOT NULL,
`quantity` INT(9) NOT NULL,
`price` DOUBLE NOT NULL,
`discount` INT(9) NOT NULL,
`catId` INT NOT NULL,
PRIMARY KEY (`prodId`, `catId`),
INDEX `fk_Product_Category1_idx` (`catId` ASC),
CONSTRAINT `fk_Product_Category1`
FOREIGN KEY (`catId`)
REFERENCES `orangeDB`.`Category` (`catId`)
ON DELETE CASCADE
ON UPDATE CASCADE)
ENGINE = InnoDB
AUTO_INCREMENT = 1143713;
我的模型类: Product,Category和ProductId复合键类。
@SuppressWarnings("serial")
@Entity
@Table(name = "Category", catalog = "orangeDB")
public class Category implements java.io.Serializable {
private Integer catId;
private String category;
private int lft;
private int rgt;
private Set<Product> products = new HashSet<Product>(0);
public Category() {
}
@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "catId", unique = true, nullable = false)
public Integer getCatId() {
return this.catId;
}
public void setCatId(Integer catId) {
this.catId = catId;
}
@Column(name = "category", nullable = false, length = 45)
public String getCategory() {
return this.category;
}
public void setCategory(String category) {
this.category = category;
}
@OneToMany(fetch = FetchType.LAZY, mappedBy = "category")
public Set<Product> getProducts() {
return this.products;
}
public void setProducts(Set<Product> products) {
this.products = products;
}
public void addProduct(Product product) {
this.products.add(product);
if (product.getCategory() != this) {
product.setCategory(this);
}
}
// other getters and setters
}
@SuppressWarnings("serial")
@Entity
@IdClass(ProductId.class)
@Table(name = "Product", catalog = "orangeDB")
public class Product implements java.io.Serializable {
private Integer prodId;
private Category category;
private char prefix = 'P';
private String product;
private int quantity;
private double price;
private int discount;
public Product() {
}
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "prodId", nullable = false)
public Integer getProdId() {
return this.prodId;
}
public void setProdId(Integer prodId) {
this.prodId = prodId;
}
@Id
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "catId", referencedColumnName = "catId", nullable = false, insertable = false, updatable = false)
public Category getCategory() {
return this.category;
}
public void setCategory(Category category) {
this.category = category;
}
@Column(name = "product", nullable = false, length = 45)
public String getProduct() {
return this.product;
}
public void setProduct(String product) {
this.product = product;
}
// other getters and setters
}
@SuppressWarnings("serial")
public class ProductId implements java.io.Serializable {
private Integer prodId;
private Integer category;
public ProductId() {
}
public ProductId(Integer prodId, Integer category) {
this.prodId = prodId;
this.category = category;
}
public Integer getProdId() {
return this.prodId;
}
public void setProdId(Integer prodId) {
this.prodId = prodId;
}
public Integer getCategory() {
return this.category;
}
public void setCategory(Integer category) {
this.category = category;
}
public boolean equals(Object other) {
if ((this == other))
return true;
if ((other == null))
return false;
if (!(other instanceof ProductId))
return false;
ProductId castOther = (ProductId) other;
return (this.getProdId() == castOther.getProdId())
&& (this.getCategory() == castOther.getCategory());
}
public int hashCode() {
int result = 17;
result = 37 * result + this.getProdId();
result = 37 * result + this.getCategory();
return result;
}
}
我的ProductService类保存方法。
@Transactional
public Product save(Product product, Integer catId) {
Category category = categoryService.findOne(catId);
// setting a prodId manually for now, else I get a composite
// identifier cannot be null exception, which is also another issue for me.
product.setProdId(1122);
category.addProduct(product);
if (product.getProdId() == null) {
em.persist(product);
} else {
em.merge(product);
}
return product;
}
有人可以帮我解决这个问题吗?我引用了一些博客和Java Persistence wikibooks,映射似乎没问题。我不明白为什么会发生这种异常。
修改
哦,我忘了添加堆栈跟踪。在这里。
exception
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is javax.persistence.PersistenceException: org.hibernate.PropertyAccessException: IllegalArgumentException occurred while calling setter of model.ProductId.prodId
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:965)
org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:855)
javax.servlet.http.HttpServlet.service(HttpServlet.java:641)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:829)
javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
root cause
javax.persistence.PersistenceException: org.hibernate.PropertyAccessException: IllegalArgumentException occurred while calling setter of model.ProductId.prodId
org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1387)
org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1310)
org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1316)
org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:881)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
java.lang.reflect.Method.invoke(Unknown Source)
org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:241)
$Proxy32.persist(Unknown Source)
service.ProductServiceImpl.save(ProductServiceImpl.java:42)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
java.lang.reflect.Method.invoke(Unknown Source)
org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317)
org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:96)
org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:260)
org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:94)
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
$Proxy35.save(Unknown Source)
controller.Admincontroller.addProduct(Admincontroller.java:276)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
java.lang.reflect.Method.invoke(Unknown Source)
org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:215)
org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132)
org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:745)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:685)
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:919)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:851)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:953)
org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:855)
javax.servlet.http.HttpServlet.service(HttpServlet.java:641)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:829)
javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
root cause
org.hibernate.PropertyAccessException: IllegalArgumentException occurred while calling setter of model.ProductId.prodId
org.hibernate.property.BasicPropertyAccessor$BasicSetter.set(BasicPropertyAccessor.java:119)
org.hibernate.mapping.Component$ValueGenerationPlan.execute(Component.java:423)
org.hibernate.id.CompositeNestedGeneratedValueGenerator.generate(CompositeNestedGeneratedValueGenerator.java:121)
org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:117)
org.hibernate.ejb.event.EJB3PersistEventListener.saveWithGeneratedId(EJB3PersistEventListener.java:78)
org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:208)
org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:151)
org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:78)
org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:853)
org.hibernate.internal.SessionImpl.persist(SessionImpl.java:827)
org.hibernate.internal.SessionImpl.persist(SessionImpl.java:831)
org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:875)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
java.lang.reflect.Method.invoke(Unknown Source)
org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:241)
$Proxy32.persist(Unknown Source)
service.ProductServiceImpl.save(ProductServiceImpl.java:42)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
java.lang.reflect.Method.invoke(Unknown Source)
org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317)
org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:96)
org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:260)
org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:94)
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
$Proxy35.save(Unknown Source)
controller.Admincontroller.addProduct(Admincontroller.java:276)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
java.lang.reflect.Method.invoke(Unknown Source)
org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:215)
org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132)
org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:745)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:685)
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:919)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:851)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:953)
org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:855)
javax.servlet.http.HttpServlet.service(HttpServlet.java:641)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:829)
javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
root cause
java.lang.IllegalArgumentException: argument type mismatch
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
java.lang.reflect.Method.invoke(Unknown Source)
org.hibernate.property.BasicPropertyAccessor$BasicSetter.set(BasicPropertyAccessor.java:65)
org.hibernate.mapping.Component$ValueGenerationPlan.execute(Component.java:423)
org.hibernate.id.CompositeNestedGeneratedValueGenerator.generate(CompositeNestedGeneratedValueGenerator.java:121)
org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:117)
org.hibernate.ejb.event.EJB3PersistEventListener.saveWithGeneratedId(EJB3PersistEventListener.java:78)
org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:208)
org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:151)
org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:78)
org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:853)
org.hibernate.internal.SessionImpl.persist(SessionImpl.java:827)
org.hibernate.internal.SessionImpl.persist(SessionImpl.java:831)
org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:875)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
java.lang.reflect.Method.invoke(Unknown Source)
org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:241)
$Proxy32.persist(Unknown Source)
service.ProductServiceImpl.save(ProductServiceImpl.java:42)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
java.lang.reflect.Method.invoke(Unknown Source)
org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317)
org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:96)
org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:260)
org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:94)
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
$Proxy35.save(Unknown Source)
controller.Admincontroller.addProduct(Admincontroller.java:276)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
java.lang.reflect.Method.invoke(Unknown Source)
org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:215)
org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132)
org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:745)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:685)
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:919)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:851)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:953)
org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:855)
javax.servlet.http.HttpServlet.service(HttpServlet.java:641)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:829)
javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
编辑2:从ProductId类中删除了@IdClass注释。
答案 0 :(得分:0)
我认为你不需要在ProductId类上使用@IdClass。它仅适用于您使用此复合ID的实体。而这个特殊错误是由于您尝试使用整数但必须使用ProductId类的事实引起的。试试这种方式
@SuppressWarnings("serial")
@Entity
@IdClass(ProductId.class)
@Table(name = "Product", catalog = "orangeDB")
public class Product implements java.io.Serializable {
private Integer prodId;
private Category category;
private char prefix = 'P';
private String product;
private int quantity;
private double price;
private int discount;
@Id
@Column(name = "prodId", nullable = false)
public Integer getProdId() {
return this.prodId;
}
public void setProdIt(Integer prodId) {
this.prodId = prodId;
}
@Id
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "catId", referencedColumnName = "catId", nullable = false, insertable = false, updatable = false)
public Category getCategory() {
return this.category;
}
public setProductId(ProductId productId){
this.prodId = productId.getProdId();
this.category = productId.getCategory();
}
//getter&setters
}
在ProductId类中:
private Integer prodId;
private Category category;
public ProductId(Integer prodId, Category category) {
this.prodId = prodId;
this.category = category;
}
getters&setters
然后将其设置为:
Category category = new Category();
ProductId pId = new ProductId(1, category); //id, category
product.setProductId(pId);
并试试这个:
new Product(1, category); // pls add this constructor
你错过的主要原因可能是Produt和IdClass ProductId的setter有相似的名字。
如果使用IdClass,你不需要任何@GeneratedValue注释。
答案 1 :(得分:0)
如果您想使用@IdClass
,那么属性名称&amp; ProductId
类和Product
实体中的类型必须匹配。
在您宣布的Product.java
课程中:
prodId
为Integer
,category
为Category
但是在ProductId.java
类中,您声明了:
prodId
为Integer
,category
为Integer
你也不应该在@IdClass
课程中发表ProductId
声明,你必须将其删除。
尝试以下更改:
Product.java
@Entity
@IdClass(ProductId.class)
@Table(name = "Product")
public class Product implements java.io.Serializable {
private Integer prodId;
private Category category;
private int categoryId; // Adding new property
@Id
@GeneratedValue
@Column(name = "prodId", nullable = false)
public Integer getProdId() {
return this.prodId;
}
@Id
@Column(name = "catId", insertable = false, updatable = false)
public int getCategoryId() {
return categoryId;
}
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "catId", referencedColumnName = "catId", nullable = false, insertable = false, updatable = false)
public Category getCategory() {
return this.category;
}
// Setters&amp;干将 }
ProductId.java
// Remove the @IdClass annoatation from here
public class ProductId implements java.io.Serializable {
private Integer prodId;
private Integer categoryId; // The property name should match
public ProductId() {
}
public ProductId(Integer prodId, Integer categoryId) {
this.prodId = prodId;
this.categoryId = categoryId;
}
public Integer getProdId() {
return this.prodId;
}
public void setProdId(Integer prodId) {
this.prodId = prodId;
}
public Integer getCategoryId() {
return categoryId;
}
public void setCategoryId(Integer categoryId) {
this.categoryId = categoryId;
}
public boolean equals(Object other) {
if ((this == other))
return true;
if ((other == null))
return false;
if (!(other instanceof ProductId))
return false;
ProductId castOther = (ProductId) other;
return (this.getProdId() == castOther.getProdId())
&& (this.getCategoryId() == castOther.getCategoryId());
}
public int hashCode() {
int result = 17;
result = 37 * result + this.getProdId();
result = 37 * result + this.getCategoryId();
return result;
}
}
此更改还将解决与composite identifier cannot be null
相关的问题。