Markus, Greg,
In this particular case, the code starts with
Object o = em.find(javaType, id);
So merge is not needed at all.
thanks,
-marina
Markus Fuchs wrote:
> Hi Greg,
>
> I can't see, why you should get a foreign key violation removing an
> ArticlePlacement, since ArticlePlacement owns the the relationships to
> Article and ArticleGroup. To only other relationship is a
> uni-directional OneToMany between Article and ArticleGroup. But neither
> Articles nor ArticleGroups are removed, correct?
>
> BTW, in
>
>> utx.begin();
>> em.merge(o);
>> em.joinTransaction();
>> em.remove(o);
>> utx.commit();
>>
> you should call the remove operation on the managed copy returned by
> em.merge(o)
>
> Thanks,
>
> -- markus.
>
>> Where javaType is com.acadept.model.article.ArticlePlacement.
>>
>> Greg Ederer wrote:
>>
>>> Markus Fuchs wrote:
>>>
>>>> Hi Greg,
>>>>
>>>> That sounds like a bug to me. Could you send me your pojos and a
>>>> small snipplet of your application code as a test case?
>>>>
>>>> You are talking about em.remove(article) and no @PreRemove in
>>>> ArticlePlacement resulting in a foreign key violation, correct?
>>>>
>>> Actually, I get the fk violation when I em.remove(articlePlacement)
>>> w/o the @PreRemove. Does this still sound like a bug, or is it just
>>> my incorrect way of doing things?
>>>
>>> Code below.
>>>
>>> Cheers,
>>>
>>> Greg
>>>
>>> In my servlet:
>>>
>>> Object o = em.find(javaType, id);
>>> responseMap.put("javaType", javaType);
>>> responseMap.put("id", id);
>>> utx.begin();
>>> em.merge(o);
>>> em.joinTransaction();
>>> em.remove(o);
>>> utx.commit();
>>>
>>>
>>> /*
>>> * Article.java
>>> *
>>> * Created on May 7, 2007, 2:15 PM
>>> *
>>> * To change this template, choose Tools | Template Manager
>>> * and open the template in the editor.
>>> */
>>>
>>> package com.acadept.model.article;
>>>
>>> import com.acadept.model.*;
>>> import java.io.Serializable;
>>> import java.util.ArrayList;
>>> import java.util.Date;
>>> import java.util.List;
>>> import javax.persistence.CascadeType;
>>> import javax.persistence.Column;
>>> import javax.persistence.Entity;
>>> import javax.persistence.GeneratedValue;
>>> import javax.persistence.GenerationType;
>>> import javax.persistence.Id;
>>> import javax.persistence.ManyToOne;
>>> import javax.persistence.OneToMany;
>>> import javax.persistence.OneToOne;
>>> import javax.persistence.PreRemove;
>>> import javax.persistence.SequenceGenerator;
>>> import javax.persistence.Temporal;
>>> import javax.persistence.TemporalType;
>>>
>>> /**
>>> * Entity class Article
>>> * * @author gregederer
>>> */
>>> @Entity
>>> public class Article implements Serializable
>>> {
>>> @Id
>>> @GeneratedValue(strategy = GenerationType.SEQUENCE, generator =
>>> "ARTICLE_SEQ_GENERATOR")
>>> @SequenceGenerator(name = "ARTICLE_SEQ_GENERATOR", sequenceName =
>>> "ARTICLE_ID_SEQ")
>>> private Long id;
>>>
>>> @ManyToOne
>>> private ArticleCategory articleCategory;
>>>
>>> @OneToMany(mappedBy = "article", cascade=CascadeType.ALL)
>>> private List<ArticlePlacement> articlePlacements = new
>>> ArrayList<ArticlePlacement>();
>>>
>>> @Column(name="lead_in_image")
>>> private String leadInImage;
>>>
>>> private String title;
>>>
>>> private String subTitle;
>>>
>>> @Column(name="lead_in", columnDefinition="text")
>>> private String leadIn;
>>>
>>> @Column(columnDefinition="text")
>>> private String body;
>>>
>>> @OneToOne
>>> private AppUser poster;
>>>
>>> @Column(name="publication_date")
>>> @Temporal(TemporalType.DATE)
>>> private Date createdDate;
>>>
>>> /** Creates a new instance of Article */
>>> public Article()
>>> {
>>> }
>>>
>>> /**
>>> * Gets the id of this Article.
>>> * @return the id
>>> */
>>> public Long getId()
>>> {
>>> return this.id;
>>> }
>>>
>>> /**
>>> * Sets the id of this Article to the specified value.
>>> * @param id the new id
>>> */
>>> public void setId(Long id)
>>> {
>>> this.id = id;
>>> }
>>>
>>> /**
>>> * Returns a hash code value for the object. This implementation
>>> computes * a hash code value based on the id fields in this object.
>>> * @return a hash code value for this object.
>>> */
>>> @Override
>>> public int hashCode()
>>> {
>>> int hash = 0;
>>> hash += (this.getId() != null ? this.getId().hashCode() : 0);
>>> return hash;
>>> }
>>>
>>> /**
>>> * Determines whether another object is equal to this Article. The
>>> result is * <code>true</code> if and only if the argument is not
>>> null and is a Article object that * has the same id field values as
>>> this object.
>>> * @param object the reference object with which to compare
>>> * @return <code>true</code> if this object is the same as the
>>> argument;
>>> * <code>false</code> otherwise.
>>> */
>>> @Override
>>> public boolean equals(Object object)
>>> {
>>> // TODO: Warning - this method won't work in the case the id
>>> fields are not set
>>> if (!(object instanceof Article)) {
>>> return false;
>>> }
>>> Article other = (Article)object;
>>> // If both are the same object, return true
>>> if(this == other)
>>> {
>>> return true;
>>> }
>>> // If both objects have ids, compare their ids
>>> if(this.getId() != null && other.getId() != null)
>>> {
>>> // If their ids are equal, return true
>>> if(this.getId().equals(other.getId()))
>>> {
>>> return true;
>>> }
>>> // Otherwise, return false
>>> else
>>> {
>>> return false;
>>> }
>>> }
>>> // If one or both do not have ids, compare their 'natural keys'
>>> if(this.getTitle() != null &&
>>> this.getTitle().equals(other.getTitle())
>>> && this.getCreatedDate() != null &&
>>> this.getCreatedDate().equals(other.getCreatedDate())
>>> && this.getPoster() != null &&
>>> this.getPoster().equals(other.getPoster())
>>> )
>>> {
>>> return true;
>>> }
>>> return false;
>>> }
>>>
>>> /**
>>> * Returns a string representation of the object. This
>>> implementation constructs * that representation based on the id
>>> fields.
>>> * @return a string representation of the object.
>>> */
>>> @Override
>>> public String toString()
>>> {
>>> return "com.acadept.model.Article[id=" + getId() + "]";
>>> }
>>>
>>> public ArticleCategory getArticleCategory()
>>> {
>>> return articleCategory;
>>> }
>>>
>>> public void setArticleCategory(ArticleCategory articleCategory)
>>> {
>>> this.articleCategory = articleCategory;
>>> articleCategory.addArticle(this);
>>> }
>>>
>>> public String getTitle()
>>> {
>>> return title;
>>> }
>>>
>>> public void setTitle(String title)
>>> {
>>> this.title = title;
>>> }
>>>
>>> public String getSubTitle()
>>> {
>>> return subTitle;
>>> }
>>>
>>> public void setSubTitle(String subTitle)
>>> {
>>> this.subTitle = subTitle;
>>> }
>>>
>>> public String getLeadIn()
>>> {
>>> return leadIn;
>>> }
>>>
>>> public void setLeadIn(String leadIn)
>>> {
>>> this.leadIn = leadIn;
>>> }
>>>
>>> public String getBody()
>>> {
>>> return body;
>>> }
>>>
>>> public void setBody(String body)
>>> {
>>> this.body = body;
>>> }
>>>
>>> public AppUser getPoster()
>>> {
>>> return poster;
>>> }
>>>
>>> public void setPoster(AppUser poster)
>>> {
>>> this.poster = poster;
>>> }
>>>
>>> public Date getCreatedDate()
>>> {
>>> return createdDate;
>>> }
>>>
>>> public void setCreatedDate(Date createdDate)
>>> {
>>> this.createdDate = createdDate;
>>> }
>>>
>>> public String getLeadInImage()
>>> {
>>> return leadInImage;
>>> }
>>>
>>> public void setLeadInImage(String leadInImage)
>>> {
>>> this.leadInImage = leadInImage;
>>> }
>>>
>>> public List<ArticlePlacement> getArticlePlacements()
>>> {
>>> return articlePlacements;
>>> }
>>>
>>> public void setArticlePlacements(List<ArticlePlacement>
>>> articlePlacements)
>>> {
>>> this.articlePlacements = articlePlacements;
>>> }
>>>
>>> public void addArticlePlacement(ArticlePlacement articlePlacement)
>>> {
>>> if(this.getArticlePlacements().contains(articlePlacement))
>>> {
>>> return;
>>> }
>>> getArticlePlacements().add(articlePlacement);
>>> articlePlacement.setArticle(this);
>>> }
>>>
>>> public void removeArticlePlacement(ArticlePlacement articlePlacement)
>>> {
>>> getArticlePlacements().remove(articlePlacement);
>>> articlePlacement.setArticle(null);
>>> }
>>>
>>> @PreRemove
>>> public void beforeRemove()
>>> {
>>> List<ArticlePlacement> articlePlacements = getArticlePlacements();
>>> for(ArticlePlacement ap : articlePlacements)
>>> {
>>> ap.setArticle(null);
>>> }
>>> }
>>> }
>>>
>>>
>>> /*
>>> * ArticlePlacement.java
>>> *
>>> * Created on May 7, 2007, 2:32 PM
>>> *
>>> * To change this template, choose Tools | Template Manager
>>> * and open the template in the editor.
>>> */
>>>
>>> package com.acadept.model.article;
>>>
>>> import java.io.Serializable;
>>> import java.util.Date;
>>> import javax.persistence.Column;
>>> import javax.persistence.Entity;
>>> import javax.persistence.GeneratedValue;
>>> import javax.persistence.GenerationType;
>>> import javax.persistence.Id;
>>> import javax.persistence.ManyToOne;
>>> import javax.persistence.PreRemove;
>>> import javax.persistence.SequenceGenerator;
>>> import javax.persistence.Table;
>>> import javax.persistence.Temporal;
>>> import javax.persistence.TemporalType;
>>>
>>> /**
>>> * Entity class ArticlePlacement
>>> *
>>> * @author gregederer
>>> */
>>> @Entity
>>> @Table(name="article_placement")
>>> public class ArticlePlacement implements Serializable
>>> {
>>> @Id
>>> @GeneratedValue(strategy = GenerationType.SEQUENCE, generator =
>>> "ARTICLE_PLACEMENT_SEQ_GENERATOR")
>>> @SequenceGenerator(name = "ARTICLE_PLACEMENT_SEQ_GENERATOR",
>>> sequenceName = "ARTICLE_PLACEMENT_ID_SEQ")
>>> private Long id;
>>>
>>> @ManyToOne
>>> private Article article;
>>>
>>> @ManyToOne
>>> private ArticleGroup articleGroup;
>>>
>>> @Temporal(value = TemporalType.TIMESTAMP)
>>> @Column(name="order_position")
>>> private Date position;
>>>
>>> @Temporal(TemporalType.TIMESTAMP)
>>> private Date startRunDate;
>>>
>>> @Temporal(TemporalType.TIMESTAMP)
>>> private Date endRunDate;
>>>
>>> /** Creates a new instance of ArticlePlacement */
>>> public ArticlePlacement()
>>> {
>>> }
>>>
>>> /**
>>> * Gets the id of this ArticlePlacement.
>>> * @return the id
>>> */
>>> public Long getId()
>>> {
>>> return this.id;
>>> }
>>>
>>> /**
>>> * Sets the id of this ArticlePlacement to the specified value.
>>> * @param id the new id
>>> */
>>> public void setId(Long id)
>>> {
>>> this.id = id;
>>> }
>>>
>>> /**
>>> * Returns a hash code value for the object. This implementation
>>> computes
>>> * a hash code value based on the id fields in this object.
>>> * @return a hash code value for this object.
>>> */
>>> @Override
>>> public int hashCode()
>>> {
>>> int hash = 0;
>>> hash += (this.getId() != null ? this.getId().hashCode() : 0);
>>> return hash;
>>> }
>>>
>>> /**
>>> * Determines whether another object is equal to this
>>> ArticlePlacement. The result is
>>> * <code>true</code> if and only if the argument is not null and is
>>> a ArticlePlacement object that
>>> * has the same id field values as this object.
>>> * @param object the reference object with which to compare
>>> * @return <code>true</code> if this object is the same as the
>>> argument;
>>> * <code>false</code> otherwise.
>>> */
>>> @Override
>>> public boolean equals(Object object)
>>> {
>>> if (!(object instanceof ArticlePlacement))
>>> {
>>> return false;
>>> }
>>> ArticlePlacement other = (ArticlePlacement)object;
>>> // If both are the same object, return true
>>> if(this == other)
>>> {
>>> return true;
>>> }
>>> // If both objects have ids, compare their ids
>>> if(this.getId() != null && other.getId() != null)
>>> {
>>> // If their ids are equal, return true
>>> if(this.getId().equals(other.getId()))
>>> {
>>> return true;
>>> }
>>> // Otherwise, return false
>>> else
>>> {
>>> return false;
>>> }
>>> }
>>> // If one or both do not have ids, compare their 'natural keys'
>>> if(this.getArticle() != null &&
>>> this.getArticle().equals(other.getArticle())
>>> && this.getArticleGroup() != null &&
>>> this.getArticleGroup().equals(other.getArticleGroup())
>>> )
>>> {
>>> return true;
>>> }
>>> return false;
>>> }
>>>
>>> /**
>>> * Returns a string representation of the object. This
>>> implementation constructs
>>> * that representation based on the id fields.
>>> * @return a string representation of the object.
>>> */
>>> @Override
>>> public String toString()
>>> {
>>> return "com.acadept.model.ArticlePlacement[id=" + getId() + "]";
>>> }
>>>
>>> public Article getArticle()
>>> {
>>> return article;
>>> }
>>>
>>> public void setArticle(Article article)
>>> {
>>> this.article = article;
>>> if(article != null)
>>> {
>>> article.addArticlePlacement(this);
>>> }
>>> }
>>>
>>> public ArticleGroup getArticleGroup()
>>> {
>>> return articleGroup;
>>> }
>>>
>>> public void setArticleGroup(ArticleGroup articleGroup)
>>> {
>>> this.articleGroup = articleGroup;
>>> if(articleGroup != null)
>>> {
>>> articleGroup.addArticlePlacement(this);
>>> }
>>> }
>>>
>>> public Date getPosition()
>>> {
>>> return position;
>>> }
>>>
>>> public void setPosition(Date position)
>>> {
>>> this.position = position;
>>> }
>>>
>>> public Date getStartRunDate()
>>> {
>>> return startRunDate;
>>> }
>>>
>>> public void setStartRunDate(Date startRunDate)
>>> {
>>> this.startRunDate = startRunDate;
>>> }
>>>
>>> public Date getEndRunDate()
>>> {
>>> return endRunDate;
>>> }
>>>
>>> public void setEndRunDate(Date endRunDate)
>>> {
>>> this.endRunDate = endRunDate;
>>> }
>>>
>>> @PreRemove
>>> public void beforeRemove()
>>> {
>>> getArticleGroup().removeArticlePlacement(this);
>>> if(getArticle() != null)
>>> {
>>> getArticle().removeArticlePlacement(this);
>>> }
>>> }
>>> }
>>>
>>>
>>> /*
>>> * ArticleGroup.java
>>> *
>>> * Created on May 7, 2007, 2:27 PM
>>> *
>>> * To change this template, choose Tools | Template Manager
>>> * and open the template in the editor.
>>> */
>>>
>>> package com.acadept.model.article;
>>>
>>> import com.acadept.model.*;
>>> import java.io.Serializable;
>>> import java.util.ArrayList;
>>> import java.util.List;
>>> import java.util.logging.Logger;
>>> import javax.persistence.CascadeType;
>>> import javax.persistence.Column;
>>> import javax.persistence.Entity;
>>> import javax.persistence.GeneratedValue;
>>> import javax.persistence.GenerationType;
>>> import javax.persistence.Id;
>>> import javax.persistence.OneToMany;
>>> import javax.persistence.OrderBy;
>>> import javax.persistence.SequenceGenerator;
>>> import javax.persistence.Table;
>>>
>>> /**
>>> * Entity class ArticleGroup
>>> * * @author gregederer
>>> */
>>> @Entity
>>> @Table(name="article_group")
>>> public class ArticleGroup implements Serializable
>>> {
>>> private static Logger logger =
>>> Logger.getLogger(ContentGroup.class.getName());
>>>
>>> @Id
>>> @GeneratedValue(strategy = GenerationType.SEQUENCE, generator =
>>> "ARTICLE_GROUP_SEQ_GENERATOR")
>>> @SequenceGenerator(name = "ARTICLE_GROUP_SEQ_GENERATOR",
>>> sequenceName = "ARTICLE_GROUP_ID_SEQ")
>>> private Long id;
>>>
>>> @Column(name="content_name", unique=true)
>>> private String name;
>>>
>>> @Column(columnDefinition="text")
>>> private String description;
>>>
>>> @OneToMany(cascade=CascadeType.ALL)
>>> @OrderBy("position ASC")
>>> private List<ArticlePlacement> articlePlacements = new
>>> ArrayList<ArticlePlacement>();
>>>
>>> /**
>>> * Gets the id of this ArticleGroup.
>>> * @return the id
>>> */
>>> public Long getId()
>>> {
>>> return this.id;
>>> }
>>>
>>> /**
>>> * Sets the id of this ArticleGroup to the specified value.
>>> * @param id the new id
>>> */
>>> public void setId(Long id)
>>> {
>>> this.id = id;
>>> }
>>>
>>> /**
>>> * Returns a hash code value for the object. This implementation
>>> computes * a hash code value based on the id fields in this object.
>>> * @return a hash code value for this object.
>>> */
>>> @Override
>>> public int hashCode()
>>> {
>>> int hash = 0;
>>> hash += (this.getId() != null ? this.getId().hashCode() : 0);
>>> return hash;
>>> }
>>>
>>> /**
>>> * Determines whether another object is equal to this ArticleGroup.
>>> The result is * <code>true</code> if and only if the argument is
>>> not null and is a ArticleGroup object that * has the same id field
>>> values as this object.
>>> * @param object the reference object with which to compare
>>> * @return <code>true</code> if this object is the same as the
>>> argument;
>>> * <code>false</code> otherwise.
>>> */
>>> @Override
>>> public boolean equals(Object object)
>>> {
>>> // TODO: Warning - this method won't work in the case the id
>>> fields are not set
>>> if (!(object instanceof ArticleGroup)) {
>>> return false;
>>> }
>>> ArticleGroup other = (ArticleGroup)object;
>>> // If both are the same object, return true
>>> if(this == other)
>>> {
>>> return true;
>>> }
>>> // If both objects have ids, compare their ids
>>> if(this.getId() != null && other.getId() != null)
>>> {
>>> // If their ids are equal, return true
>>> if(this.getId().equals(other.getId()))
>>> {
>>> return true;
>>> }
>>> // Otherwise, return false
>>> else
>>> {
>>> return false;
>>> }
>>> }
>>> // If one or both do not have ids, compare their 'natural keys'
>>> if(this.getName() != null && this.getName().equals(other.getName())
>>> )
>>> {
>>> return true;
>>> }
>>> return false;
>>> }
>>>
>>> /**
>>> * Returns a string representation of the object. This
>>> implementation constructs * that representation based on the id
>>> fields.
>>> * @return a string representation of the object.
>>> */
>>> @Override
>>> public String toString()
>>> {
>>> return "com.acadept.model.ArticleGroup[id=" + getId() + "]";
>>> }
>>>
>>> public static Logger getLogger()
>>> {
>>> return logger;
>>> }
>>>
>>> public static void setLogger(Logger aLogger)
>>> {
>>> logger = aLogger;
>>> }
>>>
>>> public String getName()
>>> {
>>> return name;
>>> }
>>>
>>> public void setName(String name)
>>> {
>>> this.name = name;
>>> }
>>>
>>> public String getDescription()
>>> {
>>> return description;
>>> }
>>>
>>> public void setDescription(String description)
>>> {
>>> this.description = description;
>>> }
>>>
>>> public List<ArticlePlacement> getArticlePlacements()
>>> {
>>> return articlePlacements;
>>> }
>>>
>>> public void setArticlePlacements(List<ArticlePlacement>
>>> articlePlacements)
>>> {
>>> this.articlePlacements = articlePlacements;
>>> }
>>>
>>> public void addArticlePlacement(ArticlePlacement articlePlacement)
>>> {
>>> if(this.getArticlePlacements().contains(articlePlacement))
>>> {
>>> return;
>>> }
>>> getArticlePlacements().add(articlePlacement);
>>> articlePlacement.setArticleGroup(this);
>>> }
>>>
>>> public void removeArticlePlacement(ArticlePlacement articlePlacement)
>>> {
>>> getArticlePlacements().remove(articlePlacement);
>>> articlePlacement.setArticleGroup(null);
>>> }
>>> }
>>>
>>>
>>>> Thanks,
>>>>
>>>> -- markus.
>>>>
>>>> Greg Ederer wrote:
>>>>
>>>>> Markus Fuchs wrote:
>>>>>
>>>>>> Hi Greg,
>>>>>>
>>>>>> Do you get a foreign key violation w/o using @PreRemove callbacks
>>>>>> in your pojos? Are you using a current glassfish build?
>>>>>>
>>>>> Hi Markus,
>>>>>
>>>>> Yes. When I em.remove() an ArticlePlacement without the
>>>>> @PreRemove, I get a PSQLException (I'm using PostgreSQL) with a
>>>>> foreign key constraint violation message.
>>>>>
>>>>> I'm using v2b50.
>>>>>
>>>>> Thanks for the reply.
>>>>>
>>>>> Cheers,
>>>>>
>>>>> Greg
>>>>>
>>>>>> Thanks,
>>>>>>
>>>>>> -- markus.
>>>>>>
>>>>>> Greg Ederer wrote:
>>>>>>
>>>>>>> I managed to get this working by adding the following to Article:
>>>>>>>
>>>>>>> @PreRemove
>>>>>>> public void beforeRemove()
>>>>>>> {
>>>>>>> List<ArticlePlacement> articlePlacements =
>>>>>>> getArticlePlacements();
>>>>>>> for(ArticlePlacement ap : articlePlacements)
>>>>>>> {
>>>>>>> ap.setArticle(null);
>>>>>>> }
>>>>>>> }
>>>>>>>
>>>>>>> And in ArticlePlacement:
>>>>>>>
>>>>>>> @PreRemove
>>>>>>> public void beforeRemove()
>>>>>>> {
>>>>>>> getArticleGroup().removeArticlePlacement(this);
>>>>>>> if(getArticle() != null)
>>>>>>> {
>>>>>>> getArticle().removeArticlePlacement(this);
>>>>>>> }
>>>>>>> }
>>>>>>>
>>>>>>> I have a feeling this is not the best way to handle this (and,
>>>>>>> I'm guessing that I'll feel like a dummy when I find out the
>>>>>>> correct way to do this, because it will be pretty obvious).
>>>>>>>
>>>>>>> Any advice welcome.
>>>>>>>
>>>>>>> Cheers,
>>>>>>>
>>>>>>> Greg
>>>>>>>
>>>>>>> Greg Ederer wrote:
>>>>>>>
>>>>>>>> Oops! Accidentally hit send. Please ignore previous post.
>>>>>>>>
>>>>>>>> I have a model containing three entity classes: Article,
>>>>>>>> ArticleGroup and ArticlePlacement. An ArticleGroup contains
>>>>>>>> zero or more ArticlePlacement objects. Each ArticlePlacement
>>>>>>>> wraps an Article (ArticlePlacement also has a start run date and
>>>>>>>> an end run date, which allows me to run an article in multiple
>>>>>>>> groups during different periods).
>>>>>>>>
>>>>>>>> So, in Article, I have:
>>>>>>>>
>>>>>>>> @OneToMany(mappedBy = "article", cascade=CascadeType.ALL)
>>>>>>>> private List<ArticlePlacement> articlePlacements = new
>>>>>>>> ArrayList<ArticlePlacement>();
>>>>>>>>
>>>>>>>> In ArticleGroup, I have:
>>>>>>>>
>>>>>>>> @OneToMany(cascade={CascadeType.PERSIST, CascadeType.MERGE,
>>>>>>>> CascadeType.REFRESH})
>>>>>>>> @OrderBy("position ASC")
>>>>>>>> private List<ArticlePlacement> articlePlacements = new
>>>>>>>> ArrayList<ArticlePlacement>();
>>>>>>>>
>>>>>>>> And, in ArticlePlacement, I have:
>>>>>>>>
>>>>>>>> @ManyToOne
>>>>>>>> private Article article;
>>>>>>>>
>>>>>>>> @ManyToOne
>>>>>>>> private ArticleGroup articleGroup;
>>>>>>>>
>>>>>>>> @PreRemove
>>>>>>>> public void beforeRemove()
>>>>>>>> {
>>>>>>>> getArticleGroup().removeArticlePlacement(this);
>>>>>>>> getArticle().removeArticlePlacement(this);
>>>>>>>> }
>>>>>>>>
>>>>>>>> When I EntityManager.remove() an Article, I get a
>>>>>>>> java.util.ConcurrentModificationException due to the
>>>>>>>> getArticle().removeArticlePlacement(this) in @PreRemove, above.
>>>>>>>> But, if I comment this out, I get a "violates foreign key"
>>>>>>>> PSQLException.
>>>>>>>>
>>>>>>>> Can someone tell me how to deal with this situation correctly?
>>>>>>>>
>>>>>>>> Thanks!
>>>>>>>>
>>>>>>>> Greg
>>>>>>>>
>>>>>>>
>>>>>>>
>>>>>
>>>>>
>>>
>>>
>>
>>