无法在Spring表单选择标记中保存外键

时间:2012-12-11 22:35:25

标签: spring-mvc

我正在尝试保存一个在select标签中有外键的表单,但它始终为null。当我使用inspect元素时,它会发布所选的id,所以我不能说它是表单的问题。有人可以请帮助。 表格

   <form:select path="categoryId">
            <form:option value="0" label="   -- Please Select --" />
            <form:options items="${categoryList}"  itemValue="categoryId" itemLabel="categoryName"/>
    </form:select>

控制器

@RequestMapping(value = "product", method = RequestMethod.POST)
public String addNewProduct(@ModelAttribute("product") Product product, Model model){
    model.addAttribute("product", product);
    purchaseOrderService.addProduct(product);
    return "categories";
}

JPA

@Transactional(propagation = Propagation.REQUIRED)
    public boolean saveProduct(Product product) {
        EntityManager em = getEm();
        em.persist(product);
        return true;
    }

持久性对象

@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name = "CATEGORY_ID", referencedColumnName = "CATEGORY_ID")
private Category categoryId;

错误

java.lang.NoClassDefFoundError: org/hibernate/exception/LockTimeoutException
org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1328)
org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1300)
org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:80)
org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:512)
org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:754)
org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:723)
org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:394)
org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:120)
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
$Proxy34.addProduct(Unknown Source)
com.logicalideas.purchaseorder.ProductController.addNewProduct(ProductController.java:30)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:601)
org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:213)
org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:126)
org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:96)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:617)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:578)
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:923)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:852)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882)
org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:789)
javax.servlet.http.HttpServlet.service(HttpServlet.java:641)
javax.servlet.http.HttpServlet.service(HttpServlet.java:722)

根本原因

java.lang.ClassNotFoundException:org.hibernate.exception.LockTimeoutException     org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1711)     org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1556)     org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1328)     org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1300)     org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:80)     org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:512)     org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:754)     org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:723)     org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:394)     org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:120)     org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)     org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)     $ Proxy34.addProduct(未知来源)     com.logicalideas.purchaseorder.ProductController.addNewProduct(ProductController.java:30)     sun.reflect.NativeMethodAccessorImpl.invoke0(原生方法)     sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)     sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)     java.lang.reflect.Method.invoke(Method.java:601)     org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:213)     org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:126)     org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:96)     org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:617)     org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:578)     org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)     org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:923)     org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:852)     org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882)     org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:789)     javax.servlet.http.HttpServlet.service(HttpServlet.java:641)     javax.servlet.http.HttpServlet.service(HttpServlet.java:722)

非常感谢

1 个答案:

答案 0 :(得分:0)

当你解决第一个问题(ClassNotFound)时,我认为现在还可以。

关于你的第二个问题:

  

嗯,这已经摆脱了错误,但它有一个奇怪的行为   现在,即使你是产品控制器,它也会创建一个新的类别   尝试使用所选类别(FK)保存新产品。然后它补充说   这个新创建的categoryId与你的副本重复   选择(名称,而不是id)到product.categoryId。我真的希望   我不是在混淆任何人。我非常感谢一些人。

这不是同一个问题。我认为你误解了Hibernate的工作方式。在这种情况下让Spring机制映射对象时,它将始终创建一个新的categoryId对象。另一方面,通过另一种方式,您可以让Spring了解它们是相同的,但是在尝试编辑类别时会遇到麻烦。

这里的问题是你依赖Spring来映射正确的Hibernate对象 - Spring映射并不总是好的。相反,我认为您可以向服务器发送类似“idOfCategory”的参数,通过该ID获取CategoryId对象,然后将类别设置为新创建的产品。更好的方法是只从客户端传输DTO对象(ProductDTO),然后在服务器端创建一个完整的Hibernate Product对象。

例如:

@RequestMapping(value = "product", method = RequestMethod.POST)
public String addNewProduct(@ModelAttribute("productDTO") ProductDTO productDTO, Model model){
    model.addAttribute("product", product);
    Product product = new Product(productDTO);
    CategoryId id = productService.getCategoryById(productDTO.getCategoryId());
    product.setCategoryId(id);
    purchaseOrderService.addProduct(product);
    return "categories";
}