Hibernate Books

All times are UTC - 5 hours [ DST ]



Post new topic Reply to topic  [ 5 posts ] 
Author Message
 Post subject: OneToMany HIbernate Projections problem
PostPosted: Tue Aug 23, 2011 10:28 am 
Newbie

Joined: Sat Jun 09, 2007 12:29 pm
Posts: 19
I'm trying to create a Hibernate projection for database stored File and its versions like this:

Code:
DetachedCriteria criteria = DetachedCriteria.forClass(File.class, "file");
    criteria.createAlias("versions","versions", CriteriaSpecification.LEFT_JOIN);
    criteria.createAlias("publishedVersion","publishedVersion", CriteriaSpecification.LEFT_JOIN);
    criteria.setProjection(
            Projections.projectionList()
                .add(Projections.alias(Projections.property("uuid"), "uuid"))
                .add(Projections.alias(Projections.property("name"), "name"))
                .add(Projections.alias(Projections.property("contentType"), "contentType"))
                .add(Projections.alias(Projections.property("extension"), "extension"))
                .add(Projections.alias(Projections.property("parent"), "parent"))
                .add(Projections.alias(Projections.property("creationDate"), "creationDate"))
                .add(Projections.alias(Projections.property("updateDate"), "updateDate"))
                .add(Projections.alias(Projections.property("publishedVersion"), "publishedVersion"))
                .add(Projections.alias(Projections.property("versions"), "versions"))
            );
    criteria.setResultTransformer(Transformers.aliasToBean(NodeView.class));
    criteria.add((parent==null)?
            Restrictions.isNull("parent"):
            Restrictions.eq("parent", parent));
    List records = hibernateTemplate.findByCriteria(criteria);




I'm trying to create a Hibernate projection for database stored File and its versions like this:

DetachedCriteria criteria = DetachedCriteria.forClass(File.class, "file");
criteria.createAlias("versions","versions", CriteriaSpecification.LEFT_JOIN);
criteria.createAlias("publishedVersion","publishedVersion", CriteriaSpecification.LEFT_JOIN);
criteria.setProjection(
Projections.projectionList()
.add(Projections.alias(Projections.property("uuid"), "uuid"))
.add(Projections.alias(Projections.property("name"), "name"))
.add(Projections.alias(Projections.property("contentType"), "contentType"))
.add(Projections.alias(Projections.property("extension"), "extension"))
.add(Projections.alias(Projections.property("parent"), "parent"))
.add(Projections.alias(Projections.property("creationDate"), "creationDate"))
.add(Projections.alias(Projections.property("updateDate"), "updateDate"))
.add(Projections.alias(Projections.property("publishedVersion"), "publishedVersion"))
.add(Projections.alias(Projections.property("versions"), "versions"))
);
criteria.setResultTransformer(Transformers.aliasToBean(NodeView.class));
criteria.add((parent==null)?
Restrictions.isNull("parent"):
Restrictions.eq("parent", parent));
List records = hibernateTemplate.findByCriteria(criteria);

I'm getting following error:

Code:
ERROR: com.objectverse.dms.web.fileexplorer.FileExplorerController - java.lang.ArrayIndexOutOfBoundsException: 8
23.8.2011 16:05:52 org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [appServlet] in context with path [/com.objectverse] threw exception [Request processing failed; nested exception is org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only] with root cause
org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:717)
at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:393)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:120)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:621)
at com.objectverse.dms.web.fileexplorer.FileExplorerController$$EnhancerByCGLIB$$44729f57_2.getSubNodes(<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:597)
at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:176)
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:426)
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:414)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:790)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:719)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:644)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:560)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:641)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:304)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:198)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:240)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:164)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:462)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:164)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:563)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:399)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:317)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:204)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:311)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)


The problem is in versions property that I need within the NodeView ResultTransformer. How can I get versions?

The error happens in

Code:
List records = hibernateTemplate.findByCriteria(criteria);


Any help appreciated.

_________________
http://www.objectverse.com
http://www.alcyone.si
http://blog.alcyone.si


Top
 Profile  
 
 Post subject: Re: OneToMany HIbernate Projections problem
PostPosted: Tue Aug 23, 2011 11:39 am 
Newbie

Joined: Mon Dec 10, 2007 7:03 am
Posts: 14
Attributes with complex types (ie relations) can not be used in Criteria projections, you can only use simple types.
Could you describe you object model with relation mapping configs?


Top
 Profile  
 
 Post subject: Re: OneToMany Hibernate Projections problem
PostPosted: Wed Aug 24, 2011 4:04 am 
Newbie

Joined: Sat Jun 09, 2007 12:29 pm
Posts: 19
Of course:

Code:
package com.objectverse.dms.model.file;

import java.sql.Blob;

import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.Lob;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.validation.constraints.NotNull;

import org.codehaus.jackson.annotate.JsonIgnoreProperties;

import com.objectverse.system.persistence.model.PersistentRecordImpl;

@Entity
@Table(name="Dms_FileVersion")
@JsonIgnoreProperties(value={"data"})
public class FileVersion extends PersistentRecordImpl implements INodeVersion {

   @NotNull
   @Column(name = "version", nullable=false)
    private Integer version = 1;
   
   @NotNull
   @Column(name = "size", nullable=false)
    private Long size;

    @Lob
    @NotNull
    @Basic(fetch = FetchType.LAZY)
    @Column(name="data", nullable=false)
    private Blob data;

    @NotNull
    @ManyToOne
   @JoinColumn(name="fileUuid", nullable=false)
   private File file;

   public Blob getData() {
      return data;
   }

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

   public Long getSize() {
      return size;
   }

   public void setSize(Long size) {
      this.size = size;
   }

   public Integer getVersion() {
      return version;
   }

   public void setVersion(Integer version) {
      this.version = version;
   }

   public File getFile() {
      return file;
   }

   public void setFile(File file) {
      this.file = file;
   }
   
}


Code:
package com.objectverse.dms.model.file;

import java.sql.Blob;
import java.util.ArrayList;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

import org.codehaus.jackson.annotate.JsonIgnoreProperties;
import org.codehaus.jackson.map.annotate.JsonDeserialize;
import org.codehaus.jackson.map.annotate.JsonSerialize;

import com.objectverse.dms.model.IFileTreeNode;
import com.objectverse.dms.util.folder.json.JsonFileVersionDeserializer;
import com.objectverse.dms.util.folder.json.JsonFolderDeserializer;
import com.objectverse.system.persistence.model.PersistentRecordImpl;
import com.objectverse.system.util.json.JsonObjectverseSerializer;

@Entity
@Table(name="Dms_File")
@JsonIgnoreProperties(value={"data", "versions"})
public class File extends PersistentRecordImpl implements IFileTreeNode {

   private static final String nodeType = "FILE";
   
   @NotNull
   @Size(min = 1, max = 255)
   @Column(name = "name", length=255, nullable=false)
    private String name;
   
   @NotNull
   @Column(name = "extension", length=10)
    private String extension;
   
    @NotNull
    @Column(name="contentType")
    private String contentType;
   
    @NotNull
    @ManyToOne
   @JoinColumn(name="parentUuid" )
   private Folder parent;
   
    @ManyToOne
   @JoinColumn(name="publishedVersionUuid" )
   private FileVersion publishedVersion;
   
    @OneToMany(mappedBy="file", cascade = CascadeType.REMOVE, fetch=FetchType.LAZY)
   private List<FileVersion> versions = new ArrayList<FileVersion>();

   public String getName() {
      return name;
   }

   public void setName(String filename) {
      this.name = filename;
   }

   public Blob getData() {
      return this.getCurrentFileVersion().getData();
   }

   public String getContentType() {
      return contentType;
   }

   public void setContentType(String contentType) {
      this.contentType = contentType;
   }

   public Long getSize() {
      return this.getCurrentFileVersion().getSize();
   }

   public String getExtension() {
      return extension;
   }

   public void setExtension(String extension) {
      this.extension = extension;
   }

   @JsonDeserialize(using=JsonFolderDeserializer.class)
   public void setParent(Folder parent) {
      this.parent = parent;
   }
   
   @JsonSerialize(using=JsonObjectverseSerializer.class)
   public Folder getParent() {
      return this.parent;
   }

   @Override
   public String getIconCls() {
      return (this.extension!=null)?this.extension:"file";
   }

   @JsonSerialize(using=JsonObjectverseSerializer.class)
   public FileVersion getPublishedVersion() {
      return publishedVersion;
   }

   @JsonDeserialize(using=JsonFileVersionDeserializer.class)
   public void setPublishedVersion(FileVersion publishedVersion) {
      this.publishedVersion = publishedVersion;
   }

   public List<FileVersion> getVersions() {
      return versions;
   }

   public void setVersions(List<FileVersion> versions) {
      this.versions = versions;
   }

   @Override
   public String getSystemPath() {
      String systemPath = "";
      if (this.parent!=null) systemPath += this.parent.getSystemPath();
      return systemPath + "/" + this.getName();
   }
   
   @Override
   public String getNodeType() {
      return File.nodeType;
   }
   
   public Integer getVersion() {
      return getCurrentFileVersion().getVersion();
   }
   
   private FileVersion getCurrentFileVersion() {
      if(this.publishedVersion!=null) {
         return this.publishedVersion;
      } else {
         FileVersion maxVersion = null;
         for(FileVersion tmp: this.getVersions()) {
            if (maxVersion == null || maxVersion.getVersion()<tmp.getVersion()) {
               maxVersion = tmp;
            }
         }
         return maxVersion;
      }
   }
   
}


If I use following:

Code:
DetachedCriteria criteria = DetachedCriteria.forClass(File.class, "file");
List<File> files = hibernateTemplate.findByCriteria(criteria);


I get list of files. The case is that the Blobs on FileVersion are also retrieved from the database and everithing is working quite slow. I read that that Lob is not successfully implemented in several jdbc drivers, so several people are using the solution, where they have blobs in separate table (just to avoid the problem of unsucessful LAZY loading). If I make a projection, then I can select fields which will be retrieved from the database. This works, except that I need versions of file as I'm deciding in real time which version is published.

_________________
http://www.objectverse.com
http://www.alcyone.si
http://blog.alcyone.si


Top
 Profile  
 
 Post subject: Re: OneToMany HIbernate Projections problem
PostPosted: Wed Aug 24, 2011 8:09 am 
Newbie

Joined: Mon Dec 10, 2007 7:03 am
Posts: 14
1) AFAIK, using criteria, you can not project a whole object like file.publishedVersion or file.versions, you'll have to project individually file.publishedVersion.id, file.publishedVersion.file, etc.
2) Lazy loading Lobs with Hibernate+PGSQL, you may need to instrument your classes, have look at ยง19.1.7 for Hibernate Core Reference


Top
 Profile  
 
 Post subject: Re: OneToMany HIbernate Projections problem
PostPosted: Wed Aug 24, 2011 10:39 am 
Newbie

Joined: Sat Jun 09, 2007 12:29 pm
Posts: 19
I thought so. So I'll have to code additional Criteria. Thanks for your help.

_________________
http://www.objectverse.com
http://www.alcyone.si
http://blog.alcyone.si


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 5 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.