【问题标题】:updating value in junction table is troublesome spring data JPA更新联结表中的值是麻烦的弹簧数据JPA
【发布时间】:2016-01-12 16:33:12
【问题描述】:

我有两个实体一个

@Entity    
public class Job {  

    @Id
    @GeneratedValue
    private Integer id;

    @Size(min = 5,max = 50, message = "Valid title is 5-50 chars")
    private String title;       

    @ManyToMany(cascade = {CascadeType.MERGE})
    @JoinTable(name = "jobs_categories",
                joinColumns = @JoinColumn(name = "jobs_id"),
                inverseJoinColumns = @JoinColumn(name = "categories_id"))
    private List<Category> categories;
    // omitting setters/getters
}

和其他一样

@Entity
public class Category {    

    @Id
    @GeneratedValue
    private Integer id;

    @Size(min = 5,max = 15, message = "Valid name is 5-15 chars")
    private String name;

    @ManyToMany(mappedBy = "categories", cascade = {CascadeType.MERGE}) 
    private List<Job> jobs; 
    // omitting setters/getters
    }

我想对这两个实现 CRUD 操作, 我保存了一份包含某些类别的工作

Job title - Fullstack JavaScript CSS3 / HTML5 / Developer
Categories - AngularJS, Backbone.js, CSS, CSS3, Graphic design, HTML, HTML5,
             JavaScript, MongoDB Node.js, twitter bootstrap, Web design.

然后,如果我想通过在上面保存的作业中添加或删除类别来更新作业,它永远不会更新(例如,添加/删除)类别。

为了更新 Job,我在 JobService 中有方法

@Service
public class JobService{

    @Autowired
    private JobRepository jobRepository;

    @Autowired
    private CategoryRepository categoryRepository;

    @Autowired
    private LocalContainerEntityManagerFactoryBean entityManagerFactory;

    private Session session;

    Logger logger = LoggerFactory.getLogger(JobService.class);      

    public void updateJobCategory(Job job) {                
    EntityManager entityManager = entityManagerFactory.getObject().createEntityManager();
    session= entityManager.unwrap(org.hibernate.Session.class);
    logger.info("got Job ID as  ==> " + String.valueOf(job.getId()));
    Job jobObj = (Job) session.get(Job.class, job.getId());
    jobObj.getCategories().clear();     
    logger.info("got Job ID as  ==> " + String.valueOf(jobObj.getId()));

    if (!job.getCategories().isEmpty()) {
        logger.info("got job.getCategories() as not Null");
        List<Category> categories = job.getCategories();
        for (Category category : categories) {              
            logger.info("Good job.getCategories() to update ==> " + category.getName());
        }
        logger.info("adding job.getCategories() to update ==> ");
        jobObj.setCategories(job.getCategories());      

    }else {
        logger.info("got job.getCategories() as Null");
    }
    session.update(jobObj); 

    }
    public void update(Job job) {
        jobRepository.update(job.getId(), job.getTitle());
        updateJobCategory(job);
    }
}

我得到日志

logger.info("Got job.getCategories() to update" + category.getName());

我正在更新(新添加/旧删除)所有类别的列表,

Hibernate: update job set title=? where id=?
INFO : com.rhcloud.jobsnetwork.service.JobService - got Job ID as  ==> 1
Hibernate: select job0_.id as id1_1_0_, job0_.title as title7_1_0_ from job job0_ where job0_.id=?
Hibernate: select categories0_.jobs_id as jobs_id1_1_0_, categories0_.categories_id as categori2_2_0_, category1_.id as id1_0_1_, category1_.name as name2_0_1_ from jobs_categories categories0_ inner join category category1_ on categories0_.categories_id=category1_.id where categories0_.jobs_id=?
INFO : com.rhcloud.jobsnetwork.service.JobService - got Job ID as  ==> 1
INFO : com.rhcloud.jobsnetwork.service.JobService - got job.getCategories() as not Null
INFO : com.rhcloud.jobsnetwork.service.JobService - Good job.getCategories() to update ==> iOS App Dev
INFO : com.rhcloud.jobsnetwork.service.JobService - Good job.getCategories() to update ==> Android App Dev
INFO : com.rhcloud.jobsnetwork.service.JobService - adding job.getCategories() to update

但是当我看到 Job 的详细信息时,我得到了列出的类别,这些类别是在创建作业时添加的而不是更新的,我猜它没有更新联结表 jobs_categories 中的类别 ID 值。 不知道更新与工作相关的类别?

更新

当我使用时

public void persistJob(Job newJob) {
         em.persist(newJob);
       }

       public void saveJob(Job job) {
          em.merge(job);
       }
       public void persistCategory(Category newcat) {
         em.persist(newcat);
       }

没有@Transactional 在我得到异常的每种方法

javax.persistence.TransactionRequiredException: No transactional EntityManager available
    at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:275)
    at com.sun.proxy.$Proxy167.persist(Unknown Source)
    at com.rhcloud.jobsnetwork.service.JobService.persistJob(JobService.java:29)
    at com.rhcloud.jobsnetwork.service.JobService$$FastClassBySpringCGLIB$$53974ce3.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:649)
    at com.rhcloud.jobsnetwork.service.JobService$$EnhancerBySpringCGLIB$$c08e8d16.persistJob(<generated>)
    at com.rhcloud.jobsnetwork.controllers.JobController.addJobDetail(JobController.java:86)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:137)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:776)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:705)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:966)
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:868)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:650)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:842)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:731)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:505)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:957)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:423)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1079)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:620)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:318)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:745)

添加@Transactional 后,它可以摆脱上述异常,我使用

保存新工作
@RequestMapping(value = "/add-job", method = RequestMethod.POST)
    public String addJobDetail(@ModelAttribute("job") Job job) {            
        jobService.persistJob(job); 
        return "redirect:/";
    } 

我让所有的事情都完美无缺,但是当我在 JobController 中使用 saveJob 作为

@RequestMapping(value = "/updated", method = RequestMethod.POST)
    public String updateJob(@ModelAttribute("job") Job job) {           
        jobService.saveJob(job);
        return "redirect:/";
    } 

更新的作业中没有保存任何类别(之前没有添加没有更新的类别),在这种情况下有任何建议。

更新 - 2

根据您的建议,我将记录器添加到

 @Transactional
   public void saveJob(Job job) {
       logger.error("got job.getCategories() of " + job.getCategories().size());
      em.merge(job);         
   }

此时我在

处得到 NullPointerException
 logger.error("got job.getCategories() of " + job.getCategories().size() + " size");

日志/跟踪是

java.lang.NullPointerException
    at com.rhcloud.jobsnetwork.service.JobService.saveJob(JobService.java:37)
    at com.rhcloud.jobsnetwork.service.JobService$$FastClassBySpringCGLIB$$53974ce3.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:717)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
    at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:98)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:262)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:653)
    at com.rhcloud.jobsnetwork.service.JobService$$EnhancerBySpringCGLIB$$41dc2ac2.saveJob(<generated>)
    at com.rhcloud.jobsnetwork.controllers.JobController.updateJob(JobController.java:109)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:137)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:776)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:705)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:966)
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:868)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:650)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:842)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:731)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:505)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:957)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:423)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1079)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:620)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:318)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:745)

【问题讨论】:

  • var : categoryObj 有什么用? 'job' 是否也在会话中(在调用此 updateJobCategory 方法之前是否已加载或保存)?
  • var : categoryObj 仅用于记录,可能会被删除。
  • @Thierry 请看看我的编辑。

标签: java jpa spring-data-jpa


【解决方案1】:

你有错误的映射。 试试这个:

@Entity
public class Category {    

@Id
@GeneratedValue
private Integer id;

@Size(min = 5,max = 15, message = "Valid name is 5-15 chars")
private String name;

@ManyToMany(cascade = CascadeType.ALL,orphanRemoval = true) 
@JoinColumn(name = "jobs_id",referencedColumnName = "jobs_id")
private List<Job> jobs; 
// omitting setters/getters
}

第二个实体:

@Entity    
public class Job {  

@Id
@GeneratedValue
private Integer id;

@Size(min = 5,max = 50, message = "Valid title is 5-50 chars")
private String title;       

@ManyToMany(cascade = CascadeType.ALL,orphanRemoval = true)
@JoinColumn(name = "categories_id",referencedColumnName = "categories_id")
private List<Category> categories;
// omitting setters/getters
}

附:编辑表格中的列名;

【讨论】:

  • 感谢您的关心,但您的回答无效。首先它说的是注释类型ManyToMany 的属性orphanRemoval 未定义,然后它创建了4 个表而不是3 个。意思是说我想要 jobcategoryjobs_categories,但它会创建 jobcategoryjobs_categoriescategories_jobs 抱歉!!
  • 其中一个实体需要是关系的所有者,请参阅第 2.9 章 双向关系的反面必须通过 OneToOne 的 mappedBy 元素引用其拥有方, OneToMany 或 ManyToMany 注释。 以及 JPA spec 的第 2.10.4 章中应用的默认映射
【解决方案2】:

在您的情况下,您有两个实体,每个实体都可以单独存在 - 没有工作的类别很好,而工作可以没有分配的类别。 orphanRemoval 用于OnetoManyOneToOne,如果您想对不再从父实体引用的相关实体执行删除操作(想想组合),这里不是这种情况。我相信您只是想删除工作与特定类别(认为关联)之间的联系。

您的映射是正确的(以 Job 作为关系所有者的双向多线程),我建议只进行少量修改: 为您的集合使用java.util.Set(通过删除连接表提高性能,防止“无法获取多个包”异常)并覆盖equals 方法(使集合操作更容易)。

我们开始吧:

@Entity    
public class Job { 
@Id
@GeneratedValue
private Integer id;

private String title;

@ManyToMany(fetch=FetchType.EAGER,cascade = { CascadeType.MERGE })
@JoinTable(name = "jobs_categories", joinColumns = @JoinColumn(name = "jobs_id") , inverseJoinColumns = @JoinColumn(name = "categories_id") )
private Set<Category> categories = new HashSet<Category>();

类别

@Entity
public class Category {

@Id
@GeneratedValue
private Integer id;

private String name;

@ManyToMany(mappedBy = "categories", cascade = { CascadeType.MERGE })
private List<Job> jobs;

@Override
public boolean equals(Object obj) {
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    Category other = (Category) obj;
    if (id == null) {
        if (other.id != null)
            return false;
    } else if (!id.equals(other.id))
        return false;
    return true;
}

您的更新函数中的一个问题是您覆盖了作业实体中对集合的引用。

jobObj.setCategories(job.getCategories());

您应该始终修改原始集合,切勿分配新集合。

您还可以考虑从您的 ManyToMany 中完全删除 Merge 级联,因为它会使代码工作流程更易于理解 - 类别将单独管理,您只需将已保存的类别添加到新的 Job 实例(但这只是一个建议,我们将使其即使在级联下也能正常工作:))。

现在是一些测试代码。我使用普通的 JPA,而不是 Spring 存储库,以使其易于理解。

JobService(在您的情况下,它将分为多个类、存储库..):

public class JobService {

   @PersistenceContext
   EntityManager em;

   public void persistJob(Job newJob) {
     em.persist(newJob);
   }

   public Job getJob(Integer jobId) {
     return em.find(Job.class, jobId);
   }

   public void saveJob(Job job) {
      em.merge(job);
   }

   public void persistCategory(Category newcat) {
     em.persist(newcat);
   }

   public List<Category> getAllCategories() {
     return em.createQuery("from Category", Category.class).getResultList();
   }  
}

让我们测试一下:

Job job = new Job();
job.setTitle("Web developer");
Category catJS = new Category();
catJS.setName("javascript");
Category catCSS = new Category();
catCSS.setName("CSS");
Category catNG = new Category();
catNG.setName("AngualrJS");
Category catHTML = new Category();
catHTML.setName("HTML5");
//persist categories separately
jobservice.persistCategory(catNG);
jobservice.persistCategory(catCSS);
jobservice.persistCategory(catHTML);
jobservice.persistCategory(catJS);
//at this point, we have 4 categories as managed entities
//add the saved categories to a new job instance
job.getCategories().add(catHTML);
job.getCategories().add(catJS);

//save job in DB
jobservice.persistJob(job);
//we do not need to set Job references in Category objects, because Job is the relationship owner - it will correctly update the FKs in join table
assertNotNull("job should be saved", job.getId());
Job fromDb = jobservice.getJob(job.getId());//reload from DB
assertNotNull("job should be stored in DB", fromDb);
assertTrue("job should have 2 categories", fromDb.getCategories().size() == 2);
//great si far so good  

//remove one of the assigned categories from Job(this is where you need that **equals** method in Category )
fromDb.getCategories().remove(catHTML);
assertTrue("job should not have only one category in Memory", fromDb.getCategories().size() ==1);
jobservice.saveJob(fromDb);
//we do not want to delete the *HTML* category from DB, just remove it from the particular job
Job fromDbAfterUpdate = jobservice.getJob(job.getId());
assertTrue("job should not have only one category in BD", fromDbAfterUpdate.getCategories().size() ==1);
List<Category> allCategories = jobservice.getAllCategories();
assertTrue("there should still be 4 categories in DB", allCategories.size() == 4);


//now lets test the Merge cascade
Category unsavedCategory = new Category();
unsavedCategory.setName("jquery");
fromDbAfterUpdate.getCategories().add(unsavedCategory );
//we have added an unsaved category to an  existing job. As Job has cascade merge on it categories, the *unsavedCategory* will be saved and then linked to job via job_category join table
jobservice.saveJob(fromDbAfterUpdate);
fromDbAfterUpdate = jobservice.getJob(fromDbAfterUpdate.getId());
assertTrue("job should now have 2 categories", fromDbAfterUpdate.getCategories().size() ==2);


// one more test, add and remove at the same time
fromDbAfterUpdate.getCategories().remove(catJS);
fromDbAfterUpdate.getCategories().add(catHTML);
fromDbAfterUpdate.getCategories().add(catCSS);
jobservice.saveJob(fromDbAfterUpdate);
fromDbAfterUpdate = jobservice.getJob(fromDbAfterUpdate.getId());
assertTrue("job should now have 3 categories", fromDbAfterUpdate.getCategories().size() ==3);
allCategories = jobservice.getAllCategories();
assertTrue("there should be 5 categories in DB", allCategories.size() == 5);

TL;DR

  • 让您的更新方法保持简单 - 您不需要从数据库中获取对象并在托管对象和分离对象之间移动内容,让 JPA 合并完成它的工作
  • 永远不要更改对托管实体集合的引用 - 直接对集合执行操作
  • 在您真正需要它们之前忽略任何级联

更多信息请咨询JPA Spec

【讨论】:

  • 感谢您的关心,但我如何更新 工作 编辑值__(例如更新名称、类别)__ 您能否提供一个 method 用于此目的,因为有方法 savegetAllCategories 拜托你会非常非常好:|
  • JPA 术语中的更新是merge。示例 JobService 有两种保存作业的方法 - persistJob - 仅适用于新作业 - 将导致 INSERT 语句。另一种方法 - saveJob 执行 em.merge 并将导致 SQL UPDATE。因此,如果您更改任何作业属性,它将在您调用em.merge(job) 时保存。提供的测试代码首先保存具有两个类别的作业,然后对该作业的类别执行多项更改
  • 您能否在调用`jobService.saveJob(job);`之前调试/添加日志记录以查看当时该作业实例中是否有任何类别?正如您所做的HTTP POST 一样,您能否验证该作业是否与其类别一起发送?您必须记住,您在 REST 方法中获得的 JOb 对象不是托管实体 - 它是从 HTTP POST 反序列化的完全分离的实体。还要检查该对象的 ID 是否与您之前持久化的 Job 实例的 ID 匹配。
  • 请在上面的问题中查看我的 Update-2
  • 好的,空指针显然是由于您的 Job 实例在您将其传递给 em.merge 时没有类别,即 job.getCategories() 为空。你如何调用你的 REST 方法?您能否验证您在 POST 请求中发送的对象是否包含类别。此问题与 JPA 无关,它只是由该特定实例没有分配类别这一事实引起的。创建一个测试方法,您可以在其中测试 JPA 相关功能,以验证更新是否在那里工作。然后分析您的 REST 以确定类别丢失的原因。
猜你喜欢
  • 2017-10-16
  • 1970-01-01
  • 2014-03-28
  • 2013-07-06
  • 2011-08-19
  • 1970-01-01
  • 2018-04-26
  • 2017-11-07
  • 1970-01-01
相关资源
最近更新 更多