org.hibernate.AssertionFailure:集合由flush()处理两次

时间:2013-09-16 19:25:59

标签: java hibernate java-ee

我有问题。我得到以下例外:

ERROR [org.hibernate.AssertionFailure] (http-0.0.0.0-80-10) an assertion failure occured (this may indicate a bug in Hibernate, but is more likely due to unsafe use of the session)
org.hibernate.AssertionFailure: collection was processed twice by flush()
    at org.hibernate.engine.Collections.prepareCollectionForUpdate(Collections.java:225)
    at org.hibernate.engine.Collections.processReachableCollection(Collections.java:208)
    at org.hibernate.event.def.FlushVisitor.processCollection(FlushVisitor.java:60)
    at org.hibernate.event.def.AbstractVisitor.processValue(AbstractVisitor.java:124)
    at org.hibernate.event.def.AbstractVisitor.processValue(AbstractVisitor.java:84)
    at org.hibernate.event.def.AbstractVisitor.processEntityPropertyValues(AbstractVisitor.java:78)
    at org.hibernate.event.def.DefaultFlushEntityEventListener.onFlushEntity(DefaultFlushEntityEventListener.java:161)
    at org.hibernate.event.def.AbstractFlushingEventListener.flushEntities(AbstractFlushingEventListener.java:219)
    at org.hibernate.event.def.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:99)
    at org.hibernate.event.def.DefaultAutoFlushEventListener.onAutoFlush(DefaultAutoFlushEventListener.java:58)
    at org.hibernate.impl.SessionImpl.autoFlushIfRequired(SessionImpl.java:998)
    at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1143)
    at org.hibernate.impl.QueryImpl.list(QueryImpl.java:102)
    at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:94)
    at mypackage.findAll(DAOjava:36)

在此异常之后,Hibernate将删除数据库中关联表的记录。 我不明白为什么会这样?它只执行select语句。 在Stacktrace上,我看到AutoFlush。也许这会导致问题。 最大的问题是我无法不断重现它。错误不时出现。

我们在Application中使用EntityManager。使用findAll()方法,我们获得了在关联表上具有关系的单独的实体列表。

我在一个标签上有一个Richfaces建议框。我可以在此列表中添加和删除元素。

<rich:tab label="${messages['tab.chiled']}" name="childTab"
        rendered="#{parentsController.selectedParent.ParentStatus == 'READY'}" switchType="ajax" 
        actionListener="#{parentController.initParentSelections()}">
         <s:decorate template="tabchildinfo.xhtml">
            <ui:param name="selection" value="#{parentController.childeSelection}" />
            <ui:param name="allowEdit" value="#{s:hasRole('assignChildesToParent')}" />
        </s:decorate>
    </rich:tab>

建议框的标签代码。

     <h:panelGrid columns="2">

       <a4j:commandButton value="" alt="" styleClass="refreshButton rightSpacing" action="#{parentsController.refreshChildSelection()}" reRender="#{idPrefix}addElement, #{idPrefix}AssignedElementsTable"/>

        <s:decorate id="#{idPrefix}addElement" styleClass="selectionAddElement"
            template="/WEB-INF/templates/edit.xhtml" rendered="#{allowEdit}">

            <ui:param name="float" value="true" />
            <ui:define name="label">#{addLabel}:</ui:define>
            <h:inputText value="#{selection.addElementText}"
                id="#{idPrefix}addElementText"
                onclick="#{rich:component(idPrefix.concat('addElementTextSuggest'))}.callSuggestion(true);"
                styleClass="selectionAddText"
                alt="#{messages['selection.add.empty']}" />
            <rich:suggestionbox id="#{idPrefix}addElementTextSuggest"
                suggestionAction="#{selection.suggest}" var="element"
                for="#{idPrefix}addElementText" minChars="0"
                nothingLabel="#{messages['selection.noResult']}" width="600">

                <h:column width="80px">
                    <f:facet name="header">
                        <h:outputText value="${messages['child.product']}" />
                    </f:facet>
                    <h:outputText value="#{element.product.id}"
                        title="#{element.product.id}" />
                </h:column>
                <h:column width="200px">
                    <f:facet name="header">
                        <h:outputText value="${messages['child.version']}" />
                    </f:facet>
                    <h:outputText value="#{element.productVersion}"
                        title="#{element.productVersion}" />
                </h:column>
                <h:column rendered="#{selection.suggestSearchCounter > 0}">
                    <f:facet name="header">
                        <a4j:commandButton value="${messages['button.addAll']}" onclick="parentEntityChanged();"
                            action="#{selection.addSuggestSearchElements()}"
                            reRender="#{idPrefix}AssignedElementsTable,#{idPrefix}addElement" />
                    </f:facet>
                </h:column>

                <a4j:support event="onselect"
                    action="#{selection.addElement(element)}"
                    onsubmit="parentEntityChanged();"
                    reRender="#{idPrefix}AssignedElementsTable,#{idPrefix}addElement"
                    oncomplete="#{rich:element(idPrefix.concat('addElementText'))}.focus();" />
            </rich:suggestionbox>
        </s:decorate>
    </h:panelGrid> 

    <rich:dataTable value="#{selection.assignedElements}" var="element" id="#{idPrefix}AssignedElementsTable"
        reRender="#{idPrefix}AssignedElementsTableScroller" styleClass="topSpacing">

            <rich:column width="100px" sortExpression="#{element.product.id}">
                <f:facet name="header">
                    <h:outputText value="${messages['child.product']}" />
                </f:facet>
                <h:outputText value="#{element.product.id}" title="#{element.product.id}" />
            </rich:column>
            <rich:column  width="300px" sortExpression="#{child.version}">
                <f:facet name="header">
                    <h:outputText value="${messages['child.version']}" />
                </f:facet>
                <h:outputText value="#{element.productVersion}" title="#{element.productVersion}" />
            </rich:column>

        <rich:column rendered="#{allowEdit}">
            <a4j:commandLink action="#{selection.removeElement(element)}" title="${messages['button.remove']}"
                reRender="#{idPrefix}AssignedElementsTable" onclick="parentEntityChanged();"> 
                <img src="/root/resources/img/icons/Delete/Delete_16x16.gif"
                    alt="${messages['button.remove']}" />
            </a4j:commandLink>
        </rich:column>

        <f:facet name="footer">
            <rich:datascroller align="center" for="#{idPrefix}AssignedElementsTable" maxPages="20"
                id="#{idPrefix}AssignedElementsTableScroller" renderIfSinglePage="false" />
        </f:facet>
    </rich:dataTable>

我的控制器类中有一个方法(initChildSelections())。它为已登录用户选择所有子项。

Java代码控制器:

@Name("parentsController")
@Scope(ScopeType.PAGE)
@Restrict("#{s:hasRole('viewParents')}")
@Synchronized(timeout = 10000L)
public class ParentsController {
    private final Logger log = LoggerFactory.getLogger(ParentsController.class);

    @Out(required = false)
    private Parent selectedParent;

    @In
    private EntityManager entityManager; // NOSONAR

    @In
    private AuditLogEntryDao auditLogEntryDao;

    @In
    private ParentDao parentDao;

    private TableFilter<Parent> filter = new TableFilter<Parent>();

    private boolean entityChanged;
    private boolean loadFullHistory = false;

    private ChildSelection childSelection;
    private List<Child> allChilds;

    private ParentData editParentData;

    ...

    @Create
    public void init() {

        parents = parentDao.findVisibleForCurrentUser();

        filter.putRenderer("name", new TableRenderer<Parent>() {
            private ViewHelper viewHelper = ParentsController.this.viewHelper;

            @Override
            public String render(Parent parent) {
                return viewHelper.getName1(parent);
            }
        });
        filter.putRenderer("country", new TableRenderer<Parent>() {
            private ViewHelper viewHelper = ParentsController.this.viewHelper;

            @Override
            public String render(Parent parent) {
                return viewHelper.getCountry(parent);
            }
        });
        filter.putRenderer("salesOrg", new TableRenderer<Parent>() {
            private ViewHelper viewHelper = ParentsController.this.viewHelper;

            @Override
            public String render(Parent parent) {
                return viewHelper.getSalesOrganisationId(Parent) + " (" + viewHelper.getSalesOrganisationName(Parent)
                        + ")";
            }
        });

        if ("edit".equals(paramMode)) {
            for (Parent parent : parents) {
                if (parent.getSID().equals(paramSid)) {
                    edit(parent, paramTab);
                }
            }
        }
    }

    public void edit(Parent selectedParent) {
        edit(selectedParent, "detailsTab");
    }

    public void edit(Parent selectedParent, String selectedTab) {
        log.info("Parent selected: {}", selectedParent.getId());

        salesOrganisations = salesOrganisationDao.findAll();
        salesOffices = salesOfficeDao.findAll();

        entityManager.refresh(selectedParent);

        setSelectedTab(selectedTab);

        this.selectedParent = selectedParent;
        setEditData(this.selectedParent);
        entityChanged = false;
        childSelection = null;

        overwriteDateThreeMonths = DateUtils.addMonths(new Date(), 3); // NOSONAR
        overwriteDateCurrent = getSelectedParent().getManualContractOverwriteExpiresAt();

        responseXmlTree = viewHelper.getXmlRichTree(selectedParent.getParentXML().getResponseXML());
        requestXmlTree = viewHelper.getXmlRichTree(selectedParent.getParentXML().getRequestXML());
        refreshAuditLogEntries();

    }

    private ParentData setEditData(Parent selectedParent) {
        if (editParentData == null) {
            editParentData = new ParentData();
        }
        // Info Parent
        if (selectedParent.getOverwriteParent() != null) {
            editParentData.setName1(selectedParent.getOverwriteParent().getName1());
            editParentData.setName2(selectedParent.getOverwriteParent().getName2());
            editParentData.setName3(selectedParent.getOverwriteParent().getName3());
            editParentData.setName4(selectedParent.getOverwriteParent().getName4());
            editParentData.setStras(selectedParent.getOverwriteParent().getStras());
            editParentData.setPstlz(selectedParent.getOverwriteParent().getPstlz());
            editParentData.setOrt01(selectedParent.getOverwriteParent().getOrt01());
            editParentData.setLand1(selectedParent.getOverwriteParent().getLand1());
            editParentData.setRemarks(selectedParent.getOverwriteParent().getRemarks());
            editParentData.setSalesOffice(selectedParent.getOverwriteParent().getSalesOffice());
            editParentData.setSalesOrganisation(selectedParent.getOverwriteParent().getSalesOrganisation());
        }

        //Workflows
        editParentData.setIsReleaseParent(selectedParent.isIsReleaseParent());
        editParentData.setIsInhouseParent(selectedParent.isIsInhouseParent());
        editParentData.setIsFieldTestParent(selectedParent.isIsFieldTestParent());
        editParentData.setIsControlledReleaseParent(selectedParent.isIsControlledReleaseParent());

        //Contract Data
        editParentData.setManualContractOverwrite(selectedParent.getManualContractOverwrite());
        editParentData.setManualContractOverwriteExpiresAt(selectedParent.getManualContractOverwriteExpiresAt());
        editParentData.setManualContractOverwriteUserId(selectedParent.getManualContractOverwriteUserId());
        editParentData.setManualContractOverwriteRemark(selectedParent.getManualContractOverwriteRemark());
        editParentData.setAllowDistribution(selectedParent.getAllowDistribution());

        return editParentData;

    }

    private Parent fillEditData(ParentData editParentData) {
        // Info Parent
        if (selectedParent.getOverwriteParent() != null) {
            selectedParent.getOverwriteParent().setName1(editParentData.getName1());
            selectedParent.getOverwriteParent().setName2(editParentData.getName2());
            selectedParent.getOverwriteParent().setName3(editParentData.getName3());
            selectedParent.getOverwriteParent().setName4(editParentData.getName4());
            selectedParent.getOverwriteParent().setStras(editParentData.getStras());
            selectedParent.getOverwriteParent().setPstlz(editParentData.getPstlz());
            selectedParent.getOverwriteParent().setOrt01(editParentData.getOrt01());
            selectedParent.getOverwriteParent().setLand1(editParentData.getLand1());
            selectedParent.getOverwriteParent().setRemarks(editParentData.getRemarks());
            selectedParent.getOverwriteParent().setSalesOffice(editParentData.getSalesOffice());
            selectedParent.getOverwriteParent().setSalesOrganisation(editParentData.getSalesOrganisation());
        }

        //Workflows
        selectedParent.setIsReleaseParent(editParentData.getIsReleaseParent());
        selectedParent.setIsInhouseParent(editParentData.getIsInhouseParent());
        selectedParent.setIsFieldTestParent(editParentData.getIsFieldTestParent());
        selectedParent.setIsControlledReleaseParent(editParentData.getIsControlledReleaseParent());

        //Contract Data
        selectedParent.setManualContractOverwrite(editParentData.getManualContractOverwrite());
        selectedParent.setManualContractOverwriteExpiresAt(editParentData.getManualContractOverwriteExpiresAt());
        selectedParent.setManualContractOverwriteUserId(editParentData.getManualContractOverwriteUserId());
        selectedParent.setManualContractOverwriteRemark(editParentData.getManualContractOverwriteRemark());
        selectedParent.setAllowDistribution(editParentData.getAllowDistribution());

        return selectedParent;

    }

    public void initChildSelections() {
        if (childSelection == null) {
            if (allChilds == null) {
               ||||EXCEPTION |||| allChilds = childDao.findVisibleForCurrentUser();
            }
            entityManager.refresh(selectedParent);
            List<Template> templates = groupDao.findForCurrentUser();
            childSelection =
                    new ChildSelection(viewHelper, identity, user.getSalesOrganisations(), new ChildFilter(
                            selectedParent), templates);

            childSelection.init(selectedParent.getChilds(), allChilds);
        }

    }

    public void refreshChildSelection() {

        if (childSelection != null) {
            allChilds = childDao.findVisibleForCurrentUser();
            entityManager.refresh(selectedParent);

            List<Child> addedChilds = new ArrayList<Child>();
            for (Child pkg : childSelection.getAddedAssignedElements()) {
                if (!selectedParent.getChilds().contains(pkg)) {
                    addedChilds.add(pkg);
                }
            }

            List<Child> removedChilds = new ArrayList<Child>();
            for (Child pkg : childSelection.getRemovedAssignedElements()) {
                if (selectedParent.getChilds().contains(pkg)) {
                    removedChilds.add(pkg);
                }
            }

            childSelection.refresh(selectedParent.getChilds(), addedChilds, removedChilds, allChilds);
        }

    }

    @Restrict("#{s:hasRole('manageParents') or s:hasRole('assignChildsToParent')}")
    public void saveChanges() {
        // dummy change to always force update on parent
        if (entityChanged) {
            refreshChildSelection();

            if (childSelection != null) {
                selectedParent.getChilds().addAll(childSelection.getAddedAssignedElements());
                selectedParent.getChilds().removeAll(childSelection.getRemovedAssignedElements());
            }

            //Set info changes
            selectedParent = fillEditData(this.editParentData);

            selectedParent.setLastModifiedAt(new Date());
            try {
                parentDao.persist(selectedParent);
            } catch (InvalidStateException e) {
                for (InvalidValue invalidValue : e.getInvalidValues()) {
                    log.info("Instance of bean class: " + invalidValue.getBeanClass().getSimpleName()
                            + " has an invalid property: " + invalidValue.getPropertyName() + " with message: "
                            + invalidValue.getMessage());
                }
            }
        }
        entityChanged = false;
    }

    @Restrict("#{s:hasRole('manageParents') or s:hasRole('assignChildsToParent')}")
    public void reset() {
        if (allChilds != null) {
            childSelection.init(selectedParent.getChilds(), allChilds);
        }
        edit(this.selectedParent);
    }

    ....
}

@Name("parentsController") @Scope(ScopeType.PAGE) @Restrict("#{s:hasRole('viewParents')}") @Synchronized(timeout = 10000L) public class ParentsController { private final Logger log = LoggerFactory.getLogger(ParentsController.class); @Out(required = false) private Parent selectedParent; @In private EntityManager entityManager; // NOSONAR @In private AuditLogEntryDao auditLogEntryDao; @In private ParentDao parentDao; private TableFilter<Parent> filter = new TableFilter<Parent>(); private boolean entityChanged; private boolean loadFullHistory = false; private ChildSelection childSelection; private List<Child> allChilds; private ParentData editParentData; ... @Create public void init() { parents = parentDao.findVisibleForCurrentUser(); filter.putRenderer("name", new TableRenderer<Parent>() { private ViewHelper viewHelper = ParentsController.this.viewHelper; @Override public String render(Parent parent) { return viewHelper.getName1(parent); } }); filter.putRenderer("country", new TableRenderer<Parent>() { private ViewHelper viewHelper = ParentsController.this.viewHelper; @Override public String render(Parent parent) { return viewHelper.getCountry(parent); } }); filter.putRenderer("salesOrg", new TableRenderer<Parent>() { private ViewHelper viewHelper = ParentsController.this.viewHelper; @Override public String render(Parent parent) { return viewHelper.getSalesOrganisationId(Parent) + " (" + viewHelper.getSalesOrganisationName(Parent) + ")"; } }); if ("edit".equals(paramMode)) { for (Parent parent : parents) { if (parent.getSID().equals(paramSid)) { edit(parent, paramTab); } } } } public void edit(Parent selectedParent) { edit(selectedParent, "detailsTab"); } public void edit(Parent selectedParent, String selectedTab) { log.info("Parent selected: {}", selectedParent.getId()); salesOrganisations = salesOrganisationDao.findAll(); salesOffices = salesOfficeDao.findAll(); entityManager.refresh(selectedParent); setSelectedTab(selectedTab); this.selectedParent = selectedParent; setEditData(this.selectedParent); entityChanged = false; childSelection = null; overwriteDateThreeMonths = DateUtils.addMonths(new Date(), 3); // NOSONAR overwriteDateCurrent = getSelectedParent().getManualContractOverwriteExpiresAt(); responseXmlTree = viewHelper.getXmlRichTree(selectedParent.getParentXML().getResponseXML()); requestXmlTree = viewHelper.getXmlRichTree(selectedParent.getParentXML().getRequestXML()); refreshAuditLogEntries(); } private ParentData setEditData(Parent selectedParent) { if (editParentData == null) { editParentData = new ParentData(); } // Info Parent if (selectedParent.getOverwriteParent() != null) { editParentData.setName1(selectedParent.getOverwriteParent().getName1()); editParentData.setName2(selectedParent.getOverwriteParent().getName2()); editParentData.setName3(selectedParent.getOverwriteParent().getName3()); editParentData.setName4(selectedParent.getOverwriteParent().getName4()); editParentData.setStras(selectedParent.getOverwriteParent().getStras()); editParentData.setPstlz(selectedParent.getOverwriteParent().getPstlz()); editParentData.setOrt01(selectedParent.getOverwriteParent().getOrt01()); editParentData.setLand1(selectedParent.getOverwriteParent().getLand1()); editParentData.setRemarks(selectedParent.getOverwriteParent().getRemarks()); editParentData.setSalesOffice(selectedParent.getOverwriteParent().getSalesOffice()); editParentData.setSalesOrganisation(selectedParent.getOverwriteParent().getSalesOrganisation()); } //Workflows editParentData.setIsReleaseParent(selectedParent.isIsReleaseParent()); editParentData.setIsInhouseParent(selectedParent.isIsInhouseParent()); editParentData.setIsFieldTestParent(selectedParent.isIsFieldTestParent()); editParentData.setIsControlledReleaseParent(selectedParent.isIsControlledReleaseParent()); //Contract Data editParentData.setManualContractOverwrite(selectedParent.getManualContractOverwrite()); editParentData.setManualContractOverwriteExpiresAt(selectedParent.getManualContractOverwriteExpiresAt()); editParentData.setManualContractOverwriteUserId(selectedParent.getManualContractOverwriteUserId()); editParentData.setManualContractOverwriteRemark(selectedParent.getManualContractOverwriteRemark()); editParentData.setAllowDistribution(selectedParent.getAllowDistribution()); return editParentData; } private Parent fillEditData(ParentData editParentData) { // Info Parent if (selectedParent.getOverwriteParent() != null) { selectedParent.getOverwriteParent().setName1(editParentData.getName1()); selectedParent.getOverwriteParent().setName2(editParentData.getName2()); selectedParent.getOverwriteParent().setName3(editParentData.getName3()); selectedParent.getOverwriteParent().setName4(editParentData.getName4()); selectedParent.getOverwriteParent().setStras(editParentData.getStras()); selectedParent.getOverwriteParent().setPstlz(editParentData.getPstlz()); selectedParent.getOverwriteParent().setOrt01(editParentData.getOrt01()); selectedParent.getOverwriteParent().setLand1(editParentData.getLand1()); selectedParent.getOverwriteParent().setRemarks(editParentData.getRemarks()); selectedParent.getOverwriteParent().setSalesOffice(editParentData.getSalesOffice()); selectedParent.getOverwriteParent().setSalesOrganisation(editParentData.getSalesOrganisation()); } //Workflows selectedParent.setIsReleaseParent(editParentData.getIsReleaseParent()); selectedParent.setIsInhouseParent(editParentData.getIsInhouseParent()); selectedParent.setIsFieldTestParent(editParentData.getIsFieldTestParent()); selectedParent.setIsControlledReleaseParent(editParentData.getIsControlledReleaseParent()); //Contract Data selectedParent.setManualContractOverwrite(editParentData.getManualContractOverwrite()); selectedParent.setManualContractOverwriteExpiresAt(editParentData.getManualContractOverwriteExpiresAt()); selectedParent.setManualContractOverwriteUserId(editParentData.getManualContractOverwriteUserId()); selectedParent.setManualContractOverwriteRemark(editParentData.getManualContractOverwriteRemark()); selectedParent.setAllowDistribution(editParentData.getAllowDistribution()); return selectedParent; } public void initChildSelections() { if (childSelection == null) { if (allChilds == null) { ||||EXCEPTION |||| allChilds = childDao.findVisibleForCurrentUser(); } entityManager.refresh(selectedParent); List<Template> templates = groupDao.findForCurrentUser(); childSelection = new ChildSelection(viewHelper, identity, user.getSalesOrganisations(), new ChildFilter( selectedParent), templates); childSelection.init(selectedParent.getChilds(), allChilds); } } public void refreshChildSelection() { if (childSelection != null) { allChilds = childDao.findVisibleForCurrentUser(); entityManager.refresh(selectedParent); List<Child> addedChilds = new ArrayList<Child>(); for (Child pkg : childSelection.getAddedAssignedElements()) { if (!selectedParent.getChilds().contains(pkg)) { addedChilds.add(pkg); } } List<Child> removedChilds = new ArrayList<Child>(); for (Child pkg : childSelection.getRemovedAssignedElements()) { if (selectedParent.getChilds().contains(pkg)) { removedChilds.add(pkg); } } childSelection.refresh(selectedParent.getChilds(), addedChilds, removedChilds, allChilds); } } @Restrict("#{s:hasRole('manageParents') or s:hasRole('assignChildsToParent')}") public void saveChanges() { // dummy change to always force update on parent if (entityChanged) { refreshChildSelection(); if (childSelection != null) { selectedParent.getChilds().addAll(childSelection.getAddedAssignedElements()); selectedParent.getChilds().removeAll(childSelection.getRemovedAssignedElements()); } //Set info changes selectedParent = fillEditData(this.editParentData); selectedParent.setLastModifiedAt(new Date()); try { parentDao.persist(selectedParent); } catch (InvalidStateException e) { for (InvalidValue invalidValue : e.getInvalidValues()) { log.info("Instance of bean class: " + invalidValue.getBeanClass().getSimpleName() + " has an invalid property: " + invalidValue.getPropertyName() + " with message: " + invalidValue.getMessage()); } } } entityChanged = false; } @Restrict("#{s:hasRole('manageParents') or s:hasRole('assignChildsToParent')}") public void reset() { if (allChilds != null) { childSelection.init(selectedParent.getChilds(), allChilds); } edit(this.selectedParent); } .... }

Hibernate映射:

PARENT

@Entity
@Table(name = "PARENT")
public class Parent implements Serializable, EntityBase {
    private static final long serialVersionUID = 1L;

    private String id;
    private List<ChildInstallInfo> childInstallInfos;

    private ParentXML parentXML;

    private List<Child> childs;
    private List<Template> groups;

    private Date lastModifiedAt;


    @PrePersist
    @PreUpdate
    public void prePersist() {
        setLastModifiedAt(new Date());
    }

    @GenericGenerator(name = "generator", strategy = "SequenceGenerator", parameters = {
            @Parameter(name = "sequence", value = "PO_ID_SEQ"),
            @Parameter(name = "prefix", value = "PARENT_") })
    @Id
    @GeneratedValue(generator = "generator")
    @Column(name = "PARENT_ID", unique = true, nullable = false, length = ID_COL_LENGTH)
    @Length(max = ID_COL_LENGTH)
    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    .....

    @ManyToMany
    @JoinTable(name = "CHILD2PARENT", joinColumns = { @JoinColumn(name = "PARENT_ID") }, inverseJoinColumns = { @JoinColumn(name = "CHILD_ID") })
    public List<Child> getChilds() {
        return childs;
    }

    public void setChilds(List<Child> childs) {
        this.childs = childs;
    }

    @ManyToMany
    @JoinTable(name = "PARENT2TEMPLATE", joinColumns = { @JoinColumn(name = "PARENT_ID") }, inverseJoinColumns = { @JoinColumn(name = "TEMPLATE_ID") })
    public List<Template> getGroups() {
        return groups;
    }

    public void setGroups(List<Template> groups) {
        this.groups = groups;
    }


    @OneToMany(mappedBy = "parent", cascade = CascadeType.REMOVE, fetch = FetchType.LAZY)
    public List<ChildInstallInfo> getChildInstallInfo() {
        return childInstallInfos;
    }

    public void setChildInstallInfo(
            List<ChildInstallInfo> childInstallInfos) {
        this.childInstallInfos = childInstallInfos;
    }

    @OneToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    @PrimaryKeyJoinColumn
    public SapParentInfo getSapParentInfo() {
        return sapParentInfo;
    }

    // We will never set the SAP data.
    // It will be maintain in SAP only
    public void setOverwriteParent(OverwriteParentInfo overwriteParent) {
        this.overwriteParent = overwriteParent;
    }


    /**
     * Compares the entity with another object.
     * 
     * @return <code>true</code> if, and only if, the other object is of the
     *         same type and has the same ID (when the key is null, the equal
     *         check is delegated to the super class), <code>false</code>
     *         otherwise.
     */
    @Override
    public boolean equals(Object obj) {
        if (obj instanceof Parent) {
            Parent other = (Parent) obj;
            if (StringUtils.isEmpty(other.getId())
                    || StringUtils.isEmpty(getId())) {
                return super.equals(obj);
            } else {
                return getId().equals(other.getId());
            }
        } else {
            return false;
        }
    }

    /**
     * Generates a hash code based on the ID of the entity. Delegates to the
     * super class when no ID is set.
     * 
     * @return a hash code as described above.
     */
    @Override
    public int hashCode() {
        if (StringUtils.isEmpty(getId())) {
            return getId().hashCode();
        } else {
            return super.hashCode();
        }
    }
}

@Entity @Table(name = "PARENT") public class Parent implements Serializable, EntityBase { private static final long serialVersionUID = 1L; private String id; private List<ChildInstallInfo> childInstallInfos; private ParentXML parentXML; private List<Child> childs; private List<Template> groups; private Date lastModifiedAt; @PrePersist @PreUpdate public void prePersist() { setLastModifiedAt(new Date()); } @GenericGenerator(name = "generator", strategy = "SequenceGenerator", parameters = { @Parameter(name = "sequence", value = "PO_ID_SEQ"), @Parameter(name = "prefix", value = "PARENT_") }) @Id @GeneratedValue(generator = "generator") @Column(name = "PARENT_ID", unique = true, nullable = false, length = ID_COL_LENGTH) @Length(max = ID_COL_LENGTH) public String getId() { return id; } public void setId(String id) { this.id = id; } ..... @ManyToMany @JoinTable(name = "CHILD2PARENT", joinColumns = { @JoinColumn(name = "PARENT_ID") }, inverseJoinColumns = { @JoinColumn(name = "CHILD_ID") }) public List<Child> getChilds() { return childs; } public void setChilds(List<Child> childs) { this.childs = childs; } @ManyToMany @JoinTable(name = "PARENT2TEMPLATE", joinColumns = { @JoinColumn(name = "PARENT_ID") }, inverseJoinColumns = { @JoinColumn(name = "TEMPLATE_ID") }) public List<Template> getGroups() { return groups; } public void setGroups(List<Template> groups) { this.groups = groups; } @OneToMany(mappedBy = "parent", cascade = CascadeType.REMOVE, fetch = FetchType.LAZY) public List<ChildInstallInfo> getChildInstallInfo() { return childInstallInfos; } public void setChildInstallInfo( List<ChildInstallInfo> childInstallInfos) { this.childInstallInfos = childInstallInfos; } @OneToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL) @PrimaryKeyJoinColumn public SapParentInfo getSapParentInfo() { return sapParentInfo; } // We will never set the SAP data. // It will be maintain in SAP only public void setOverwriteParent(OverwriteParentInfo overwriteParent) { this.overwriteParent = overwriteParent; } /** * Compares the entity with another object. * * @return <code>true</code> if, and only if, the other object is of the * same type and has the same ID (when the key is null, the equal * check is delegated to the super class), <code>false</code> * otherwise. */ @Override public boolean equals(Object obj) { if (obj instanceof Parent) { Parent other = (Parent) obj; if (StringUtils.isEmpty(other.getId()) || StringUtils.isEmpty(getId())) { return super.equals(obj); } else { return getId().equals(other.getId()); } } else { return false; } } /** * Generates a hash code based on the ID of the entity. Delegates to the * super class when no ID is set. * * @return a hash code as described above. */ @Override public int hashCode() { if (StringUtils.isEmpty(getId())) { return getId().hashCode(); } else { return super.hashCode(); } } }

DAOS

@Entity
@Table(name = "CHILD")
public class Child implements Serializable, EntityBase {
    private static final String CHILD_ID_COL = "CHILD_ID";

    private static final long serialVersionUID = 1L;

    private String id;
    private List<Child2Phase> child2Phase;
    private List<Parent> parents;
    private List<SalesOrganisation> salesOrganizations;
    private List<ChildInstallInfo> installInfos;
    private Date lastModifiedAt;

    .....

    @PrePersist
    @PreUpdate
    public void prePersist() {
        setLastModifiedAt(new Date());
    }

    // -------------------------------- mappings
    // --------------------------------------------
    @GenericGenerator(name = "generator", strategy = "SequenceGenerator", parameters = {
            @Parameter(name = "sequence", value = "PO_ID_SEQ"),
            @Parameter(name = "prefix", value = "PKG_") })
    @Id
    @GeneratedValue(generator = "generator")
    @Column(name = CHILD_ID_COL, unique = true, nullable = false, length = ID_COL_LENGTH)
    @Length(max = ID_COL_LENGTH)
    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    ......

    @ManyToOne(fetch = FetchType.EAGER, optional = true)
    @JoinColumn(name = "PRODUCT_ID", nullable = true)
    public Product getProduct() {
        return product;
    }

    public void setProduct(Product product) {
        this.product = product;
    }

    ......

    @OneToMany(mappedBy = "pk.child", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    @OrderBy("pk.phase asc")
    public List<Child2Phase> getChild2Phase() {
        return child2Phase;
    }

    public void setChild2Phase(List<Child2Phase> child2Phase) {
        this.child2Phase = child2Phase;
    }

    @ManyToMany
    @JoinTable(name = "CHILD2PARENT", joinColumns = { @JoinColumn(name = CHILD_ID_COL) }, inverseJoinColumns = { @JoinColumn(name = "PARENT_ID") })
    public List<Parent> getParents() {
        return parents;
    }

    public void setParents(List<Parent> parents) {
        this.parents = parents;
    }

    @OneToMany(mappedBy = "child", cascade = CascadeType.REMOVE, fetch = FetchType.LAZY)
    public List<ChildInstallInfo> getInstallInfos() {
        return installInfos;
    }

    public void setInstallInfos(List<ChildInstallInfo> installInfos) {
        this.installInfos = installInfos;
    }

    @ManyToMany
    @JoinTable(name = "CHILD2VKORG", joinColumns = { @JoinColumn(name = CHILD_ID_COL) }, inverseJoinColumns = { @JoinColumn(name = "VKORG") })
    public List<SalesOrganisation> getSalesOrganizations() {
        return salesOrganizations;
    }

    public void setSalesOrganizations(List<SalesOrganisation> salesOrganizations) {
        this.salesOrganizations = salesOrganizations;
    }

    @Version
    @Column(name = "LAST_MODIFIED_AT", nullable = false)
    public Date getLastModifiedAt() {
        return DateUtil.copyDate(lastModifiedAt);
    }

    public void setLastModifiedAt(Date lastModifiedAt) {
        this.lastModifiedAt = DateUtil.copyDate(lastModifiedAt);
    }

    /**
     * Compares the entity with another object.
     * 
     * @return <code>true</code> if, and only if, the other object is of the
     *         same type and has the same ID (when the key is null, the equal
     *         check is delegated to the super class), <code>false</code>
     *         otherwise.
     */
    @Override
    public boolean equals(Object obj) {
        if (obj instanceof Child) {
            Child other = (Child) obj;
            if (StringUtils.isEmpty(other.getId())
                    || StringUtils.isEmpty(getId())) {
                return super.equals(obj);
            } else {
                return getId().equals(other.getId());
            }
        } else {
            return false;
        }
    }

    /**
     * Generates a hash code based on the ID of the entity. Delegates to the
     * super class when no ID is set.
     * 
     * @return a hash code as described above.
     */
    @Override
    public int hashCode() {
        if (StringUtils.isEmpty(getId())) {
            return getId().hashCode();
        } else {
            return super.hashCode();
        }
    }
}

@Entity @Table(name = "CHILD") public class Child implements Serializable, EntityBase { private static final String CHILD_ID_COL = "CHILD_ID"; private static final long serialVersionUID = 1L; private String id; private List<Child2Phase> child2Phase; private List<Parent> parents; private List<SalesOrganisation> salesOrganizations; private List<ChildInstallInfo> installInfos; private Date lastModifiedAt; ..... @PrePersist @PreUpdate public void prePersist() { setLastModifiedAt(new Date()); } // -------------------------------- mappings // -------------------------------------------- @GenericGenerator(name = "generator", strategy = "SequenceGenerator", parameters = { @Parameter(name = "sequence", value = "PO_ID_SEQ"), @Parameter(name = "prefix", value = "PKG_") }) @Id @GeneratedValue(generator = "generator") @Column(name = CHILD_ID_COL, unique = true, nullable = false, length = ID_COL_LENGTH) @Length(max = ID_COL_LENGTH) public String getId() { return id; } public void setId(String id) { this.id = id; } ...... @ManyToOne(fetch = FetchType.EAGER, optional = true) @JoinColumn(name = "PRODUCT_ID", nullable = true) public Product getProduct() { return product; } public void setProduct(Product product) { this.product = product; } ...... @OneToMany(mappedBy = "pk.child", cascade = CascadeType.ALL, fetch = FetchType.EAGER) @OrderBy("pk.phase asc") public List<Child2Phase> getChild2Phase() { return child2Phase; } public void setChild2Phase(List<Child2Phase> child2Phase) { this.child2Phase = child2Phase; } @ManyToMany @JoinTable(name = "CHILD2PARENT", joinColumns = { @JoinColumn(name = CHILD_ID_COL) }, inverseJoinColumns = { @JoinColumn(name = "PARENT_ID") }) public List<Parent> getParents() { return parents; } public void setParents(List<Parent> parents) { this.parents = parents; } @OneToMany(mappedBy = "child", cascade = CascadeType.REMOVE, fetch = FetchType.LAZY) public List<ChildInstallInfo> getInstallInfos() { return installInfos; } public void setInstallInfos(List<ChildInstallInfo> installInfos) { this.installInfos = installInfos; } @ManyToMany @JoinTable(name = "CHILD2VKORG", joinColumns = { @JoinColumn(name = CHILD_ID_COL) }, inverseJoinColumns = { @JoinColumn(name = "VKORG") }) public List<SalesOrganisation> getSalesOrganizations() { return salesOrganizations; } public void setSalesOrganizations(List<SalesOrganisation> salesOrganizations) { this.salesOrganizations = salesOrganizations; } @Version @Column(name = "LAST_MODIFIED_AT", nullable = false) public Date getLastModifiedAt() { return DateUtil.copyDate(lastModifiedAt); } public void setLastModifiedAt(Date lastModifiedAt) { this.lastModifiedAt = DateUtil.copyDate(lastModifiedAt); } /** * Compares the entity with another object. * * @return <code>true</code> if, and only if, the other object is of the * same type and has the same ID (when the key is null, the equal * check is delegated to the super class), <code>false</code> * otherwise. */ @Override public boolean equals(Object obj) { if (obj instanceof Child) { Child other = (Child) obj; if (StringUtils.isEmpty(other.getId()) || StringUtils.isEmpty(getId())) { return super.equals(obj); } else { return getId().equals(other.getId()); } } else { return false; } } /** * Generates a hash code based on the ID of the entity. Delegates to the * super class when no ID is set. * * @return a hash code as described above. */ @Override public int hashCode() { if (StringUtils.isEmpty(getId())) { return getId().hashCode(); } else { return super.hashCode(); } } }

我们使用:JBOSS 5 + Hibernate 3.3.0 + Richfaces 3.3.3 + JBOSS Seam 2.2.2

1 个答案:

答案 0 :(得分:1)

我认为你是同时从两个或多个线程访问Hibernate会话的一个实例,你不应该这样做...... "deleting records on association tables" nHibernate C#使用SELECT时遇到了同样的问题,这是由使用相同会话的2个主题引起的 - 在同一时间内更多SELECT个查询(第二个{{1}}在第一个完成同一会话之前就已开始了)