在我的TagController中调用purchaseService.updatePurchase(purchase)时出现以下错误:
SEVERE: Servlet.service() for servlet [PurchaseAPIServer] in context with path [/PurchaseAPIServer] threw exception [Request processing failed; nested exception is org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.app.model.Purchase.tags, no session or session was closed] with root cause
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.app.model.Purchase.tags, no session or session was closed
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:383)
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:375)
at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:368)
at org.hibernate.collection.PersistentSet.add(PersistentSet.java:212)
at com.app.model.Purchase.addTags(Purchase.java:207)
at com.app.controller.TagController.createAll(TagController.java:79)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:212)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:126)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:96)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:617)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:578)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:900)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:827)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:789)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:641)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:225)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:169)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:927)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:999)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:565)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:309)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)
的 TagController: 的
@RequestMapping(value = "purchases/{purchaseId}/tags", method = RequestMethod.POST, params = "manyTags")
@ResponseStatus(HttpStatus.CREATED)
public void createAll(@PathVariable("purchaseId") final Long purchaseId, @RequestBody final Tag[] entities)
{
Purchase purchase = purchaseService.getById(purchaseId);
Set<Tag> tags = new HashSet<Tag>(Arrays.asList(entities));
purchase.addTags(tags);
purchaseService.updatePurchase(purchase);
}
的 采购:
@Entity
@XmlRootElement
public class Purchase implements Serializable
{
/**
*
*/
private static final long serialVersionUID = 6603477834338392140L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@OneToMany(mappedBy = "purchase", fetch = FetchType.LAZY, cascade={CascadeType.ALL})
private Set<Tag> tags;
@JsonIgnore
public Set<Tag> getTags()
{
if (tags == null)
{
tags = new LinkedHashSet<Tag>();
}
return tags;
}
public void setTags(Set<Tag> tags)
{
this.tags = tags;
}
public void addTag(Tag tag)
{
tag.setPurchase(this);
this.tags.add(tag);
}
public void addTags(Set<Tag> tags)
{
Iterator<Tag> it = tags.iterator();
while (it.hasNext())
{
Tag tag = it.next();
tag.setPurchase(this);
this.tags.add(tag);
}
}
...
}
的 标签:
@Entity
@XmlRootElement
public class Tag implements Serializable
{
/**
*
*/
private static final long serialVersionUID = 5165922776051697002L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumns({@JoinColumn(name = "PURCHASEID", referencedColumnName = "ID")})
private Purchase purchase;
@JsonIgnore
public Purchase getPurchase()
{
return purchase;
}
public void setPurchase(Purchase purchase)
{
this.purchase = purchase;
}
}
的 PurchaseService:
@Service
public class PurchaseService implements IPurchaseService
{
@Autowired
private IPurchaseDAO purchaseDAO;
public PurchaseService()
{
}
@Transactional
public List<Purchase> getAll()
{
return purchaseDAO.findAll();
}
@Transactional
public Purchase getById(Long id)
{
return purchaseDAO.findOne(id);
}
@Transactional
public void addPurchase(Purchase purchase)
{
purchaseDAO.save(purchase);
}
@Transactional
public void updatePurchase(Purchase purchase)
{
purchaseDAO.update(purchase);
}
}
的 TagService:
@Service
public class TagService implements ITagService
{
@Autowired
private ITagDAO tagDAO;
public TagService()
{
}
@Transactional
public List<Tag> getAll()
{
return tagDAO.findAll();
}
@Transactional
public Tag getById(Long id)
{
return tagDAO.findOne(id);
}
@Transactional
public void addTag(Tag tag)
{
tagDAO.save(tag);
}
@Transactional
public void updateTag(Tag tag)
{
tagDAO.update(tag);
}
}
关于如何解决这个问题的任何想法? (我想避免使用EAGER加载)。
我是否需要为交易设置某种形式的会话管理?
由于
的 TagController 的
@RequestMapping(value = "purchases/{purchaseId}/tags", method = RequestMethod.POST, params = "manyTags")
@ResponseStatus(HttpStatus.CREATED)
public void createAll(@PathVariable("purchaseId") final Long purchaseId, @RequestBody final Tag[] entities)
{
Purchase purchase = purchaseService.getById(purchaseId);
// Validation
RestPreconditions.checkRequestElementNotNull(purchase);
RestPreconditions.checkRequestElementIsNumeric(purchaseId);
Set<Tag> tags = new HashSet<Tag>(Arrays.asList(entities));
purchaseService.addTagsToPurchase(purchaseId, tags);
}
的 PurchaseService 的
@Transactional
public void addTagsToPurchase(Long purchaseId, Set<Tag> tags)
{
Purchase p = purchaseDAO.findOne(purchaseId);
p.addTags(tags);
}
答案 0 :(得分:0)
您在不初始化其标签集合的情况下加载Purchase,然后在您的控制器中,一旦事务提交并且会话关闭,您就会向此未初始化的集合添加标记。显然,抛出了这个异常。
您有两种可能性:
Hibernate.initialize(purchase.getTags())
,或者在单个查询(select distinct p from Purchase p left join fetch p.tags
)中执行加载标记及其标记的JPQL查询。addTagsToPurchase(Long purchaseId, Set<Tag> tags)
,重新加载购买并将标签添加到此次购买中,而不是提供比DAO更多的服务类。这实际上是您的控制器所需的服务方法。我当然更喜欢到目前为止的第二种解决方案:
通常,如果您的控制器执行单个原子操作需要多次调用服务层,则意味着服务层不提供所需的功能,并且该服务在表示层中实现