-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 3 posts ] 
Author Message
 Post subject: NullSafeSet called two times when saving once
PostPosted: Mon Jan 21, 2008 11:07 am 
Newbie

Joined: Mon Jan 21, 2008 9:11 am
Posts: 1
Hi,

I'm trying to use the PostgreSQL's large LargeObjectManager to store byte[] with hibernate.

To do this I created a new UserType called "BlobUserType" supposed to handle the storage and
retrieval process of byte[] properties.

While storing and retrieval of blobs generally seems to work I have the following problem:

If I store an Object (here "Smallclass") which includes a byte[] property (here "largeobject") with
this code ...

Code:
        byte[] b = "ABC".getBytes();

        Session session = HibernateUtil.getSessionFactory().openSession();
        Transaction tx = session.beginTransaction();

        Smallclass smallclass = new Smallclass();
        smallclass.setLargeobject(b);
        session.save(smallclass);
       
        // session.flush();       
        tx.commit();

        session.close();
       


... the BlobUserType's nullSafeSet method is called two times, resulting in one insert and one update statement
as seen in the output. As a consequence two new oid's are requested where only one was needed.

Can anybody tell me why nullSafeSet() is called two times and how to avoid it?
Can I somehow determine if a call to nullSafeSet() is related to an insert or update?


Regards,

Frank



=== my Environment =======================================================================================

Hibernate version: Hibernate3

Database: PostgreSQL 1.6.3

=== the generated output including SQL ====================================================================

Code:
Hibernate:
    select
        nextval ('smallclass_id_seq')
Hibernate:
    insert
    into
        public.smallclass
        (largeobject, id)
    values
        (?, ?)
nullSafeSet
BlobUserType, new oid: 20803
Hibernate:
    update
        public.smallclass
    set
        largeobject=?
    where
        id=?
nullSafeSet
BlobUserType, new oid: 20804


=== my BlobUserType=======================================================================================

Code:
public class BlobUserType implements UserType {

    int oid = 0;

    public final int[] sqlTypes() {
        return new int[]{Types.INTEGER};
    }

    public Class returnedClass() {
        return byte[].class;
    }

    public final void nullSafeSet(PreparedStatement statement, Object value, int index) throws HibernateException, SQLException {
        System.out.println("nullSafeSet");
               
        if (value == null) {
            statement.setNull(index, Hibernate.INTEGER.sqlType());
        } else {
            try {
                int oid = writeBytes((byte[]) value);
                statement.setInt(index, oid);
            } catch (Exception ex) {
                Logger.getLogger(BlobUserType.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

    public Object nullSafeGet(ResultSet rs, String[] names, Object owner) throws HibernateException, SQLException {
        byte[] b = null;
        try {
            int oid = rs.getInt(names[0]);
            if (rs.wasNull()) {
                return null;
            }
            b = readBytes(oid);
        } catch (Exception ex) {
            Logger.getLogger(BlobUserType.class.getName()).log(Level.SEVERE, null, ex);
        }
        return b;
    }

    public Object assemble(Serializable cached, Object owner) throws HibernateException {
        return cached;
    }

    public Object deepCopy(Object value) throws HibernateException {
        return value;
    }

    public Serializable disassemble(Object value) throws HibernateException {
        return (Serializable) value;
    }

    public boolean equals(Object x, Object y) throws HibernateException {
        return false;
    }

    public int hashCode(Object x) throws HibernateException {
        return 0;
    }

    public boolean isMutable() {
        return true;
    }

    public Object replace(Object original, Object target, Object owner) throws HibernateException {
        return target;
    }

    public int writeBytes(byte[] bytes) throws SQLException, Exception {
        org.hibernate.classic.Session session = HibernateUtil.getSessionFactory().openSession();

        Connection con = session.connection();
        Connection pgCon = getPostgresConnection(con);

        boolean oldAutoCommit = pgCon.getAutoCommit();
        pgCon.setAutoCommit(false);

        ByteArrayInputStream inStream = new ByteArrayInputStream(bytes);
        LargeObjectManager lobj = ((org.postgresql.PGConnection) pgCon).getLargeObjectAPI();

        oid = lobj.create(LargeObjectManager.READ | LargeObjectManager.WRITE);
        System.out.println("BlobUserType, new oid: " + oid);

        LargeObject lob = lobj.open(oid, LargeObjectManager.WRITE);

        byte buf[] = new byte[2048];

        int s, tl = 0;
        while ((s = inStream.read(buf, 0, 2048)) > 0) {
            lob.write(buf, 0, s);
            tl += s;
        }
        lob.close();
        pgCon.setAutoCommit(oldAutoCommit);
        pgCon.commit();

        return oid;
    }

    public byte[] readBytes(int oid) throws SQLException, Exception {
        this.oid = oid;

        Session session = HibernateUtil.getSessionFactory().openSession();

        Connection con = session.connection();

        Connection pgCon = getPostgresConnection(con);

        boolean oldAutoCommit = pgCon.getAutoCommit();
        pgCon.setAutoCommit(false);


        LargeObjectManager lobj = ((org.postgresql.PGConnection) pgCon).getLargeObjectAPI();
        LargeObject lob = lobj.open(oid, LargeObjectManager.READ);

        byte buf[] = new byte[lob.size()];
        lob.read(buf, 0, lob.size());
        lob.close();

       
        pgCon.setAutoCommit(oldAutoCommit);
        pgCon.commit();

        return buf;
    }

    private Connection getPostgresConnection(Connection con) throws Exception {
        ConnectionWrapper wrap = (ConnectionWrapper) con;
        Jdbc2Connection realCon = (Jdbc2Connection) wrap.getWrappedConnection();
        return realCon;
    }
}


=== the mapping file =====================================================================================

Code:
<hibernate-mapping>
    <class name="db.generated.Smallclass" table="smallclass" schema="public">
        <id name="id" type="java.lang.Integer">
            <column name="id" />
            <generator class="sequence">
                <param name="sequence">smallclass_id_seq</param>
            </generator>
        </id>
        <property name="largeobject" type="db.BlobUserType">
            <column name="largeobject" />
        </property>
    </class>
</hibernate-mapping>


=== the Smallclass class =====================================================================================

Code:
public class Smallclass  implements java.io.Serializable {

     private Integer id;
     private byte[] largeobject;

    public Smallclass() {
    }

    public Smallclass(byte[] largeobject) {
       this.largeobject = largeobject;
    }
   
    public Integer getId() {
        return this.id;
    }
   
    public void setId(Integer id) {
        this.id = id;
    }
    public byte[] getLargeobject() {
        return this.largeobject;
    }
   
    public void setLargeobject(byte[] largeobject) {
        this.largeobject = largeobject;
    }
}

_________________
Frank


Top
 Profile  
 
 Post subject: can u help me
PostPosted: Tue Jan 29, 2008 3:46 am 
Newbie

Joined: Fri Jan 25, 2008 8:32 am
Posts: 15
i am trying to insert the value in databases but it is fired by hibernate...

Hibernate: select unwanted0_.ID as ID0_0_, unwanted0_.name as name0_0_ from UNWANTED unwanted0_ where unwanted0_.ID=?
org.hibernate.MappingException: Unknown entity: java.lang.Long
at org.hibernate.impl.SessionFactoryImpl.getEntityPersister(SessionFactoryImpl.java:548)
at org.hibernate.impl.SessionImpl.getEntityPersister(SessionImpl.java:1338)
at org.hibernate.engine.ForeignKeys.isTransient(ForeignKeys.java:180)
at org.hibernate.event.def.AbstractSaveEventListener.getEntityState(AbstractSaveEventListener.java:487)
at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:70)
at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:38)
at org.hibernate.impl.SessionImpl.firePersist(SessionImpl.java:618)
at org.hibernate.impl.SessionImpl.persist(SessionImpl.java:592)
at org.hibernate.impl.SessionImpl.persist(SessionImpl.java:596)
at org.apache.jsp.unwanted_jsp._jspService(unwanted_jsp.java:131)
at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:97)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:332)
at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:314)
at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:264)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:269)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:174)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:117)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:108)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:151)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:874)
at org.apache.coyote.http11.Http11BaseProtocol$Http11ConnectionHandler.processConnection(Http11BaseProtocol.java:665)
at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:528)
at org.apache.tomcat.util.net.LeaderFollowerWorkerThread.runIt(LeaderFollowerWorkerThread.java:81)
at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:689)
at java.lang.Thread.run(Unknown Source)

org.apache.jasper.JasperException: Exception in JSP: /unwanted.jsp:4

1: <%@ include file="protected.jsp" %>
2: <%@ include file="header.jsp" %>
3: <%
4: Long id=Long.valueOf(request.getParameter("Id"));
5: Session sess = HibernateUtil.currentSession();
6: Unwanted u= new Unwanted();
7:


Stacktrace:
my mapping looks like it..
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
<class name="com.ats.custFlight.pojo.Unwanted" table="unwanted" lazy="false">
<id column="ID" name="id" type="java.lang.Long"/>
<property column="name" name="name" type="java.lang.String"/>
</class>
</hibernate-mapping>



my code to upload data is--

Long id=Long.valueOf(request.getParameter("Id"));
Session sess = HibernateUtil.currentSession();
Unwanted u= new Unwanted();

Unwanted u2 = (Unwanted) sess.get (Unwanted.class,(long)77);
u.setId(id);
u.setName("RAHUL");
try{
sess.save(u);
}catch( Exception e )
{
e.printStackTrace();
}
System.out.println(" size is " + u.getId());

my hibernate.util code is--
package com.ats.custFlight.util;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.hibernate.*;
import org.hibernate.cfg.*;

public class HibernateUtil {

private static Log log = LogFactory.getLog(HibernateUtil.class);

private static final SessionFactory sessionFactory;

static {
try {
// Create the SessionFactory
sessionFactory = new Configuration().configure().buildSessionFactory();

} catch (Throwable ex) {
// Make sure you log the exception, as it might be swallowed
log.error("Initial SessionFactory creation failed.", ex);
ex.printStackTrace();
throw new ExceptionInInitializerError(ex);
}
}

public static final ThreadLocal < Session > session = new ThreadLocal < Session > ();

public static Session currentSession() throws HibernateException {
Session s = (Session) session.get();
// Open a new Session, if this Thread has none yet
if (s == null) {
s = sessionFactory.openSession();
session.set(s);
}
return s;
}

public static void closeSession() throws HibernateException {
Session s = (Session) session.get();
session.set(null);
if (s != null)
s.close();
}
}
and JAVA CLASS IS..

package com.ats.custFlight.pojo;

public class Unwanted {

Long id;
String name;

public String getName() {
return name;
}

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

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}
}



pkaf wrote:
Hi,

I'm trying to use the PostgreSQL's large LargeObjectManager to store byte[] with hibernate.

To do this I created a new UserType called "BlobUserType" supposed to handle the storage and
retrieval process of byte[] properties.

While storing and retrieval of blobs generally seems to work I have the following problem:

If I store an Object (here "Smallclass") which includes a byte[] property (here "largeobject") with
this code ...

Code:
        byte[] b = "ABC".getBytes();

        Session session = HibernateUtil.getSessionFactory().openSession();
        Transaction tx = session.beginTransaction();

        Smallclass smallclass = new Smallclass();
        smallclass.setLargeobject(b);
        session.save(smallclass);
       
        // session.flush();       
        tx.commit();

        session.close();
       


... the BlobUserType's nullSafeSet method is called two times, resulting in one insert and one update statement
as seen in the output. As a consequence two new oid's are requested where only one was needed.

Can anybody tell me why nullSafeSet() is called two times and how to avoid it?
Can I somehow determine if a call to nullSafeSet() is related to an insert or update?


Regards,

Frank



=== my Environment =======================================================================================

Hibernate version: Hibernate3

Database: PostgreSQL 1.6.3

=== the generated output including SQL ====================================================================

Code:
Hibernate:
    select
        nextval ('smallclass_id_seq')
Hibernate:
    insert
    into
        public.smallclass
        (largeobject, id)
    values
        (?, ?)
nullSafeSet
BlobUserType, new oid: 20803
Hibernate:
    update
        public.smallclass
    set
        largeobject=?
    where
        id=?
nullSafeSet
BlobUserType, new oid: 20804


=== my BlobUserType=======================================================================================

Code:
public class BlobUserType implements UserType {

    int oid = 0;

    public final int[] sqlTypes() {
        return new int[]{Types.INTEGER};
    }

    public Class returnedClass() {
        return byte[].class;
    }

    public final void nullSafeSet(PreparedStatement statement, Object value, int index) throws HibernateException, SQLException {
        System.out.println("nullSafeSet");
               
        if (value == null) {
            statement.setNull(index, Hibernate.INTEGER.sqlType());
        } else {
            try {
                int oid = writeBytes((byte[]) value);
                statement.setInt(index, oid);
            } catch (Exception ex) {
                Logger.getLogger(BlobUserType.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

    public Object nullSafeGet(ResultSet rs, String[] names, Object owner) throws HibernateException, SQLException {
        byte[] b = null;
        try {
            int oid = rs.getInt(names[0]);
            if (rs.wasNull()) {
                return null;
            }
            b = readBytes(oid);
        } catch (Exception ex) {
            Logger.getLogger(BlobUserType.class.getName()).log(Level.SEVERE, null, ex);
        }
        return b;
    }

    public Object assemble(Serializable cached, Object owner) throws HibernateException {
        return cached;
    }

    public Object deepCopy(Object value) throws HibernateException {
        return value;
    }

    public Serializable disassemble(Object value) throws HibernateException {
        return (Serializable) value;
    }

    public boolean equals(Object x, Object y) throws HibernateException {
        return false;
    }

    public int hashCode(Object x) throws HibernateException {
        return 0;
    }

    public boolean isMutable() {
        return true;
    }

    public Object replace(Object original, Object target, Object owner) throws HibernateException {
        return target;
    }

    public int writeBytes(byte[] bytes) throws SQLException, Exception {
        org.hibernate.classic.Session session = HibernateUtil.getSessionFactory().openSession();

        Connection con = session.connection();
        Connection pgCon = getPostgresConnection(con);

        boolean oldAutoCommit = pgCon.getAutoCommit();
        pgCon.setAutoCommit(false);

        ByteArrayInputStream inStream = new ByteArrayInputStream(bytes);
        LargeObjectManager lobj = ((org.postgresql.PGConnection) pgCon).getLargeObjectAPI();

        oid = lobj.create(LargeObjectManager.READ | LargeObjectManager.WRITE);
        System.out.println("BlobUserType, new oid: " + oid);

        LargeObject lob = lobj.open(oid, LargeObjectManager.WRITE);

        byte buf[] = new byte[2048];

        int s, tl = 0;
        while ((s = inStream.read(buf, 0, 2048)) > 0) {
            lob.write(buf, 0, s);
            tl += s;
        }
        lob.close();
        pgCon.setAutoCommit(oldAutoCommit);
        pgCon.commit();

        return oid;
    }

    public byte[] readBytes(int oid) throws SQLException, Exception {
        this.oid = oid;

        Session session = HibernateUtil.getSessionFactory().openSession();

        Connection con = session.connection();

        Connection pgCon = getPostgresConnection(con);

        boolean oldAutoCommit = pgCon.getAutoCommit();
        pgCon.setAutoCommit(false);


        LargeObjectManager lobj = ((org.postgresql.PGConnection) pgCon).getLargeObjectAPI();
        LargeObject lob = lobj.open(oid, LargeObjectManager.READ);

        byte buf[] = new byte[lob.size()];
        lob.read(buf, 0, lob.size());
        lob.close();

       
        pgCon.setAutoCommit(oldAutoCommit);
        pgCon.commit();

        return buf;
    }

    private Connection getPostgresConnection(Connection con) throws Exception {
        ConnectionWrapper wrap = (ConnectionWrapper) con;
        Jdbc2Connection realCon = (Jdbc2Connection) wrap.getWrappedConnection();
        return realCon;
    }
}


=== the mapping file =====================================================================================

Code:
<hibernate-mapping>
    <class name="db.generated.Smallclass" table="smallclass" schema="public">
        <id name="id" type="java.lang.Integer">
            <column name="id" />
            <generator class="sequence">
                <param name="sequence">smallclass_id_seq</param>
            </generator>
        </id>
        <property name="largeobject" type="db.BlobUserType">
            <column name="largeobject" />
        </property>
    </class>
</hibernate-mapping>


=== the Smallclass class =====================================================================================

Code:
public class Smallclass  implements java.io.Serializable {

     private Integer id;
     private byte[] largeobject;

    public Smallclass() {
    }

    public Smallclass(byte[] largeobject) {
       this.largeobject = largeobject;
    }
   
    public Integer getId() {
        return this.id;
    }
   
    public void setId(Integer id) {
        this.id = id;
    }
    public byte[] getLargeobject() {
        return this.largeobject;
    }
   
    public void setLargeobject(byte[] largeobject) {
        this.largeobject = largeobject;
    }
}


Top
 Profile  
 
 Post subject:
PostPosted: Fri Mar 28, 2008 8:06 am 
Newbie

Joined: Fri Mar 07, 2008 6:01 am
Posts: 7
Location: Brussels, BELGIUM
@rhlpnt :
You set the ID of your object before saving, and the mapping does not have the generator type "assigned" for the ID.
It then searches first for the ID to update the record...

Did you manage to avoid the select before insertion? I try to find it out...


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 3 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.