gpt4 book ai didi

java - org.hibernate.AssertionFailure : collection was processed twice by flush()

转载 作者:行者123 更新时间:2023-12-02 06:44:04 24 4
gpt4 key购买 nike

我有个问题。我收到以下异常:

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。也许这是导致问题的原因。
最大的问题是我不能不断地重现它。错误时有发生。

我们在应用程序中使用 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>

我的 Controller 类中有一个方法 (initChildSelections())。它为登录用户选择所有 child 。

Java代码 Controller :


@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 映射:

家长

@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();
}
}
}

child

@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();
}
}
}

DAOS


@Name("parentDao")
@AutoCreate
public class parentDao extends AbstractDao<Parent> {
public ParentDao() {
super(Parent.class);
}
}


/**
* Default DAO object that provides common methods.
*/
public abstract class AbstractDao<T> extends AbstractNoEditDao<T> {
public AbstractDao(Class<T> entityClass) {
super(entityClass);
}

public void persist(T entity) {

entityManager.persist(entity);
}

public void persistAll(List<T> entities) {
for (T entity : entities) {
persist(entity);
}
}

public void delete(T entity) {
entityManager.remove(entity);
}
}

public abstract class AbstractNoEditDao<T> {
@In
protected EntityManager entityManager; // NOSONAR

@In
protected Session session; // NOSONAR

private final Class<T> entityClass;

public AbstractNoEditDao(Class<T> entityClass) {
this.entityClass = entityClass;
}

public void refresh(T entity) {
entityManager.refresh(entity);
}

@SuppressWarnings("unchecked")
||||EXCEPTION|||
public List<T> findAll() {
return entityManager.createQuery("select e from " + EntityUtil.getEntityName(entityClass) + " e")
.getResultList();
}
}

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

最佳答案

我认为您正在访问 Hibernate 的一个实例同时来自两个或多个线程的 session ,你不应该这样做......
我在 "deleting records on association tables" 上遇到了同样的问题与 nHibernate使用 C#它是由使用同一 session 的 2 个线程引起的 - 更多 SELECT同时查询(第二个 SELECT 在第一个在同一 session 中完成之前开始)

关于java - org.hibernate.AssertionFailure : collection was processed twice by flush(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18835715/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com