@OneToMany relationship with @EmbeddedId, giving uninitialized proxy passed to persist()

86 Views Asked by At

I have googled a lot, but I have not found any solution. Error showed in the log:

org.hibernate.PersistentObjectException: uninitialized proxy passed to persist()
    at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:99)
    at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:762)
    at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:755)
    at org.hibernate.engine.spi.CascadingAction$7.cascade(CascadingAction.java:315)
    at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:399)
    at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:342)
    at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:208)
    at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:165)
    at org.hibernate.event.internal.AbstractSaveEventListener.cascadeBeforeSave(AbstractSaveEventListener.java:424)
    at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:263)
    at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:192)
    at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:135)
    at org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:208)
    at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:151)

Hibernate querys in the log:

(SqlStatementLogger.java:104) - insert into DEST_ALERTAS (EMAIL, ID_DESTINATARIO) values (?, ?)
(SqlStatementLogger.java:104) - update DEST_ALERTAS_SISTEMA set ACTIVO=? where ID_DESTINATARIO=? and ID_SISTEMA=?

I am inserting a new DEST_ALERTAS, so the first insert is ok, and the update is wrong, it should also be a insert.

My code:

DEST_ALERTAS entity

@Entity
@Table(name = "DEST_ALERTAS")
public class DestinatariosAlertasEntidad implements Serializable {

 
  private static final long serialVersionUID = 1L;

  @Id
  @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "Identificador_DEST_ALERTAS_PK")
  @SequenceGenerator(name = "Identificador_DEST_ALERTAS_PK", sequenceName = "SEC_GI_DEST_ALERTAS", allocationSize = 1)
  @Column(name = "ID_DESTINATARIO", unique = true, nullable = false)
  private int idDestinatario;

  @Column(name = "EMAIL", length = 100)
  private String email;

  @OneToMany(mappedBy = "destinatario", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
  @JsonIgnore
  private Set<DestinatariosAlertasSistemaEntidad> destinatarioSistema = new HashSet<DestinatariosAlertasSistemaEntidad>();
  

DEST_ALERTAS_SISTEMA entity

@Entity
@Table(name = "DEST_ALERTAS_SISTEMA")
public class DestinatariosAlertasSistemaEntidad implements Serializable {


  private static final long serialVersionUID = 1L;
  
  @EmbeddedId
  private DestinatarioSistemaKey clave;

  @MapsId("idSistema")
  @ManyToOne(fetch = FetchType.EAGER)
  @JoinColumn(name = "ID_SISTEMA", referencedColumnName = "ID_SISTEMA", insertable = false, updatable = false)
  private SistemaEntidad sistema;

  @MapsId("idDestinatario")
  @ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
  @JoinColumn(name = "ID_DESTINATARIO", referencedColumnName = "ID_DESTINATARIO", insertable = false, updatable = false)
  private DestinatariosAlertasEntidad destinatario;


Class used to map the composite key is DestinatarioSistemaKey

@Embeddable
public class DestinatarioSistemaKey implements Serializable {

    private static final long serialVersionUID = 1L;

    @Column(name = "ID_SISTEMA")
    private Integer idSistema;
    
    @Column(name = "ID_DESTINATARIO")
    private Integer idDestinatario;

SISTEMAS entity class:

@Entity
@Table(name = "SISTEMAS")
public class SistemaEntidad implements Serializable {

  private static final long serialVersionUID = 1L;

  @Id
  @Column(name = "ID_SISTEMA", unique = true, nullable = false, precision = 10)
  private Integer id;

  @OneToMany(mappedBy = "sistema", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
  private Set<SistemaMotivoEntidad> motivos = new HashSet<SistemaMotivoEntidad>();

  @OneToMany(mappedBy = "sistema", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
  private Set<SistemaCausaEntidad> causas = new HashSet<SistemaCausaEntidad>();

  @OneToMany(mappedBy = "sistema", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
  private Set<SistemaProblemaEntidad> problemas = new HashSet<SistemaProblemaEntidad>();

  @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
  @JoinColumn(name = "ID_TIPO_SISTEMA")
  private TipoSistemaEntidad tipo;

My controller is:

@RequestMapping(value = "/creaDestinatariosAlertas", method = RequestMethod.POST)
  public String creaDestinatariosAlertas(
      @Validated @ModelAttribute("filtro") FiltroDestinatarioSistemaAlertas usuarioAlerta,
      Model model, RedirectAttributes flash, SessionStatus status, HttpServletRequest request, BindingResult result) {
    
    if (result.hasErrors()) {
      return VISTA_CREACION_DESTINATARIOS_ALERTAS;
    }
    
    DestinatariosAlertasEntidad entidad = new DestinatariosAlertasEntidad();
    try {
      entidad.setEmail(usuarioAlerta.getEmail());
      entidad.setDestinatarioSistema(obtenerListaEntidad(usuarioAlerta.getSistemas(), entidad));
      alertasServicio.guardarDestinatario(entidad);
    } catch (Exception e) {
      logger.error(" Ha fallado a la hora de crear un destinatario. " + e.getMessage() + " - " + e);
    }
    String mensajeFlash = (entidad.getIdDestinatario() != 0) ? "Destinatario Creado con éxito!"
        : "No se ha podido crear el Destinatario.!";
    flash.addFlashAttribute(SUCCESS, mensajeFlash);

    // Se procede a borrar la sesion.
    status.setComplete();

    return OK;
  }


  private Set<DestinatariosAlertasSistemaEntidad> obtenerListaEntidad(List<Integer> lista, DestinatariosAlertasEntidad usuarioAlerta) {

    Set<DestinatariosAlertasSistemaEntidad> sistemas = new HashSet<DestinatariosAlertasSistemaEntidad>();
    
    for (Integer sistemaId:lista) {
      //Get sistema from DB
      SistemaEntidad sistema = this.tablasServicio.buscarSistemaByIdEntidad(sistemaId);
      
      //Composite key creation
      DestinatarioSistemaKey key = new DestinatarioSistemaKey();
      key.setIdDestinatario(usuarioAlerta.getIdDestinatario());
      key.setIdSistema(sistemaId);
      
      DestinatariosAlertasSistemaEntidad entidad = new DestinatariosAlertasSistemaEntidad();
      entidad.setClave(key);
      entidad.setDestinatario(usuarioAlerta);
      entidad.setSistema(sistema);
      entidad.setActivo(true);
      
      sistemas.add(entidad);
    }
    
    return sistemas;
  }

AlertasServicio is an interface for calling RepoClass. What RepoClass does is: this.persist(destinatarioAlertasEntidad);

Any help appreciated.

Sorry for the spanish code!

I have tried deleting cascades on SistemaEntidad , but same result.

0

There are 0 best solutions below