spring2 hibernate3 : lazy loading
Bonjour à tous,
j'utilise dans un projet Spring 2/Hibernate 3.2/JSF 1.1, et je bute depuis un petit moment sur un problème d’on je ne trouve aucune solution : LazyLoadingException
Ayant parcouru des pages et des pages, je suis tombé sur ce forum :
http://www.developpez.net/forums/arc...p/t-35594.html
La personne avait rencontré le même problème…mais sa solution ne semble pas marcher chez moi !! :’(
Mon problème ce situe à ce niveau :
J’ai une relation one-to-many reliant un Client à aucune ou plusieurs Adresse.
Je souhaite que cette relation soit en mode lazy=true. Et c’est pour cette raison que mon cauchemar existe !
Tout comme le lien fournis plus haut, j’affiche la liste de tous les clients (sans charger leur adresse). Et lorsque je clique sur un de ces clients, je stocke celui-ci dans une variable en session pour la passer à une autre page dans le but de l’éditer.
Le passage s’effectue avec merveille mais lorsque les adresses sont demandées j’obtiens ce joli message d’erreur :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
| 01:05:52,002 ERROR LazyInitializationException:<init>:19 - could not initialize proxy - the owning Session was closed
org.hibernate.LazyInitializationException: could not initialize proxy - the owning Session was closed
at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:60)
at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:111)
at org.hibernate.proxy.pojo.cglib.CGLIBLazyInitializer.invoke(CGLIBLazyInitializer.java:172)
at fr.labmestre.client.model.Client$$EnhancerByCGLIB$$9426579d.getNom(<generated>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.apache.myfaces.el.PropertyResolverImpl.getProperty(PropertyResolverImpl.java:438)
at org.apache.myfaces.el.PropertyResolverImpl.getValue(PropertyResolverImpl.java:82)
at com.sun.facelets.el.LegacyELContext$LegacyELResolver.getValue(LegacyELContext.java:141)
at com.sun.el.parser.AstValue.getValue(AstValue.java:96)
at com.sun.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:183)
at com.sun.facelets.el.TagValueExpression.getValue(TagValueExpression.java:71)
at com.sun.facelets.el.LegacyValueBinding.getValue(LegacyValueBinding.java:56)
at javax.faces.component.UIOutput.getValue(UIOutput.java:77)
at org.apache.myfaces.shared_impl.renderkit.RendererUtils.getStringValue(RendererUtils.java:217)
at org.apache.myfaces.shared_impl.renderkit.html.HtmlTextRendererBase.renderInput(HtmlTextRendererBase.java:135)
at org.apache.myfaces.shared_impl.renderkit.html.HtmlTextRendererBase.encodeEnd(HtmlTextRendererBase.java:53)
at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:536)
at org.apache.myfaces.shared_impl.renderkit.RendererUtils.renderChild(RendererUtils.java:442)
at org.apache.myfaces.shared_impl.renderkit.RendererUtils.renderChildren(RendererUtils.java:419)
at org.apache.myfaces.shared_impl.renderkit.html.HtmlGroupRendererBase.encodeEnd(HtmlGroupRendererBase.java:75)
at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:536)
at org.apache.myfaces.shared_impl.renderkit.RendererUtils.renderChild(RendererUtils.java:442)
at org.apache.myfaces.shared_impl.renderkit.html.HtmlGridRendererBase.renderChildren(HtmlGridRendererBase.java:216)
at org.apache.myfaces.shared_impl.renderkit.html.HtmlGridRendererBase.encodeEnd(HtmlGridRendererBase.java:98)
at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:536)
at org.apache.myfaces.shared_impl.renderkit.RendererUtils.renderChild(RendererUtils.java:442)
at org.apache.myfaces.shared_impl.renderkit.html.HtmlGridRendererBase.renderChildren(HtmlGridRendererBase.java:216)
at org.apache.myfaces.shared_impl.renderkit.html.HtmlGridRendererBase.encodeEnd(HtmlGridRendererBase.java:98)
at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:536)
at org.apache.myfaces.shared_impl.renderkit.RendererUtils.renderChild(RendererUtils.java:442)
at org.apache.myfaces.shared_impl.renderkit.RendererUtils.renderChildren(RendererUtils.java:419)
at org.apache.myfaces.shared_impl.renderkit.RendererUtils.renderChild(RendererUtils.java:440)
at org.apache.myfaces.shared_impl.renderkit.html.HtmlGridRendererBase.renderChildren(HtmlGridRendererBase.java:216)
at org.apache.myfaces.shared_impl.renderkit.html.HtmlGridRendererBase.encodeEnd(HtmlGridRendererBase.java:98)
at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:536)
at com.sun.facelets.tag.jsf.ComponentSupport.encodeRecursive(ComponentSupport.java:242)
at com.sun.facelets.tag.jsf.ComponentSupport.encodeRecursive(ComponentSupport.java:239)
at com.sun.facelets.FaceletViewHandler.renderView(FaceletViewHandler.java:580)
at org.apache.myfaces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:384)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:138)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:252)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
at org.apache.myfaces.webapp.filter.ExtensionsFilter.doFilter(ExtensionsFilter.java:97)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
at org.apache.myfaces.webapp.filter.ExtensionsFilter.doFilter(ExtensionsFilter.java:144)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
at org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:174)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:77)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:178)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:126)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:105)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:107)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:148)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:869)
at org.apache.coyote.http11.Http11BaseProtocol$Http11ConnectionHandler.processConnection(Http11BaseProtocol.java:667)
at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:527)
at org.apache.tomcat.util.net.LeaderFollowerWorkerThread.runIt(LeaderFollowerWorkerThread.java:80)
at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:684)
at java.lang.Thread.run(Thread.java:595)
9 févr. 2007 01:05:52 com.sun.facelets.FaceletViewHandler handleRenderException
GRAVE: Error Rendering View[/pages/office/edit/ed_client.xhtml]
javax.faces.el.EvaluationException: /pages/office/edit/ed_client.xhtml @30,28 value="#{clientEditBean.client.nom}": Exception getting value of property nom of base of type : fr.labmestre.client.model.Client$$EnhancerByCGLIB$$9426579d
at com.sun.facelets.el.LegacyValueBinding.getValue(LegacyValueBinding.java:60)
at javax.faces.component.UIOutput.getValue(UIOutput.java:77)
at org.apache.myfaces.shared_impl.renderkit.RendererUtils.getStringValue(RendererUtils.java:217)
at org.apache.myfaces.shared_impl.renderkit.html.HtmlTextRendererBase.renderInput(HtmlTextRendererBase.java:135)
at org.apache.myfaces.shared_impl.renderkit.html.HtmlTextRendererBase.encodeEnd(HtmlTextRendererBase.java:53)
at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:536)
at org.apache.myfaces.shared_impl.renderkit.RendererUtils.renderChild(RendererUtils.java:442)
at org.apache.myfaces.shared_impl.renderkit.RendererUtils.renderChildren(RendererUtils.java:419)
at org.apache.myfaces.shared_impl.renderkit.html.HtmlGroupRendererBase.encodeEnd(HtmlGroupRendererBase.java:75)
at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:536)
at org.apache.myfaces.shared_impl.renderkit.RendererUtils.renderChild(RendererUtils.java:442)
at org.apache.myfaces.shared_impl.renderkit.html.HtmlGridRendererBase.renderChildren(HtmlGridRendererBase.java:216)
at org.apache.myfaces.shared_impl.renderkit.html.HtmlGridRendererBase.encodeEnd(HtmlGridRendererBase.java:98)
at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:536)
at org.apache.myfaces.shared_impl.renderkit.RendererUtils.renderChild(RendererUtils.java:442)
at org.apache.myfaces.shared_impl.renderkit.html.HtmlGridRendererBase.renderChildren(HtmlGridRendererBase.java:216)
at org.apache.myfaces.shared_impl.renderkit.html.HtmlGridRendererBase.encodeEnd(HtmlGridRendererBase.java:98)
at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:536)
at org.apache.myfaces.shared_impl.renderkit.RendererUtils.renderChild(RendererUtils.java:442)
at org.apache.myfaces.shared_impl.renderkit.RendererUtils.renderChildren(RendererUtils.java:419)
at org.apache.myfaces.shared_impl.renderkit.RendererUtils.renderChild(RendererUtils.java:440)
at org.apache.myfaces.shared_impl.renderkit.html.HtmlGridRendererBase.renderChildren(HtmlGridRendererBase.java:216)
at org.apache.myfaces.shared_impl.renderkit.html.HtmlGridRendererBase.encodeEnd(HtmlGridRendererBase.java:98)
at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:536)
at com.sun.facelets.tag.jsf.ComponentSupport.encodeRecursive(ComponentSupport.java:242)
at com.sun.facelets.tag.jsf.ComponentSupport.encodeRecursive(ComponentSupport.java:239)
at com.sun.facelets.FaceletViewHandler.renderView(FaceletViewHandler.java:580)
at org.apache.myfaces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:384)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:138)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:252)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
at org.apache.myfaces.webapp.filter.ExtensionsFilter.doFilter(ExtensionsFilter.java:97)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
at org.apache.myfaces.webapp.filter.ExtensionsFilter.doFilter(ExtensionsFilter.java:144)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
at org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:174)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:77)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:178)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:126)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:105)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:107)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:148)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:869)
at org.apache.coyote.http11.Http11BaseProtocol$Http11ConnectionHandler.processConnection(Http11BaseProtocol.java:667)
at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:527)
at org.apache.tomcat.util.net.LeaderFollowerWorkerThread.runIt(LeaderFollowerWorkerThread.java:80)
at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:684)
at java.lang.Thread.run(Thread.java:595) |
En effet, entre deux appels de mes pages JSF, la session hibernate a été fermé.
En attendant j’avançais mon projet en mettant explicitement lazy= "false"…tout marche très bien.
J’ai donc mis en place un filtre OSIV (Open Session In View) fourni par Spring ! En attendant de celui qu’il crée une nouvelle session et rende possible le chargement des adresses demandées spécifiquement pour le client mis en variable de session.
Mais avec ou sans la même erreur ressort !
Je sais qu’il existe OpenSessionInViewInterceptor qui, si j’ai bien compris, remplis exactement le même rôle mais ce mettrait dans application-context-spring.xml au lieu de Web.xml pour OpenSessionInView.
Face à ce problème un petit coup de main ne serait pas de refus car là….je sèche…
Je vous fournis tous les éléments de mon projet en espérant que l’un d’entre-vous aura rencontrer le même problème et aura une solution à me proposer!...et si possible facile à mettre en place ;)(là j’en demande peut-être trop….).
ClientsBean - liste des clients
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
| package fr.labmestre.client.ui;
import org.apache.log4j.Logger;
import java.util.*;
import fr.labmestre.common.exception.LabMestreException;
import fr.labmestre.common.ui.*;
import fr.labmestre.client.model.Client;
import fr.labmestre.client.model.service.ClientServiceAble;
import fr.labmestre.common.model.Adresse;
import fr.labmestre.common.UtilsFunc;
import fr.labmestre.common.Constants;
public class ClientsBean extends PersonneBean
{
private static Logger log = Logger.getLogger(ClientsBean.class);
private ClientServiceAble clientService;
private Client client;
public ClientsBean()
{
super();
}
public ClientServiceAble getClientService(ClientServiceAble clientService) {
return this.clientService;
}
public void setClientService(ClientServiceAble clientService) {
this.clientService = clientService;
}
//Récupère l'identifiant d'un client existant et l'affecte ou en crée un nouveau
public void setId(long id)
{
if (id > 0)
{
try
{
System.out.println("je suis dans SETID");
Client cl1 =this.clientService.getClient(id);
UtilsFunc.setSessionAttribute(Constants.CLIENT_KEY,cl1);
}catch (LabMestreException e)
{
log.error("impossible de chargers tous les utilisateurs"+e);
}
}
}
public String newClient()
{
//création d'une variable de session avec un nouveau client
UtilsFunc.setSessionAttribute(Constants.CLIENT_KEY,new Client());
return super.redirectBean.forward();
}
public void refresh()
{
super.personnes.clear();
try
{
//fais appel au DAO pour charger tous les clients
super.personnes =this.clientService.getClients();
}catch (LabMestreException e)
{
log.error("impossible de chargers tous les utilisateurs");
}
}
public List getClients()
{
//création du tableaux qui contiendra les clients
super.personnes=new ArrayList();
this.refresh();
return super.personnes;
}
public void setClients(List clients)
{
super.personnes=clients;
}
} |
ClientEditBean - Edition d'un client
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
|
package fr.labmestre.client.ui;
import fr.labmestre.client.model.Client;
import fr.labmestre.client.model.service.ClientServiceAble;
import fr.labmestre.client.ui.ClientsBean;
import fr.labmestre.common.ui.RedirectToBean;
import java.util.List;
import java.util.Set;
import java.util.ArrayList;
import java.util.Iterator;
import fr.labmestre.common.exception.LabMestreException;
import fr.labmestre.common.model.Adresse;
import fr.labmestre.common.Constants;
import fr.labmestre.common.Visit;
import fr.labmestre.common.UtilsFunc;
import javax.faces.component.UIData;
import javax.faces.component.UIOutput;
import javax.faces.context.FacesContext;
import javax.faces.model.SelectItem;
import org.apache.log4j.*;
public class ClientEditBean{
private static final Logger log=Logger.getLogger(ClientEditBean.class);
private Client client;
private RedirectToBean redirectBean;
private ClientServiceAble clientService;
private UIData dataTableAdresse;
private List adresses;
public ClientEditBean()
{
}
public ClientServiceAble getClientService(ClientServiceAble clientService) {
return this.clientService;
}
public void setClientService(ClientServiceAble clientService) {
this.clientService = clientService;
}
public List getAdressesList()
{
this.adresses=new ArrayList(((Client) UtilsFunc.getSessionAttribute(Constants.CLIENT_KEY)).getAdresses());
return this.adresses;
}
public void setDataTableAdresse(UIData dataTableAdresse)
{
this.dataTableAdresse=dataTableAdresse;
}
public UIData getDataTableAdresse()
{
return this.dataTableAdresse;
}
public List getTypeAdresseList()
{
List listTypeAdresse=new ArrayList();
listTypeAdresse.add(new SelectItem(Adresse.TYPE_ADRESS_FACTURATION));
listTypeAdresse.add(new SelectItem(Adresse.TYPE_ADRESS_LIVRAISON));
return listTypeAdresse;
}
public Client getClient()
{
this.client=(Client)UtilsFunc.getSessionAttribute(Constants.CLIENT_KEY);
return this.client;
}
public RedirectToBean getRedirectBean() {
return redirectBean;
}
public void setRedirectBean(RedirectToBean redirectBean) {
this.redirectBean = redirectBean;
}
public void removeAdresse()
{
int row = dataTableAdresse.getRowIndex();
Iterator itAdresse=this.client.getAdresses().iterator();
int i=0;
boolean found=false;
while (itAdresse.hasNext()&&found==false)
{
Adresse adresse=(Adresse)itAdresse.next();
if(i==row)
{
this.client.getAdresses().remove(adresse);
found=true;
}
i++;
}
}
public void createAdresse()
{
this.client.getAdresses().add(new Adresse());
}
public void createClient()
{
try
{
this.clientService.saveClient(this.client);
}catch (LabMestreException e)
{
log.error("Impossible d'ajouter l'utilisateur"+this.client.getIdPersonne()+":"+this.client.getNom()+":"+this.client.getPrenom());
}
}
public void saveClient()
{
if (this.client.getIdPersonne()==0)
{
try
{
this.createClient();
}catch (Exception e)
{
log.error("Impossible d'ajouter l'utilisateur"+this.client.getIdPersonne()+e);
}
}else
{
try
{
this.updateClient();
}catch (Exception e)
{
log.error("Utilisateur modifié, impossible de le modifier dans la base de donnée");
log.error(e);
}
}
this.cancel();
}
public void updateClient()
{
try
{
this.clientService.updateClient(this.client);
}catch (LabMestreException e)
{
log.error("Utilisateur modifié, impossible de le modifier dans la base de donnée"+this.client.getIdPersonne()+":"+this.client.getNom()+":"+this.client.getPrenom());
}
}
public String save()
{
this.saveClient();
return this.redirectBean.backward();
}
public void cancel()
{
//supprime la variable de session client
UtilsFunc.removeSessionAttribute(Constants.CLIENT_KEY);
this.redirectBean.backward();
}
} |
Personne - Object de base pour client
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
| package fr.labmestre.common.model;
import fr.labmestre.common.CoordonneePostal;
import java.util.Date;
public class Personne {
protected long idPersonne;
protected String nom;
protected String prenom;
protected java.util.Date dateNaissance;
protected String tel;
protected String fax;
protected String email;
public void setIdPersonne(long value) {
this.idPersonne = value;
}
public long getIdPersonne() {
return idPersonne;
}
public long getORMID() {
return getIdPersonne();
}
public void setNom(String value) {
this.nom = value;
}
public String getNom() {
return nom;
}
public void setPrenom(String value) {
this.prenom = value;
}
public String getPrenom() {
return prenom;
}
public void setDateNaissance(java.util.Date value) {
this.dateNaissance = value;
}
public java.util.Date getDateNaissance() {
return dateNaissance;
}
public void setTel(String value) {
this.tel = value;
}
public String getTel() {
return tel;
}
public void setFax(String value) {
this.fax = value;
}
public String getFax() {
return fax;
}
public void setEmail(String value) {
this.email = value;
}
public String getEmail() {
return email;
}
public String toString() {
return String.valueOf(getIdPersonne());
}
} |
Client - Object métier
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
| package fr.labmestre.client.model;
import fr.labmestre.common.model.Personne;
import java.util.Iterator;
import fr.labmestre.common.model.Adresse;
import java.util.Date;
public class Client extends Personne{
private String statutJuridique;
private String siteWeb;
private String commentaire;
private String raccourciFax;
private java.util.Set adresses = new java.util.HashSet();
public void setRaccourciFax(String value) {
this.raccourciFax = value;
}
public String getRaccourciFax() {
return raccourciFax;
}
public void setAdresses(java.util.Set value) {
this.adresses = value;
}
public java.util.Set getAdresses() {
return adresses;
}
public void setStatutJuridique(String value) {
this.statutJuridique = value;
}
public String getStatutJuridique() {
return statutJuridique;
}
public void setSiteWeb(String value) {
this.siteWeb = value;
}
public String getSiteWeb() {
return siteWeb;
}
public void setCommentaire(String value) {
this.commentaire = value;
}
public String getCommentaire() {
return commentaire;
}
} |
ClientDaoImpl - Dao pour charger les Objets Client
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
|
package fr.labmestre.client.model.dao;
import org.apache.log4j.Logger;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import fr.labmestre.client.model.Client;
import java.io.Serializable;
import java.util.*;
public class ClientDaoImpl extends HibernateDaoSupport implements ClientDaoAble{
private Logger log = Logger.getLogger(ClientDaoImpl.class);
public Client getClient(Long idPersonne)
{
Client user=(Client) this.getHibernateTemplate().load(Client.class,idPersonne);
return user;
}
public List getClients() {
return (List) this.getHibernateTemplate().loadAll(Client.class);
}
public void saveClient(Client value) {
this.getHibernateTemplate().save(value);
}
public void updateClient(Client value) {
this.getHibernateTemplate().update(value);
}
public void deleteClient(Client value) {
this.getHibernateTemplate().delete(value);
}
} |
spring2 hibernate3 : lazy loading (suite...)
N'ayant pas eu assez de place pour tout vous fournir, je continu ici ;)
Adresse - Objet métier pour Adresse
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
|
package fr.labmestre.common.model;
import java.io.Serializable;
import fr.labmestre.client.model.Client;
import fr.labmestre.common.CoordonneePostal;
import fr.labmestre.common.model.*;
public class Adresse implements Serializable {
public static final String TYPE_ADRESS_FACTURATION="Facturation";
public static final String TYPE_ADRESS_LIVRAISON="Livraison";
private long idAdresse;
private CoordonneePostal coordonnee;
private String type;
private fr.labmestre.client.model.Client client;
public void setCoordonnee(CoordonneePostal coordonnee) {
this.coordonnee = coordonnee;
}
public CoordonneePostal getCoordonnee() {
return coordonnee;
}
public void setType(String type)
{
this.type = type;
}
public String getType()
{
return this.type;
}
public long getIdAdresse() {
return idAdresse;
}
public void setIdAdresse(long idAdresse) {
this.idAdresse = idAdresse;
}
public void setClient(fr.labmestre.client.model.Client value) {
this.client = value;
}
public fr.labmestre.client.model.Client getClient() {
return client;
}
} |
Personne.hbm.xml - Client mapping
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| <?xml version="1.0" encoding="utf-8" ?>
<!--
Licensee: Gerard Bouchard
License Type: Evaluation
-->
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="fr.labmestre.common.model.Personne" table="Personne" discriminator-value="Personne" >
<id name="idPersonne" column="idPersonne" type="long" unsaved-value="0">
<generator class="native">
</generator>
</id>
<discriminator column="Discriminator" type="string"/>
<property name="nom" type="string" length="50" not-null="false" />
<property name="prenom" type="string" length="255" not-null="false" />
<property name="dateNaissance" type="date" not-null="false" />
<property name="tel" type="string" length="25" not-null="false" />
<property name="fax" type="string" length="25" not-null="false" />
<property name="email" type="string" length="255" not-null="false" />
<subclass name="fr.labmestre.client.model.Client" discriminator-value="Client" >
<property name="statutJuridique" type="string" length="90" not-null="false" />
<property name="siteWeb" type="string" length="255" not-null="false" />
<property name="commentaire" type="string" length="255" not-null="false" />
<property name="raccourciFax" type="string" length="255" not-null="false" />
<set name="Adresses" cascade="save-update,all-delete-orphan" inverse="true" lazy="true">
<key column="PersonneidPersonne" not-null="false"/>
<one-to-many class="fr.labmestre.common.model.Adresse"/>
</set>
</subclass>
</class>
</hibernate-mapping> |
Adresse.hbm.xml - mapping Adresse
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| <?xml version="1.0" encoding="utf-8" ?>
<!--
Licensee: Gerard Bouchard
License Type: Evaluation
-->
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="fr.labmestre.common.model.Adresse" table="Adresse">
<id name="idAdresse" column="idAdresse" type="long" unsaved-value="0">
<generator class="native">
</generator>
</id>
<property name="type" type="string" column="type" length="50" not-null="true"/>
<component name="coordonnee" class="fr.labmestre.common.CoordonneePostal">
<property name="ville" type="string" column="ville" length="50"/>
<property name="pays" type="string" column="pays" length="50"/>
<property name="adresse" type="string" column="adresse"/>
<property name="codePostal" type="string" column="codePostal" length="20"/>
</component>
<many-to-one name="client" column="PersonneidPersonne" class="fr.labmestre.client.model.Client" not-null="true">
</many-to-one>
</class>
</hibernate-mapping> |
Web.xml
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193
| <?xml version="1.0" encoding="UTF-8"?>
<!--
* Copyright 2004 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
-->
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>labmestre-facelet-spring-jguard-jsf</display-name>
<context-param>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>server</param-value>
</context-param>
<context-param>
<param-name>facelets.LIBRARIES</param-name>
<param-value>/WEB-INF/tags/tomahawk.taglib.xml ; /WEB-INF/tags/javascript4jsf.taglib.xml</param-value>
</context-param>
<context-param>
<param-name>javax.faces.CONFIG_FILES</param-name>
<param-value>/WEB-INF/faces-config-office.xml</param-value>
</context-param>
<context-param>
<description>This parameter tells MyFaces if javascript code should be allowed in the
rendered HTML output.
If javascript is allowed, command_link anchors will have javascript code
that submits the corresponding form.
If javascript is not allowed, the state saving info and nested parameters
will be added as url parameters.
Default: "true"</description>
<param-name>org.apache.myfaces.ALLOW_JAVASCRIPT</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<description>This parameter tells MyFaces if javascript code should be allowed in the
rendered HTML output.
If javascript is allowed, command_link anchors will have javascript code
that submits the corresponding form.
If javascript is not allowed, the state saving info and nested parameters
will be added as url parameters.
Default: "false"
Setting this param to true should be combined with STATE_SAVING_METHOD "server" for
best results.
This is an EXPERIMENTAL feature. You also have to enable the detector filter/filter mapping below to get
JavaScript detection working.</description>
<param-name>org.apache.myfaces.DETECT_JAVASCRIPT</param-name>
<param-value>false</param-value>
</context-param>
<context-param>
<description>If true, rendered HTML code will be formatted, so that it is "human readable".
i.e. additional line separators and whitespace will be written, that do not
influence the HTML code.
Default: "true"</description>
<param-name>org.apache.myfaces.PRETTY_HTML</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<description>If true, a javascript function will be rendered that is able to restore the
former vertical scroll on every request. Convenient feature if you have pages
with long lists and you do not want the browser page to always jump to the top
if you trigger a link or button action that stays on the same page.
Default: "false"</description>
<param-name>org.apache.myfaces.AUTO_SCROLL</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>com.sun.faces.validateXml</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>javax.faces.DEFAULT_SUFFIX</param-name>
<param-value>.xhtml</param-value>
</context-param>
<context-param>
<param-name>facelets.REFRESH_PERIOD</param-name>
<param-value>2</param-value>
</context-param>
<context-param>
<param-name>facelets.DEVELOPMENT</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>com.sun.faces.verifyObjects</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>enableJMX</param-name>
<param-value>false</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext_LabMestre.xml</param-value>
</context-param>
<filter>
<filter-name>hibernateFilter</filter-name>
<filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
<init-param>
<param-name>sessionFactoryBeanName</param-name>
<param-value>mySessionFactory</param-value>
</init-param>
<init-param>
<param-name>singleSession</param-name>
<param-value>false</param-value>
</init-param>
</filter>
<filter>
<filter-name>extensionsFilter</filter-name>
<filter-class>org.apache.myfaces.webapp.filter.ExtensionsFilter</filter-class>
<init-param>
<description>Set the size limit for uploaded files.
Format: 10 - 10 bytes
10k - 10 KB
10m - 10 MB
1g - 1 GB</description>
<param-name>uploadMaxFileSize</param-name>
<param-value>100m</param-value>
</init-param>
<init-param>
<description>Set the threshold size - files
below this limit are stored in memory, files above
this limit are stored on disk.
Format: 10 - 10 bytes
10k - 10 KB
10m - 10 MB
1g - 1 GB</description>
<param-name>uploadThresholdSize</param-name>
<param-value>100k</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>hibernateFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>extensionsFilter</filter-name>
<servlet-name>Faces Servlet</servlet-name>
</filter-mapping>
<filter-mapping>
<filter-name>extensionsFilter</filter-name>
<url-pattern>*.jsf</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>extensionsFilter</filter-name>
<url-pattern>/faces/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>extensionsFilter</filter-name>
<url-pattern>/faces/myFacesExtensionResource/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>org.apache.myfaces.webapp.StartupServletContextListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>
</listener>
<listener>
<listener-class>fr.labmestre.apf.webapp.listener.StartupListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.jsf</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>30</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>/index.jsp</welcome-file>
<welcome-file>/index.html</welcome-file>
</welcome-file-list>
<login-config>
<auth-method>FORM</auth-method>
</login-config>
</web-app> |
application-context.xml - fichier de configuration de spring
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
| <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<!-- ========================= Start of PERSISTENCE DEFINITIONS =========================
DataSource Definition -->
<bean class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close" id="dataSource_LabMestre">
<property name="driverClassName">
<value>org.gjt.mm.mysql.Driver</value>
</property>
<property name="url">
<value>jdbc:mysql://192.168.1.7:3306/springhibdb</value>
</property>
<property name="username">
<value>mysql</value>
</property>
<property name="password">
<value>mdp4mysqlL$</value>
</property>
</bean>
<!-- Hibernate SessionFactory Definition -->
<bean
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean" id="mySessionFactory" lazy-init="true">
<!-- séparer en plusieurs fichiers
<property name="configLocation">
<value>/WEB-INF/hibernate.cfg.xml</value>
</property>
-->
<property name="mappingResources">
<list>
<value>fr/labmestre/common/model/mapping/Personne.hbm.xml</value>
<value>fr/labmestre/common/model/mapping/Adresse.hbm.xml</value>
</list>
</property>
<!-- cible les répertoire contenant tous les hbm
<property name="mappingDirectoryLocations">
<list>
<value>classpath:/com/springinaction/training/model</value>
</list>
</property>
-->
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</prop>
<prop key="hibernate.generate_statistics">false</prop>
<prop key="hibernate.connection.release_mode">auto</prop>
<prop key="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.c3p0.acquire_increment">1</prop>
<prop key="hibernate.c3p0.idle_test_period">100</prop>
<prop key="hibernate.c3p0.max_size">60</prop>
<prop key="hibernate.c3p0.max_statements">0</prop>
<prop key="hibernate.c3p0.min_size">10</prop>
<prop key="hibernate.c3p0.timeout">100</prop>
<prop key="hibernate.use_outer_join">true</prop>
</props>
</property>
<property name="dataSource">
<ref bean="dataSource_LabMestre"/>
</property>
</bean>
<!-- Spring Data Access Exception Translator Defintion -->
<bean
class="org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator" id="jdbcExceptionTranslator_LabMestre">
<property name="dataSource">
<ref bean="dataSource_LabMestre"/>
</property>
</bean>
<!-- Hibernate Template Defintion -->
<bean class="org.springframework.orm.hibernate3.HibernateTemplate" id="hibernateTemplate_LabMestre">
<property name="sessionFactory">
<ref bean="mySessionFactory"/>
</property>
<property name="jdbcExceptionTranslator">
<ref bean="jdbcExceptionTranslator_LabMestre"/>
</property>
</bean>
<!-- Hibernate Transaction Manager Definition -->
<bean
class="org.springframework.orm.hibernate3.HibernateTransactionManager" id="transactionManager_LabMestre">
<property name="sessionFactory">
<ref bean="mySessionFactory"/>
</property>
</bean>
<!-- ========================= Start of DAO DEFINITIONS =========================
TODO DAO Definition: Hibernate implementation -->
<bean class="fr.labmestre.client.model.dao.ClientDaoImpl" id="clientDao">
<property name="hibernateTemplate">
<ref bean="hibernateTemplate_LabMestre"/>
</property>
</bean>
<!-- ========================= Start of SERVICE DEFINITIONS =========================
TODO Service Definition -->
<bean class="fr.labmestre.client.model.service.ClientServiceImpl" id="clientService">
<property name="springClientDao">
<ref local="clientDao"/>
</property>
</bean>
<!-- Transactional proxy for the TODO Service -->
<bean
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" id="clientServiceProxy">
<property name="transactionManager">
<ref local="transactionManager_LabMestre"/>
</property>
<property name="target">
<ref local="clientService"/>
</property>
<property name="transactionAttributes">
<props>
<prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="save*">PROPAGATION_REQUIRED</prop>
<prop key="update*">PROPAGATION_REQUIRED</prop>
<prop key="delete*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
</beans> |
ouf!!
Bon ben voilà...je pense vous avoir fournis toutes les pièces utiles....
Je vous remercie d'avance pour votre aide précieuse!;)
@ bientot, fxonline
spring2 hibernate3 : lazy loading
merci *alexandre* pour ta réponse!
je vais creuser toutes les voix que tu m'as proposées! et je file trouver ce magazine!!
S'il a ma solution ça serait merveilleux...
Sinon j'avoue ne pas avoir tout compris mais google est mon ami;)
Mais une question me chiffone...il semblerait qu'utiliser la solution du filtre OSIV marche en règle générale...pourquoi mon cas ferait-il exception...aurais-je mal compris son utilité?
spring2 hibernate3 : lazy loading
Tu as parfaitement compris mon problème!Et tu viens de me donner une indication importante.
D'après ce que j'avais pu comprendre sur l'utilisation d'un filtre OSIV, je croyais qu'il permettait de détecter lorsqu’un appel vers hibernate serait effectué et l’aurait rattaché automatiquement à la nouvelle session.
Mais si j'ai bien compris tes explications, il permet juste l'ouverte de la session tout le long d’un request/reponse, et il n'y a aucune relation avec les échanges suivant.
Donc inutile de m'acharner sur ce pauvre OSIV...(j'ai crée je ne sais combien de version allégé! j'ai même intégré ma solution dans Appfuse 1.9.4...pensant d’autre mauvaise manipulation de ma part!...)
Ok l'explication a été trouvé, tu me propose de rattacher moi même l'élément a une nouvelle session par la commande session.merge()!
Je me pause alors 2 questions :
-Où dois-je mettre cette commande ? (Couche service ?,couche dao ?, un bean dans spring ?)
-Cela permettrait-il de rattacher automatiquement à une nouvelle session hibernate n’importe quelle objet métier partiellement mis en mémoire (HttpSession) ?
Pour être plus clair concernant ma 2ème question, dans mon cas cela fonctionne ainsi :
RQ/REP | évènement
1 clientsBean affiche la liste des clients
2 clientsBean reçois comme indication de mettre en mémoire (HttpSession) un client sélectionné par l’utilisateur (fonction setId(long id) de clientsBean)
3 clientEditBean récupère le client mis en mémoire (HttpSession-> fonction getClient de clientEditBean) et met en page son contenu (et là lorsqu’on arrive aux adresses : lazyException)
Il faudrait donc qu’une classe ou une fonction agisse au moment où clientEditBean récupère les adresses et effectue le rattachement!
Je vais creuser cette histoire! J’en avait déjà entendu parlé mais je n’ai jamais vu d’exemple dans le cas de spring2/hibernate3.2.Je n’ai aucune idée de comment mettre cela en place !
Merci beaucoup en tout cas !
spring2 hibernate3 : lazy loading
Ok, si je comprends bien ericw78, chaque page (jsp + servlet) doit être confiné à une seule tâche.
Ainsi, au lieu de mettre le client sélectionné en mémoire, je ne passerais à la prochaine page uniquement son identifiant et cette dernière irait le chercher dans la bdd.
Ok cela me semble très faisable et facile à modifier!
Alors il me vient une dernière interrogation:
Lorsque je travaillais en lazy=false, j'utiliser cette variable en mémoire pour la modifier directement après un submit. Puis je faisais appel à saveOrUpdate() et la base de donnée était mise à jour.
Pour mettre en place la solution d’ericw78, je vais devoir charger le client a modifier puis utiliser un constructeur par copie pour effectuer les modification faites par l’utilisateur (travaillant directement sur une instance l’objet métier Client) et enfin faire appel à la fonction saveOrUpdate() . Y'aurait-il une solution pour éviter de passer par un constructeur par copie ?
Concernant ce que dis a.snaps, je ne m’étais pas occuper jusqu'à présent de l’accès concurrent à une même donnée, Pensant que la dernière modification écraserait les autres.
Pour l’histoire d’une instance managé par la BDD…j’avoue que là…je sèche…. ;) peut-être un peu trop compliqué à mon niveau ;)
Merci pour tous ces conseils ! Je vais mettre en place la solution de ericw78 dans un premier temps et je reviens pour vous tenir au courant !...Mais l’espoir et de retour !!!;)