JPA之"could not initialize proxy - no Session"的异常解决

引言: 在使用JPA中经常会碰到各类问题,这里列出解决no Session问题的方法。

1.  异常信息的描述

   这里列出异常栈, 关键词是无法初始化proxy,在读取数据库的过程中.

org.hibernate.LazyInitializationException: could not initialize proxy - no Session
	at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:148)
	at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:266)
	at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:68)
	at com.rain.wx.meal.model.ShopCartOrder_$$_jvst9ff_3.toString(ShopCartOrder_$$_jvst9ff_3.java)
	at java.lang.String.valueOf(String.java:2982)
	at java.io.PrintStream.println(PrintStream.java:821)
	at com.rain.wx.meal.service.OrderServiceTest.testNewShopCartOrder(OrderServiceTest.java:26)
	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.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.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:252)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
	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:191)
	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)

2.  测试代码

   这里的测试代码如下:  

import javax.transaction.Transactional;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner;

import com.rain.wx.meal.dao.ShopCartOrderRepository;
import com.rain.wx.meal.model.ShopCartOrder;

@RunWith(SpringRunner.class)
@SpringBootTest
@ActiveProfiles("dev")
public class OrderServiceTest {
    @Autowired
    private ShopCartOrderRepository shopCartOrderRepo;
    
	@Test
	public void testNewShopCartOrder() {
		long shopCartOrderId = 5l;
		
		ShopCartOrder shopCartOrder = this.shopCartOrderRepo.getOne(shopCartOrderId);
		
		System.out.println(shopCartOrder);
	}
}
 ShopCartRepository的代码:

import java.util.List;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

import com.rain.wx.meal.model.ShopCartOrder;

@Repository
public interface ShopCartOrderRepository extends JpaRepository {
    public List getByUserId(long userId);
    
    /**
     * Query the current shop cart order.
     * 
     * @param userId
     * @param dishId
     * @return
     */
    @Query(value="from ShopCartOrder shopCartOrder where shopCartOrder.userId = :userId and shopCartOrder.mealDish.id = :dishId")
    public ShopCartOrder getByUserIdAndDishId(@Param("userId") long userId, @Param("dishId") long dishId);
}
 经过分析,可以发现findOne使用的是JpaRepository自带的方法findOne. 那问题出在哪来呢,因为自带的方法一般不会报错的。

3.  问题的解决

    鉴于数据库操作中一般会使用事务,是不是事务造成的呢?  添加@Transactional暂且一试。

import javax.transaction.Transactional;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner;

import com.rain.wx.meal.dao.ShopCartOrderRepository;
import com.rain.wx.meal.model.ShopCartOrder;

@RunWith(SpringRunner.class)
@SpringBootTest
@ActiveProfiles("dev")
public class OrderServiceTest {
    @Autowired
    private ShopCartOrderRepository shopCartOrderRepo;
    
	@Test
	@Transactional
	public void testNewShopCartOrder() {
		long shopCartOrderId = 5l;
		
		ShopCartOrder shopCartOrder = this.shopCartOrderRepo.getOne(shopCartOrderId);
		
		System.out.println(shopCartOrder);
	}
}
@Transactional主要在当下的数据库操作中,添加事务控制。

你可能感兴趣的:(问题分析,数据库,Java技术,Spring,Boot实战)