org.hibernate.LazyInitializationException: 无法初始化代理 - 没有 Session。对于测试用例 JUnit

Posted

技术标签:

【中文标题】org.hibernate.LazyInitializationException: 无法初始化代理 - 没有 Session。对于测试用例 JUnit【英文标题】:org.hibernate.LazyInitializationException: could not initialize proxy - no Session . For a Testcase JUnit 【发布时间】:2017-06-01 10:08:38 【问题描述】:

我有两个控制器,如下所示,我一直在尝试为它们编写测试用例,但自从控制器用户 @AuthenticationPrincipal 以来。我很难为他们编写测试用例,并且在运行测试用例时遇到错误。

@ResponseBody
@RequestMapping(value = "/view/id", method = RequestMethod.GET, produces = "application/pdf")
public ResponseEntity renderDocument(@AuthenticationPrincipal Principal principal, @PathVariable("id") Long id)
        throws IOException 
    Journal journal = journalRepository.findOne(id);
    Category category = journal.getCategory();
    CurrentUser activeUser = (CurrentUser) ((Authentication) principal).getPrincipal();
    User user = userRepository.findOne(activeUser.getUser().getId());
    List<Subscription> subscriptions = user.getSubscriptions();
    Optional<Subscription> subscription = subscriptions.stream()
            .filter(s -> s.getCategory().getId().equals(category.getId())).findFirst();
    if (subscription.isPresent() || journal.getPublisher().getId().equals(user.getId())) 
        File file = new File(PublisherController.getFileName(journal.getPublisher().getId(), journal.getUuid()));
        InputStream in = new FileInputStream(file);
        return ResponseEntity.ok(IOUtils.toByteArray(in));
     else 
        return ResponseEntity.notFound().build();
    



@RequestMapping(method = RequestMethod.POST, value = "/publisher/publish")
@PreAuthorize("hasRole('PUBLISHER')")
public String handleFileUpload(@RequestParam("name") String name, @RequestParam("category")Long categoryId, @RequestParam("file") MultipartFile file,
        RedirectAttributes redirectAttributes, @AuthenticationPrincipal Principal principal) 

    CurrentUser activeUser = (CurrentUser) ((Authentication) principal).getPrincipal();
    Optional<Publisher> publisher = publisherRepository.findByUser(activeUser.getUser());

    String uuid = UUID.randomUUID().toString();
    File dir = new File(getDirectory(publisher.get().getId()));
    createDirectoryIfNotExist(dir);

    File f = new File(getFileName(publisher.get().getId(), uuid));
    if (!file.isEmpty()) 
        try 
            BufferedOutputStream stream = new BufferedOutputStream(new FileOutputStream(f));
            FileCopyUtils.copy(file.getInputStream(), stream);
            stream.close();
            Journal journal = new Journal();
            journal.setUuid(uuid);
            journal.setName(name);
            journalService.publish(publisher.get(), journal, categoryId);
            return "redirect:/publisher/browse";
         catch (Exception e) 
            redirectAttributes.addFlashAttribute("message",
                    "You failed to publish " + name + " => " + e.getMessage());
        
     else 
        redirectAttributes.addFlashAttribute("message",
                "You failed to upload " + name + " because the file was empty");
    

    return "redirect:/publisher/publish";

测试用例是

@Test
    @WithMockUser(username = "user1", roles =  "USER" )
    public void renderDocument() throws Exception 


        mockMvc.perform(get("/view/id", 1)).andExpect(content().contentType(contentType)).andExpect(status().isOk());
    

但我收到以下错误:-

org.hibernate.LazyInitializationException: could not initialize proxy - no Session
    at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:165)
    at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:286)
    at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:185)
    at com.crossover.trial.journals.model.Publisher_$$_jvst650_0.toString(Publisher_$$_jvst650_0.java)
    at org.springframework.web.util.UriComponents.getVariableValueAsString(UriComponents.java:269)
    at org.springframework.web.util.UriComponents.expandUriComponent(UriComponents.java:234)
    at org.springframework.web.util.HierarchicalUriComponents$FullPathComponent.expand(HierarchicalUriComponents.java:685)
    at org.springframework.web.util.HierarchicalUriComponents.expandInternal(HierarchicalUriComponents.java:328)
    at org.springframework.web.util.HierarchicalUriComponents.expandInternal(HierarchicalUriComponents.java:47)
    at org.springframework.web.util.UriComponents.expand(UriComponents.java:163)
    at org.springframework.web.util.UriComponentsBuilder.buildAndExpand(UriComponentsBuilder.java:412)
    at org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder.<init>(MockHttpServletRequestBuilder.java:122)
    at org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get(MockMvcRequestBuilders.java:55)
    at com.crossover.trial.journals.rest.JournalServiceTest.renderDocument(JournalServiceTest.java:187)
    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:498)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:254)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:89)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:193)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

JournalServiceTest.java

package com.crossover.trial.journals.rest;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup;

import java.nio.charset.Charset;
import java.util.List;
import java.util.Optional;

import com.crossover.trial.journals.Application;
import com.crossover.trial.journals.model.Journal;
import com.crossover.trial.journals.model.Publisher;
import com.crossover.trial.journals.model.User;
import com.crossover.trial.journals.repository.PublisherRepository;
import com.crossover.trial.journals.service.JournalService;
import com.crossover.trial.journals.service.ServiceException;
import com.crossover.trial.journals.service.UserService;

import org.junit.Before;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.MethodSorters;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.web.context.WebApplicationContext;

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
@WebAppConfiguration
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class JournalServiceTest 

    private final static String NEW_JOURNAL_NAME = "New Journal";

    @Autowired
    private JournalService journalService;

    @Autowired
    private UserService userService;

    @Autowired
    private PublisherRepository publisherRepository;

    private MockMvc mockMvc;

    @Autowired
    private WebApplicationContext webApplicationContext;

    @Before
    public void setup() throws Exception 
        this.mockMvc = webAppContextSetup(webApplicationContext).apply(springSecurity()).build();
    

    @Test
    public void browseSubscribedUser() 
        List<Journal> journals = journalService.listAll(getUser("user1"));
        assertNotNull(journals);
        assertEquals(1, journals.size());

        assertEquals(new Long(1), journals.get(0).getId());
        assertEquals("Medicine", journals.get(0).getName());
        assertEquals(new Long(1), journals.get(0).getPublisher().getId());
        assertNotNull(journals.get(0).getPublishDate());
    

    @Test
    public void browseUnSubscribedUser() 
        List<Journal> journals = journalService.listAll(getUser("user2"));
        assertEquals(0, journals.size());
    

    @Test
    public void listPublisher() 
        User user = getUser("publisher1");
        Optional<Publisher> p = publisherRepository.findByUser(user);
        List<Journal> journals = journalService.publisherList(p.get());
        assertEquals(2, journals.size());

        assertEquals(new Long(1), journals.get(0).getId());
        assertEquals(new Long(2), journals.get(1).getId());

        assertEquals("Medicine", journals.get(0).getName());
        assertEquals("Test Journal", journals.get(1).getName());
        journals.stream().forEach(j -> assertNotNull(j.getPublishDate()));
        journals.stream().forEach(j -> assertEquals(new Long(1), j.getPublisher().getId()));

    

    @Test(expected = ServiceException.class)
    public void publishFail() throws ServiceException 
        User user = getUser("publisher2");
        Optional<Publisher> p = publisherRepository.findByUser(user);

        Journal journal = new Journal();
        journal.setName("New Journal");

        journalService.publish(p.get(), journal, 1L);
    

    @Test(expected = ServiceException.class)
    public void publishFail2() throws ServiceException 
        User user = getUser("publisher2");
        Optional<Publisher> p = publisherRepository.findByUser(user);

        Journal journal = new Journal();
        journal.setName("New Journal");

        journalService.publish(p.get(), journal, 150L);
    

    @Test()
    public void publishSuccess() 
        User user = getUser("publisher2");
        Optional<Publisher> p = publisherRepository.findByUser(user);

        Journal journal = new Journal();
        journal.setName(NEW_JOURNAL_NAME);
        journal.setUuid("SOME_EXTERNAL_ID");
        try 
            journalService.publish(p.get(), journal, 3L);
         catch (ServiceException e) 
            fail(e.getMessage());
        

        List<Journal> journals = journalService.listAll(getUser("user1"));
        assertEquals(2, journals.size());

        journals = journalService.publisherList(p.get());
        assertEquals(2, journals.size());
        assertEquals(new Long(3), journals.get(0).getId());
        assertEquals(new Long(4), journals.get(1).getId());
        assertEquals("Health", journals.get(0).getName());
        assertEquals(NEW_JOURNAL_NAME, journals.get(1).getName());
        journals.stream().forEach(j -> assertNotNull(j.getPublishDate()));
        journals.stream().forEach(j -> assertEquals(new Long(2), j.getPublisher().getId()));
    

    @Test(expected = ServiceException.class)
    public void unPublishFail() 
        User user = getUser("publisher1");
        Optional<Publisher> p = publisherRepository.findByUser(user);
        journalService.unPublish(p.get(), 4L);
    

    @Test(expected = ServiceException.class)
    public void unPublishFail2() 
        User user = getUser("publisher1");
        Optional<Publisher> p = publisherRepository.findByUser(user);
        journalService.unPublish(p.get(), 100L);
    

    @Test
    public void unPublishSuccess() 
        User user = getUser("publisher2");
        Optional<Publisher> p = publisherRepository.findByUser(user);
        journalService.unPublish(p.get(), 4L);

        List<Journal> journals = journalService.publisherList(p.get());
        assertEquals(1, journals.size());
        journals = journalService.listAll(getUser("user1"));
        assertEquals(1, journals.size());
    

    @Test
    public void renderDocument() throws Exception 
        mockMvc.perform(get("/view/id", "1"));
    

    protected User getUser(String name) 
        Optional<User> user = userService.getUserByLoginName(name);
        if (!user.isPresent()) 
            fail("user1 doesn't exist");
        
        return user.get();
    


【问题讨论】:

能分享一下JournalServiceTest.java文件的代码吗,请注明行号: :187 请检查。我已经上传了整个 JournalServiceTest.java 的代码 【参考方案1】:

您已从数据库中获取对象,如下所示,

期刊杂志 = journalRepository.findOne(id);

类别类别 = journal.getCategory();

还有你用过的地方

category.getId()

澄清:当您从数据库中获取日志对象时,只有日志对象与代理类别对象一起获取,而不是实际的类别对象。因此,当您尝试使用日志对象获取类别时,它会尝试使用实际类别对象初始化代理类别对象,这需要调用 db。

但是由于日志对象可能与会话分离,所以它说没有会话。

解决办法:你有代理对象,解包代理对象的方法有很多

categoryProxyObj=entityManager.unwrap(SessionImplementor.class).getPersistenceContext().unproxy(categoryProxyObj); categoryProxyObj=((SessionImplementor)session).getPersistenceContext().unproxy(categoryProxyObj); Hibernate.initialize(categoryProxyObj); if (categoryProxyObj instanceof HibernateProxy) categoryProxyObj=((HibernateProxy)categoryProxyObj).getHibernateLazyInitializer().getImplementation();

你喜欢哪种方法,你可以使用。

或者,如果您不需要类别对象而只需要类别 ID,则在 Journal 中

使用

private Category category;

@OneToOne(fetch=FetchType.LAZY, optional=false)
public Category getCategory() 
    return this.category;

代替

@OneToOne(fetch=FetchType.LAZY, optional=false)
private Category category;

【讨论】:

以上是关于org.hibernate.LazyInitializationException: 无法初始化代理 - 没有 Session。对于测试用例 JUnit的主要内容,如果未能解决你的问题,请参考以下文章