2

两天来,我试图让我的 JSF+Primefaces/JBoss AS 7.1/Hibernate 应用程序工作,我在LazyInitializationExceptions 和Too many tables; MySQL can only use 61 tables in a join错误之间来回跳动。

我将尝试尽可能正确地描述我当前的实体模型。

我有一台由几个模块组成的机器。每个模块基本上都是我的 Web 应用程序中的一个选项卡,在这个选项卡上,一个表单中有几个字段。问题在于下拉字段。对于那些,我从构建选项的drools系统外部获取可用选项,具体取决于其他模块中的其他字段。例如,可用的颜色取决于所选的表面材料,并相应地创建下拉菜单。

现在,由于 JSF/Primefaces 的限制,我需要将选定的下拉值保存为我的模块实体中的对象。请参阅Primefaces selectOneMenu 中的 CustomContent without persisting objectDisabling 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. 这并不奇怪。

当我为此搜索解决方案时,我主要参考OpenSessionInViewSpring 框架附带的过滤器。由于我不使用 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

有任何想法吗?如果需要有关配置或任何内容的更多信息,我很乐意提供这些信息!

4

0 回答 0