java.lang.IllegalStateException

Saludos

Tengo un cliente CRUD rudimentario en Java Swing, JPA, Toplink y una base de datos Postgresql. Varios usuarios usan este cliente de manera concurrente.

Las relaciones de las clases de entidad son las siguientes:

public class Agencias implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @Basic(optional = false)
    @Column(name = "noagencia")
    private Integer noagencia;

     @OneToMany(cascade = CascadeType.ALL, mappedBy = "agencias")
    private Collection<Llamadas> llamadasCollection;

     }

public class Llamadas implements Serializable {
    @Transient
    private PropertyChangeSupport changeSupport = new PropertyChangeSupport(this);
    private static final long serialVersionUID = 1L;

    @Basic(optional = false)
    @SequenceGenerator (name="llamadas_nollamada_seq", allocationSize=1)
    @Id @GeneratedValue ( generator="llamadas_nollamada_seq")
    @Column(name = "nollamada")
    private Long nollamada;

    @JoinColumn(name = "noagencia", referencedColumnName = "noagencia")
    @ManyToOne(optional = false)
    private Agencias agencias;

}

Me he dado cuenta que de manera aparentemente aleatoria aparece la excepcion siguiente a la hora de realizar operaciones persist,merge y remove de objetos del tipo "Llamadas":

"java.lang.IllegalStateException: During synchronization a new object was found through a relationship that was not marked cascade PERSIST"

¿A que se debe este error? He tenido muchos problemas para reproducirlo, el error aparece de manera aparentemente aleatoria aunque tengo la sospecha de que se debe a varios usuarios realizando operaciones persist,merge,remove al mismo tiempo.

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.
Imagen de ezamudio

más info

Sin más info es difícil ayudarte. Efectivamente el problema es de concurrencia, eso es obvio por el mensaje, que suena como que tienes alguna entidad con relación 1-N a otra entidad y le agregaste un objeto a esa relación, pero no lo persististe. Algo así:

Tienes las entidades Maestro y Detalle. Un Maestro puede tener varios Detalles. Si creas un maestro y le pones detalles, debes persistir todo, a menos que tengas la relación marcada como cascade PERSIST, entonces con persistir el maestro se guardan también los detalles. Pero si no tienes el cascade PERSIST entonces si le haces algo al maestro y le agregas un Detalle y persistes el maestro, puedes tener luego broncas porque ese Detalle nada más está en memoria.

Viendo tus entidades, tal vez una Agencia que tenga varias Llamadas. Por cierto, es recomendable (y es la convención) que las entidades tengan nombre singular, es decir Agencia y Llamada. Lo raro es que tienes CascadeType.ALL en el detalle de llamadas... tal vez alguna bronca que ocurre cuando dos o más clientes están trabajando sobre los mismos datos, que finalmente es el problema más común en aplicaciones que manejan concurrencia. Tal vez si manejas la persistencia dentro de una transacción... deberías revisar las estrategias de optimistic y pessimistic locking para ver cuál se adecúa mejor a tus necesidades e implementar esa.

Ok, voy a intentar

Ok, voy a intentar persistiendo primero a los detalles antes del maestro. Tal vez con eso se pueda quitar una de las posibilidades. Gracias!

Imagen de ezamudio

puedes?

En caso de que estés actualizando Agenda, puedes primero persistir llamadas, pero si estás insertando una nueva Agenda, probablemente debes primero persistirla y luego sus Llamadas (depende de cómo estén definidas tus entidades)

Imagen de Nopalin

No creo que sea de concurrencia

El problema no tiene que ver con concurrencia, el problema tiene que ver con la forma en que estás declarando la relación @OneToMany en la entidad Agencias. Ahi le estas diciendo que la lista es una relación inversa con el mappedBy, pero al mismo tiempo le estas diciendo que esa entidad es la encargada de persistir las nuevas Llamadas que encuentre en la collecion con el Cascade.ALL, no se cual se la jerarquía de definiciones en hibernate pero al parecer si esta definido un mappedBy es el que gana. Entonces el problema seguramente se reproduce cuando persistes una entidad Agencias, y a la colección de llamadas agregas una nueva, luego persistes Agencias, donde tu esperas que por el Cascade.ALL se persistas los nuevos, pero ya que como Llamadas tiene la propiedad de la relación, tu debes persistir por aparte Llamadas.

Puedes hacer dos cosas: quitar el mappedBy de la colección y dejar solo el Cascade.ALL o quitar el Cascade.ALL y persistir siempre las Llamadas por aparte de Agencias.

sobres