两天来,我试图让我的 JSF+Primefaces/JBoss AS 7.1/Hibernate 应用程序工作,我在LazyInitializationException
s 和Too many tables; MySQL can only use 61 tables in a join
错误之间来回跳动。
我将尝试尽可能正确地描述我当前的实体模型。
我有一台由几个模块组成的机器。每个模块基本上都是我的 Web 应用程序中的一个选项卡,在这个选项卡上,一个表单中有几个字段。问题在于下拉字段。对于那些,我从构建选项的drools系统外部获取可用选项,具体取决于其他模块中的其他字段。例如,可用的颜色取决于所选的表面材料,并相应地创建下拉菜单。
现在,由于 JSF/Primefaces 的限制,我需要将选定的下拉值保存为我的模块实体中的对象。请参阅Primefaces selectOneMenu 中的 CustomContent without persisting object和Disabling items with PrimeFaces SelectOneMenu with custom content / p:column了解我有/有的问题。
因此,对于每个 DropDown 字段,我@OneToOne
在模块实体类中都有一个关系:
@Entity
public class PressureModule {
@OneToOne(cascade = CascadeType.ALL)
private Machine machine;
@OneToOne(cascade = CascadeType.ALL)
private DropDownSelectItem type = DropDownSelectItem.getSelectOneItem();
@OneToOne(cascade = CascadeType.ALL)
private DropDownSelectItem pressureTop = DropDownSelectItem.getSelectOneItem();
@OneToOne(cascade = CascadeType.ALL)
private DropDownSelectItem color = DropDownSelectItem.getSelectOneItem();
// getters, setters
}
还有一个 DopDownSelectItem:
@Entity
public class DropDownSelectItem implements Serializable, Comparable<DropDownSelectItem> {
@Id
@GeneratedValue
private Long id;
@Column
private String label;
@Column
private String value;
@Column
private boolean disabled;
@Column
private String disabledReason;
}
Hibernate 自动创建以下表:
CREATE TABLE `dropdownselectitem` (
`id` bigint(20) NOT NULL,
`disabled` tinyint(1) default NULL,
`disabledReason` varchar(255) default NULL,
`label` varchar(255) default NULL,
`value` varchar(255) default NULL,
PRIMARY KEY (`id`),
) ENGINE=InnoDB DEFAULT CHARSET=latin1 ;
CREATE TABLE `pressuremodule` (
`id` bigint(20) NOT NULL,
`machine_id` bigint(20) default NULL,
`pressuretop_id` bigint(20) default NULL,
`color_id` bigint(20) default NULL,
`type_id` bigint(20) default NULL,
PRIMARY KEY (`id`),
CONSTRAINT `FK8E3D129AE7CE7BEF` FOREIGN KEY (`type_id`) REFERENCES `dropdownselectitem` (`id`),
CONSTRAINT `FK8E3D129ABD1E6ED1` FOREIGN KEY (`pressuretop_id`) REFERENCES `dropdownselectitem` (`id`),
CONSTRAINT `FK8E3D129ABD1EE330` FOREIGN KEY (`color_id`) REFERENCES `dropdownselectitem` (`id`),
CONSTRAINT `FK8E3D129AC56471E2` FOREIGN KEY (`machine_id`) REFERENCES `machine` (`id`),
) ENGINE=InnoDB DEFAULT CHARSET=latin1 ;
下拉列表中填充了以下逻辑:
在 .xhtml 中:
<p:selectOneMenu value="#{bean.field}" var="x">
<f:selectItems
value="#{dropDownValuesBean.getSelectItems()}" var="dd"
itemLabel="#{dd.label}" itemValue="#{dd}" />
<p:column>
<h:outputText value="#{x.label}" />
<h:outputText value=" {#{x.value}}" />
</p:column>
<p:ajax event="change" update="@form" />
</p:selectOneMenu>
和 DropDownValuesBean(缩短):
public List<PstSelectItem> getSelectItems(final String module, final String field) {
knowledgeBase = KnowledgeBaseFactory.newKnowledgeBase();
List<PstSelectItem> returnList;
StatefulKnowledgeSession statefulKnowledgeSession = knowledgeBase.newStatefulKnowledgeSession();
statefulKnowledgeSession.insert(sessionBean.getActiveMachine());
statefulKnowledgeSession.fireAllRules();
Collection<FactHandle> handles = statefulKnowledgeSession.getFactHandles(new ClassObjectFilter(DropDownSelectItem.class));
for (FactHandle handle : handles) {
DropDownSelectItem selectItem = (DropDownSelectItem) statefulKnowledgeSession.getObject(handle);
returnList.add(selectItem);
}
Collections.sort(returnList);
return returnList;
}
现在的问题是,如果我有很多下拉字段(我们谈论最多 150 个),则会发生以下异常:
javax.persistence.PersistenceException: org.hibernate.exception.GenericJDBCException: Too many tables; MySQL can only use 61 tables in a join
原因很清楚,我能理解这个问题。现在,如果我更改要使用的实体@OneToOne( fetch = FetchType.LAZY)
,我会遇到著名的LazyInitializationException
. 这并不奇怪。
当我为此搜索解决方案时,我主要参考OpenSessionInView
Spring 框架附带的过滤器。由于我不使用 Spring,并且由于我不打算引入该依赖项,所以我有点迷茫。
我已经尝试过以下事情:
@PersistenceContext(type = PersistenceContextType.EXTENDED)
在我的 DAO 中使用: https ://community.jboss.org/thread/177735- 仅在数据库中存储对选定的下拉值(仅选定的字符串而不是整个对象)的引用-失败是因为我无法从实体中的该字符串重新计算选定的值
DropDownSelectItem
,因为我无法将相应的 Drools 逻辑注入实体( s@Inject
中不支持 ing@Entity
) - 将序列化的 DropDownSelectItem 直接保存在数据库中,但这会导致巨大的数据库表(因为每个 DropDown-item 都保存在一个 blob 中)并且我无法使用简单的 SQL 获取所选值(需要用于报告目的)
环境:
- JBoss AS 7.1.0
- Primefaces 3.2
- MySQL 5.5
- JDK 6
有任何想法吗?如果需要有关配置或任何内容的更多信息,我很乐意提供这些信息!