【问题标题】:Hibernate failed to lazily initialize a collection of role no session in entity service even with @Transactional即使使用@Transactional,Hibernate 也无法在实体服务中延迟初始化角色集合,没有会话
【发布时间】:2016-07-03 02:54:11
【问题描述】:

我有一个休眠项目,它连接到两个数据源并有一个基础 dao。我也使用基础 dao 为数据源派生通用 daos。

我有一个获取连接关系的服务,当实体具有一对多关系时,我会遇到以下错误。我陷入了无法获得一对多关系对象的困境。

我使用 apache commons beanutils 来复制属性,希望它能进行深层复制,但它也不起作用。我的想法不多了。

我了解到我可以选择使用 Open Session In View,但我不知道该怎么做。

错误

failed to lazily initialize a collection of role: com.sony.spe.mc.domain.OperationalUnit.user, could not initialize proxy - no Session

我有以下层和文件

控制器层

    @ApiOperation(value = "read", nickname = "getByID")
    @RequestMapping(value="/read", method = RequestMethod.GET)
    @ApiImplicitParams({
        @ApiImplicitParam(name = "id", value = "User's id", required = true, dataType = "int", paramType = "query")
    })
    @ApiResponses(value = { 
            @ApiResponse(code = 200, message = "Success", response = User.class),
            @ApiResponse(code = 500, message = "Failure")})
    @ResponseBody
    public UserProxy getByID(long id) {
        UserProxy user;
        try {               
            user = userService.fetchUserById(id);
        }
        catch(Exception ex) {
            ex.printStackTrace();
            return null;
        }
        return user;
    }

服务层

用户服务

@Service
@Transactional("fuseTransactionManager")
public class UserServiceImpl extends BaseFuseServiceImpl<User> implements UserService {
    @Autowired
    UserDao userDao;

    @Override 
    protected UserDao getDao() {
        return userDao;
    }

    @Override
    public UserProxy fetchUserById(long id) {
        try {
/***** ERROR HAPPENS HERE. THE USER OBJECT IS NOT ABLE TO GET THE ONE TO MANY OBJECTS even though I have @Transactional *****/
            User user = userDao.fetchEntityById(User.class, id);
            UserProxy userProxy = new UserProxy();
            BeanUtils.copyProperties(userProxy, user);
            return userProxy;
        } catch(Exception ex) {
            ex.printStackTrace();
            return null;
        }
    }
.....

通用保险丝服务

@Service
public class BaseFuseServiceImpl<T extends Serializable> extends BaseServiceImpl<T> implements BaseFuseService<T> {
    @Autowired
    BaseFuseDao<T> baseFuseDao;

    @Override
    protected BaseFuseDao<T> getDao() {
        return baseFuseDao;
    }
}

特定服务实现的非常通用的服务

@Service
@Transactional("baseTransactionManager")
public abstract class BaseServiceImpl<T extends Serializable> implements BaseService<T> {
    protected abstract BaseDao<T> getDao();

    @Override
    public T fetchEntityById(Class<T> entityClass, long id) {
        return getDao().fetchEntityById(entityClass, id);
    }

用户实体。还有一个对应的代理对象,除了没有@Entity @Column 注释之外几乎完全相同。

@Entity
@Table(name="USER")
//@AttributeOverride(name = "ID", column = @Column(name = "USER_ID",  nullable = false))
public class User extends BaseEntity {
//public class User implements Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = 5236507646361562577L;

    @Id  
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "USER_ID")
    private long id;  

    @OneToMany(cascade=CascadeType.ALL)  
    @JoinTable(name="USER_OPERATIONALUNIT",  
        joinColumns = {@JoinColumn(name="USER_ID")},  
        inverseJoinColumns = {@JoinColumn(name="OPERATIONALUNIT_ID")}
    )  
    private Set<OperationalUnit> operationalUnit;
.... getters and setters

【问题讨论】:

  • 您的服务类上有一个@Transactional 注释,这很好。但是你真的确定事务管理设置正确并且事务实际上在它们应该开始的时候开始(例如在输入方法fetchUserById之前)?
  • 我不太确定。我应该采取哪些额外步骤来确保这一点?
  • 调试日志记录或调试。实际上,如果您闯入应该是事务性的方法,您会在堆栈框架中看到负责事务管理的类和方法。尝试在那里放置一个断点并再次运行它会发生什么。

标签: java spring hibernate annotations hibernate-onetomany


【解决方案1】:

为什么要在类中创建所有方法@Transactional。您可以在需要时使用@Transactional。对于最佳实践,请在方法上使用 @Transactional

所以在您的情况下,有两种解决方案:

1.通过热切地获取孩子:

您需要使用您的注释急切地传递 fetchType,即

@OneToMany(cascade=CascadeType.ALL,fetch=FetchType.EAGER)

2。通过使用@Transactional:

这里你需要在当前事务中初始化你的集合,即

public UserProxy fetchUserById(long id) {
        try {
            User user = userDao.fetchEntityById(User.class, id);
// Here you need to initialize collection using getter method after retrieving object
            user.getOperationalUnit().size();
//Now you will get childs with your parent entity
                UserProxy userProxy = new UserProxy();
                BeanUtils.copyProperties(userProxy, user);
                return userProxy;
            } catch(Exception ex) {
                ex.printStackTrace();
                return null;
            }
        }

更多详情@TransactionalRefer this link.

【讨论】:

  • 我也试过这个,但我得到了同样的错误。由于它是一对多关系,因此操作单元也有一组用户,我使用一对多注释来保存它们。我尝试进行初始化并获取大小,但操作单元导致延迟加载错误。我还尝试使用 Eager 进行获取,这会导致无限循环。
  • @Sakib JPA 中的关系始终是单向的,除非您在两个方向上将父级与子级关联起来。
猜你喜欢
  • 2017-08-13
  • 2016-06-04
  • 2018-11-21
  • 2014-12-23
  • 2017-01-30
  • 2020-03-18
  • 2022-07-08
  • 1970-01-01
  • 2015-04-01
相关资源
最近更新 更多