Alex
Alex

Reputation: 2125

Spring: detached entity passed to persist

It is a short time that I'm studying Spring,I'm a student I have problems with dependency injection. In this project I have this error code in the method acquista.Why? Acquista in english is translated in "buy".If my Carrello (cart) is composed by more than one Articolo(Article) , in ArticoliOrdine(ArticlesOrder) I have only the first of them.Why?How can I solve it?

Error code:

 Grave: Servlet.service() for servlet [applicationContext] in context with path  [/SpringStore] threw exception [Request processing failed; nested exception is  javax.persistence.PersistenceException: org.hibernate.PersistentObjectException: detached entity passed to persist: bean.Ordine] with root cause
org.hibernate.PersistentObjectException: detached entity passed to persist: bean.Ordine
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:139)
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:75)
at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:811)
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:784)
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:789)
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:1181)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:289)
at com.sun.proxy.$Proxy37.persist(Unknown Source)
at daoJPA.CarrelloDAOImpl.acquista(CarrelloDAOImpl.java:130)     

CarrelloDAOImpl.java

@Transactional
 public class CarrelloDAOImpl implements CarrelloDAO {

@PersistenceContext
private EntityManager em;

@Autowired
Carrello carrello;

@Autowired
private ArticoliOrdine articoliOrdine;

@Autowired
private Ordine ordine;


public void acquista(Cliente c){

    ordine.setIdCliente(c);
    ordine.setData(new Date(System.currentTimeMillis()));
    ordine.setStato("In lavorazione");
    em.persist(ordine);

    Set<String> lista_articoli=carrello.getMappa_Articoli().keySet();
    synchronized(lista_articoli){
        Iterator<String> it=lista_articoli.iterator();
        while(it.hasNext()){
            String codice=it.next();
            System.out.println("codice: "+codice);
            Query q=em.createQuery("SELECT a FROM Articolo a WHERE a.codice =:codice");
            q.setParameter("codice", codice);
            Articolo a =(Articolo)q.getSingleResult();
            ArticoliOrdinePK pk=articoliOrdine.getArticoliordinePK();
            pk.setIdArticolo(a.getId());
            pk.setIdOrdine(ordine.getId());
            articoliOrdine.setArticolo(a);
            articoliOrdine.setQuantita(carrello.getMappa_Articoli().get(codice));
            em.persist(articoliOrdine);

            //aggiorno la quantita' dell'articolo
            Articolo articolo_update=em.find(Articolo.class,a.getId());
            articolo_update.setQuantita(articolo_update.getQuantita()- articoliOrdine.getQuantita());
        }//while        
    }//syncronized
}//acquista

}//CarrelloDAOImpl

Ordine.java

@Table(name="ordine")
@Entity
public class Ordine implements Serializable {

private static final long serialVersionUID = 1L;

@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="id")
private Integer id;

@Temporal(TemporalType.TIMESTAMP)
@Column(name="data")
private Date data;

@Column(name="stato")
private String stato;

@ManyToOne(optional=false)
@JoinColumn(name="idCliente",referencedColumnName="id")
private Cliente idCliente;

@OneToMany(mappedBy="ordine",cascade=CascadeType.ALL,fetch=FetchType.LAZY)
Collection<ArticoliOrdine> articoliordineCollection;

public Ordine() {
}

public Ordine(Integer id) {
    this.id = id;
}

public Ordine(Integer id, Date data, String stato) {
    this.id = id;
    this.data = data;
    this.stato = stato;
}

public Integer getId() {
    return id;
}

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


public Date getData() {
    return data;
}

public void setData(Date data) {
    this.data = data;
}

public String getStato() {
    return stato;
}

public void setStato(String stato) {
    this.stato = stato;
}


public Cliente getIdCliente() {
    return idCliente;
}

public void setIdCliente(Cliente idCliente) {
    this.idCliente = idCliente;
}

public Collection<ArticoliOrdine> getArticoliordineCollection() {
    return articoliordineCollection;
}

public void setArticoliordineCollection(
        Collection<ArticoliOrdine> articoliordineCollection) {
    this.articoliordineCollection = articoliordineCollection;
}

@Override
public boolean equals(Object o){
    if(! (o instanceof Ordine) )
        return false;
    Ordine ordine=(Ordine)o;
    return ordine.id==this.id;
}//equals

public String toString(){
    return id+" cliente:"+idCliente.getId();
}//toString



}//Ordine

CarrelloController.java

@Controller
public class CarrelloController {

@Autowired
CarrelloDAO carrelloDAO;

@Autowired
Carrello carrello;

...

@RequestMapping(value="/acquista",method=RequestMethod.POST)
public String acquista(HttpServletRequest request,ModelMap model){
    HttpSession session=request.getSession();
    Cliente cliente=(Cliente)session.getAttribute("cliente");
    carrelloDAO.acquista(cliente);
    carrello.svuotaCarrello();
    model.addAttribute("num_articoli",carrello.contaArticoliCarrello());
    model.addAttribute("totale_carrello",carrello.getTotale());
    return "redirect:/";
}//checkOut

}//CarrelloController

ApplicationContext.xml

<bean  class="daoJPA.ClienteDAOImpl" id="clienteDAO"/>

<bean  class="daoJPA.ArticoloDAOImpl" id="articoloDAO"/>

<bean class="bean.Carrello" id="carrello" scope="session">
    <aop:scoped-proxy/>
</bean>

<bean class="daoJPA.CarrelloDAOImpl" id="carrelloDAO"/>

<bean class="bean.ArticoliOrdine" id="articoliOrdine" scope="prototype">
    <property name="articoliordinePK">
        <bean class="bean.ArticoliOrdinePK" id="articoliOrdinePK" scope="prototype"/>
    </property>
</bean>

<bean class="bean.Ordine" id="ordine" scope="prototype"/>

Upvotes: 1

Views: 3667

Answers (1)

Vlad Mihalcea
Vlad Mihalcea

Reputation: 153710

You are not approaching this the right way. Your entities shouldn't be treated as Spring Beans.

@Autowired
private ArticoliOrdine articoliOrdine;

...

em.persist(articoliOrdine);

For long conversations you should either use:

  • Extended persistence context
  • detached objects saved in your Http Session

And detached entities shouldn't be passed to persist. You should merge them instead.

Persist is only meant for moving an entity state from TRANSIENT to PERSISTED. For DETACHED -> PERSISTED transitions you should always use EntityManager#merge() or Hibernate specific saveOrUpdate.

Upvotes: 1

Related Questions