Question

I am having some trouble properly retrieving blob data from my database using java in my JSF 2.0 application. The first problem I am having is on my getter method for the Blob named "file" I get an error saying that "Basic attributes can only be of the following types..." basically saying that I can not return a Blob object. My code looks like what is below. Even with the error my code compiles. I have created a test method (the last bit of code below) and tried to test but it gives me runtime errors.

Controller Bean

import java.sql.Blob;

@Entity
@Table(named = "files")
@NamedQueries( {
    @NamedQuery(name = "MyBlob.getBlob",
    query = from MyBlob WHERE fileId =: fileId")
})
public class MyBlob implements Serializable {

     private Integer fileId;
     private Blob file;
     ...

     public Integer getFileId() {
         return fileId;
     }

     public void setFileId() {
         this.fileId = fileId;
     }

     public Blob getFile() {
         return file;
     }

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

     ....

}

BlobDao.java File method to get blob

public MyBlob getBlob(Integer fileId) throws HibernateException {
    Session session = getSessionFactory().openSession();
    try { 
      MyBlob blob = (MyBlob)session.getNamedQuery("MyBlob.getBlob").setInteger("fileId", fileId).uniqueResult();
      return blob;
    } catch(HibernateException e) {
         throw new HibernateException(e);
    } finally {
        session.close();
    }
}

TestDao.java

@Test
public void testBlob() {

    MyBlob test = blobdao.getBlob(1);  // 1 is a fileId that exists in the DB with a blob image file.
    Blob blob = test.getFile();
    try {
        System.out.println(blob.length));   //this prints a number but I dont think the right one. 
        if(blob.length > 0 ) {
             System.out.println(blob.toString() ); //errors out here
        }
    } catch(SQLException e) {
          return System.out.println("Failed");
    }
}

I am not sure that I am doing this right at all. Any help would be great. Thanks.

Was it helpful?

Solution

on my getter method for the Blob named "file" I get an error saying that "Basic attributes can only be of the following types..." basically saying that I can not return a Blob object.

Indeed, a java.sql.Blob is not a persistent field or property that can be mapped by Hibernate/JPA. The JPA specification puts is like this:

2.1.1 Persistent Fields and Properties

...

The persistent fields or properties of an entity may be of the following types: Java primitive types; java.lang.String; other Java serializable types (including wrappers of the primitive types, java.math.BigInteger, java.math.BigDecimal, java.util.Date, java.util.Calendar, java.sql.Date, java.sql.Time, java.sql.Timestamp, user-defined serializable types, byte[], Byte[], char[], and Character[]); enums; entity types and/or collections of entity types; and embeddable classes (see section 2.1.5).

You should probably use the Lob annotation and change your attribute type. From the specification:

9.1.19 Lob Annotation

A Lob annotation specifies that a persistent property or field should be persisted as a large object to a database-supported large object type. Portable applications should use the Lob annotation when mapping to a database Lob type. The Lob annotation may be used in conjunction with the Basic annotation. A Lob may be either a binary or character type. The Lob type is inferred from the type of the persistent field or property, and except for string and character-based types defaults to Blob.

...

Example 1:

@Lob @Basic(fetch=EAGER)
@Column(name="REPORT")
protected String report;

Example 2:

@Lob @Basic(fetch=LAZY)
@Column(name="EMP_PIC", columnDefinition="BLOB NOT NULL")
protected byte[] pic;

References

  • JPA 1.0 specification
    • Section 2.1.1 "Persistent Fields and Properties"
    • Section 9.1.19 "Lob Annotation"

Well my exact requirements are to retrieve the Blob from the database either as a Blob or a byte[], whatever works, and then somehow convert that into a valid InputStream object.

What about ByteArrayInputStream(byte[])?

OTHER TIPS

I am guessing the Blob object is your Entity. It might help if you print that as well.

Make sure your Blob returns byte[]

@Basic(fetch = FetchType.LAZY)
@Lob             
@Column(length = 104857600, nullable = false)
private byte[] data;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top