我正在尝试使用Vaadin和JPA Persistence层进行简单的概念验证。
我有一个与@OneToMany关系的Bean与fetchType = Lazy以及当我尝试使用我的DAO将这个bean的集合添加到表中时。我有下一个例外:
Caused by: org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: common.domain.Bill.detail, no session or session was closed
有没有办法在没有JPAContainer的情况下使用Vaadin和JPA?
感谢。
答案 0 :(得分:0)
您可以使用Bean(项目)容器并在那里添加您的实体。
如果您只是使用容器,则不会像使用JPAContainer那样延迟加载。
使用容器的组件仍然从容器中进行延迟加载,但所有对象都保存在容器中。 然后,容器的延迟加载必须由您自己完成。
有关Bean(Item)容器和容器的更多信息here。
答案 1 :(得分:0)
我正在使用来自lazyquerycontainer插件的EntityContainer类。顾名思义,它支持延迟加载。它只是工作:))
一些示例代码:
resultsTable = new Table();
resultsTable.setSelectable(true);
resultsTable.setCaption("JpaQuery");
resultsTable.setPageLength(40);
resultsTable.setImmediate(true);
resultsTable.setEditable(false);
resultsTable.setWriteThrough(true);
container = new EntityContainer<Call>(em, false, true, true, Call.class, 100, new Object[] {"imsi"}, new boolean[] {true});
container.addContainerProperty(LazyQueryView.PROPERTY_ID_ITEM_STATUS, QueryItemStatus.class, QueryItemStatus.None, true, false);
container.addContainerProperty("startTime", Date.class, null, true, true);
container.addContainerProperty("stopTime", Date.class, null, true, true);
container.addContainerProperty("imsi", String.class, null, false, true);
container.addContainerProperty("imei", String.class, null, false, true);
container.addContainerProperty("callType", Integer.class, null, true, true);
container.addContainerProperty("cdpn", String.class, null, true, true);
container.addContainerProperty("cgpn", String.class, null, true, true);
container.addContainerProperty("status", Integer.class, null, true, true);
container.addContainerProperty("mmRelCause", Integer.class, null, true, true);
container.addContainerProperty("rrRelCause", Integer.class, null, true, true);
resultsTable.setContainerDataSource(container);
resultsTable.setVisibleColumns(new String[] {"startTime" , "stopTime" , "imsi", "imei", "callType" , "cdpn", "cgpn", "status", "mmRelCause" , "rrRelCause" });
resultsTable.setColumnHeaders(new String[] {"Start time", "Stop time", "IMSI", "IMEI", "Call Type", "CDPN", "CGPN", "Status", "MM Release Cause", "RR Release Cause"});
resultsTable.setColumnCollapsingAllowed(true);
resultsTable.setColumnCollapsed("mmRelCause", true);
resultsTable.setColumnCollapsed("rrRelCause", true);
要过滤基于JQL的数据,您可以执行filter
方法传递过滤器字符串和绑定变量映射。
...
whereParameters.put("stopTimeFrom", filterParams.getStopTimeFrom());
where = "e.startTime >= :stopTimeFrom";
...
container.filter(where, whereParameters);
如果您首选Criteria API,则可以使用criteriacontainer。
答案 2 :(得分:0)
这是一个老帖子,但......
让我们看看你的用例:
- 您的浏览器请求您的申请
- 在您的服务器端代码中,您使用EntityManager加载bean(您的bean在会话中),但其关系实例(它是惰性的)是proxy =&gt;只有在您第一次访问关系实例时才会加载关系实例
- 您的浏览器收到回复
- 您单击一个按钮(例如),它向服务器发送请求
- 你试图添加/改变一些懒惰的关系
- 由于代理没有会话(它是使用上一个会话创建的,但现在它不再与会话相关联),它会引发异常
您可以尝试以下解决方案之一:
1-尝试在添加/更改惰性关系之前合并您的bean(将bean附加到当前会话):bean = em.merge(bean);
2-第一次加载实体时,尝试强制加载惰性关系:bean.getMyLazyRelationship();
3-在修改实体之前再次加载实体
4-将LAZY改为EAGER,但它(通常)不是一个好的解决方案
使用容器可能或可能不会解决此问题。
希望有所帮助