问题
Right so i am working with hibernate gilead and gwt to persist my data on users and files of a website. my users have a list of file locations. i am using annotations to map my classes to the database. I am getting a org.hibernate.LazyInitializationException
when i try to add file locations to the list that is held in the user class.
this is a method below that is overridden from a external file upload servlet class that i am using. when the file uploads it calls this method.
the user1 is loaded from the database elsewhere.
the exception occurs at user1.getFileLocations().add(fileLocation);
. I dont understand it really at all.! any help would be great. the stack trace of the error is below
public String executeAction(HttpServletRequest request,
List<FileItem> sessionFiles) throws UploadActionException {
for (FileItem item : sessionFiles) {
if (false == item.isFormField()) {
try {
YFUser user1 = (YFUser)getSession().getAttribute(SESSION_USER);
// This is the location where a file will be stored
String fileLocationString = "/Users/Stefano/Desktop/UploadedFiles/" + user1.getUsername();
File fl = new File(fileLocationString);
fl.mkdir();
// so here i will create the a file container for my uploaded file
File file = File.createTempFile("upload-", ".bin",fl);
// this is where the file is written to disk
item.write(file);
// the FileLocation object is then created
FileLocation fileLocation = new FileLocation();
fileLocation.setLocation(fileLocationString);
//test
System.out.println("file path = "+file.getPath());
user1.getFileLocations().add(fileLocation);
//the line above is where the exception occurs
} catch (Exception e) {
throw new UploadActionException(e.getMessage());
}
}
removeSessionFileItems(request);
}
return null;
}
//This is the class file for a Your Files User
@Entity
@Table(name = "yf_user_table")
public class YFUser implements Serializable,ILightEntity {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "user_id",nullable = false)
private int userId;
@Column(name = "username")
private String username;
@Column(name = "password")
private String password;
@Column(name = "email")
private String email;
@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name = "USER_FILELOCATION", joinColumns = {
@JoinColumn(name = "user_id") }, inverseJoinColumns = {
@JoinColumn(name = "locationId") })
private List<FileLocation> fileLocations = new ArrayList<FileLocation>() ;
public YFUser(){
}
public int getUserId() {
return userId;
}
private void setUserId(int userId) {
this.userId = userId;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public List<FileLocation> getFileLocations() {
if(fileLocations ==null){
fileLocations = new ArrayList<FileLocation>();
}
return fileLocations;
}
public void setFileLocations(List<FileLocation> fileLocations) {
this.fileLocations = fileLocations;
}
/*
public void addFileLocation(FileLocation location){
fileLocations.add(location);
}*/
@Override
public void addProxyInformation(String property, Object proxyInfo) {
// TODO Auto-generated method stub
}
@Override
public String getDebugString() {
// TODO Auto-generated method stub
return null;
}
@Override
public Object getProxyInformation(String property) {
// TODO Auto-generated method stub
return null;
}
@Override
public boolean isInitialized(String property) {
// TODO Auto-generated method stub
return false;
}
@Override
public void removeProxyInformation(String property) {
// TODO Auto-generated method stub
}
@Override
public void setInitialized(String property, boolean initialised) {
// TODO Auto-generated method stub
}
@Override
public Object getValue() {
// TODO Auto-generated method stub
return null;
}
}
@Entity
@Table(name = "fileLocationTable")
public class FileLocation implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "locationId", updatable = false, nullable = false)
private int ieId;
@Column (name = "location")
private String location;
public FileLocation(){
}
public int getIeId() {
return ieId;
}
private void setIeId(int ieId) {
this.ieId = ieId;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
}
Apr 2, 2010 11:33:12 PM org.hibernate.LazyInitializationException <init>
SEVERE: failed to lazily initialize a collection of role: com.example.client.YFUser.fileLocations, no session or session was closed
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.example.client.YFUser.fileLocations, no session or session was closed
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:380)
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:372)
at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:365)
at org.hibernate.collection.AbstractPersistentCollection.write(AbstractPersistentCollection.java:205)
at org.hibernate.collection.PersistentBag.add(PersistentBag.java:297)
at com.example.server.TestServiceImpl.saveFileLocation(TestServiceImpl.java:132)
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:597)
at net.sf.gilead.gwt.PersistentRemoteService.processCall(PersistentRemoteService.java:174)
at com.google.gwt.user.server.rpc.RemoteServiceServlet.processPost(RemoteServiceServlet.java:224)
at com.google.gwt.user.server.rpc.AbstractRemoteServiceServlet.doPost(AbstractRemoteServiceServlet.java:62)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:713)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:806)
at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:487)
at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:362)
at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:181)
at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:729)
at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:405)
at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
at org.mortbay.jetty.handler.RequestLogHandler.handle(RequestLogHandler.java:49)
at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
at org.mortbay.jetty.Server.handle(Server.java:324)
at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:505)
at org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java:843)
at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:647)
at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:211)
at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:380)
at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:396)
at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:488)
Apr 2, 2010 11:33:12 PM net.sf.gilead.core.PersistentBeanManager clonePojo
INFO: Third party instance, not cloned : org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.example.client.YFUser.fileLocations, no session or session was closed
回答1:
Lazy means that the values of the collection are loaded from the database only when they are accessed. If at that time the Session
has been closed, the LazyInitializationException
is thrown, because the data cannot be fetched.
In your case I'd simply suggest adding an eager fetch type to the association:
@ManyToMany(cascade = CascadeType.ALL, fetchType=FetchType.EAGER)
This will load the fileLocations
when the entity is loaded and no lazy loading will be needed.
A common solution is to use OpenSessionInView, but it may not always work with GWT, becaucse the client is remote and the session cannot be opened there.
So you are going to have some problems with lazy initialization. You can search around for related questions, there are a few - this and this for example.
回答2:
This exception means that the FileLocations association is not yet loaded and you are trying to access it. There is no session opened, and there is no way to load the association. This is the LazyInitializationException.
Edit: Read Bozho's post for the solution.
来源:https://stackoverflow.com/questions/2569648/lazyinitializationexception-when-adding-to-a-list-that-is-held-within-a-entity-c