我有一个小型控制台应用程序,并且将spring-data-jpa与hibernate一起使用。我真的不知道在独立控制台应用程序中使用spring-data- jpa及其存储库时如何懒惰初始化集合。这是我的一些代码:
@Entity public class User { ... @OneToMany(cascade=CascadeType.ALL) @JoinColumn(name="USER_ORDER_ID") private Set<Order> orders = new HashSet<Order>(); ... }
资料库:
public interface UserRepository extends PagingAndSortingRepository<User, Long> { public ArrayList<User> findByFirstNameIgnoreCase(String firstName); }
服务展示:
@Service @Repository @Transactional public class UserServiceImpl implements UserService { @Autowired private UserRepository userRepository; public ArrayList<User> findByFirstNameIgnoreCase(String firstName) { ArrayList<User> users = new ArrayList<User>(); users = userRepository.findByFirstNameIgnoreCase(firstName); return users; }
我的主要方法:
... user = userRepository.findByFirstNameIgnoreCase("john").get(0); orders = user.getOrders(); for (Order order : orders) { LOGGER.info("getting orders: " + order.getId()); }
foreach循环获取异常:
EVERE:无法延迟初始化角色集合:com.aki.util.User.orders,未关闭任何会话或会话org.hibernate.LazyInitializationException:无法延迟初始化角色集合:
请注意,从带有某种OpenSessionInViewFilter的Web应用程序运行此程序时,我没有此问题。
一种解决方案是通过以下方式制作User.orders一个 热切的 收藏
User.orders
@OneToMany(cascade=CascadeType.ALL, fetch = FetchType.EAGER) private Set<Order> orders = new HashSet<Order>();
默认情况下,实体关联是延迟加载的。这意味着ordersSet实际上只是一个代理对象,除非您在其上调用方法,否则它不会被初始化。这很好,因为Order除非需要它们,否则不会加载关联的对象。但是,如果您尝试在运行的事务之外访问未初始化的集合,则可能会导致问题。
orders
Order
如果您知道在大多数情况下您将需要用户订单,那么使关联热切地获取是有意义的。否则,您将必须确保集合在事务内被初始化/加载。在OpenSessionInViewFilter你确定提到品牌,交易停留在请求处理过程中打开,这就是为什么你没有在YOUT的webapp这个问题。
OpenSessionInViewFilter
如果必须让它延迟加载,请尝试使用Spring TransactionTemplate将代码包装在您的main方法中:
TransactionTemplate
TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager); transactionTemplate.execute(new TransactionCallbackWithoutResult() { @Override protected void doInTransactionWithoutResult(TransactionStatus status) { ... } });