1

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"/>
Vlad Mihalcea
  • 142,745
  • 71
  • 566
  • 911
Alex
  • 2,075
  • 5
  • 27
  • 39
  • add the entity `Ordine` to your question. It seems you are setting the `id` property of the entity and calling `persist`. If `id` is not of type `assigned` then you will get this exception. – Chaitanya Nov 30 '14 at 14:47
  • I added Ordine To my question – Alex Nov 30 '14 at 15:58

1 Answers1

1

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.

Baum mit Augen
  • 49,044
  • 25
  • 144
  • 182
Vlad Mihalcea
  • 142,745
  • 71
  • 566
  • 911
  • I used Jpa+Hibernate .I tried with `em.begin()` and `em.commit` but the @Transational annotation does not allow this – Alex Dec 01 '14 at 11:10
  • You don't need to manually declare transaction boundaries if you use Spring. you can simply use the Transactional annotation and let Spring do the rest. You can also use TransactionTemplate for some other use cases where you don't want to rely on annotations. – Vlad Mihalcea Dec 01 '14 at 11:46
  • Why my entity have become dethached if they were inside the boundaries?I read your articles but I can't understand it – Alex Dec 01 '14 at 12:39
  • I solved using Lookup method injection .Is this a good solution? – Alex Dec 02 '14 at 14:15
  • But using Lookup method injection I will have a new instance everytime I will want one.I just have to call an abstract method which give me the new instance..Instead ,Request gives me new instance every HTTP request – Alex Dec 02 '14 at 14:55
  • Prototype gives only one instance for each request.Only one.. [Link](http://docs.spring.io/spring/docs/3.0.0.M3/reference/html/ch04s04.html) – Alex Dec 02 '14 at 15:10
  • yes it gives me a new instance but the injection occurs only once – Alex Dec 02 '14 at 15:29