-->
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.  [ 8 posts ] 
Author Message
 Post subject: DB2 and byte[] primary key columns
PostPosted: Mon Nov 24, 2003 12:47 pm 
Beginner
Beginner

Joined: Mon Nov 24, 2003 12:44 pm
Posts: 40
I am having difficulties with using middlegen and hibernator against UDB7.2 fp5.

The table definition is as follows...

Code:
Column                         Type      Type
name                           schema    name               Length   Scale Nulls
------------------------------ --------- ------------------ -------- ----- -----
REQUEST_ID                     SYSIBM    CHARACTER                13     0 No   
TYPE                           SYSIBM    CHARACTER                 1     0 No   
VALUATION_DATE                 SYSIBM    DATE                      4     0 Yes   
PRCSSNG_TMSTMP                 SYSIBM    TIMESTAMP                10     0 No   
IN_FORCE_INDICATOR             SYSIBM    CHARACTER                 1     0 No   
LWR_INFLTN_ASSMPTN             SYSIBM    DOUBLE                    8     0 No   
UPPR_INFLTN_ASSMPT             SYSIBM    DOUBLE                    8     0 No   
SCTN148_EXCSS_ASSM             SYSIBM    DOUBLE                    8     0 No   
REQUESTED_BY                   SYSIBM    CHARACTER                 7     0 No   
AUTHORISED_BY                  SYSIBM    CHARACTER                 7     0 Yes   
MVMNTS_INDCTR                  SYSIBM    CHARACTER                 1     0 No   
STATUS                         SYSIBM    CHARACTER                 1     0 Yes   


Middlegen 2.0b1 generates the following...

Code:
<?xml version="1.0"?>
  <!DOCTYPE hibernate-mapping PUBLIC
    "-//Hibernate/Hibernate Mapping DTD 2.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd" >
   
  <hibernate-mapping>
    <!--
      Created by Middlegen Hibernate plugin
         http://boss.bekk.no/boss/middlegen/
         http://hibernate.sourceforge.net/
     -->

  <class
     name="com.landg.bpa.hibernate.Tbpvalreqi"
     table="TBPVALREQI"
  >

    <id
        name="requestId"
        type="byte[]"
        column="REQUEST_ID"
    >
        <generator class="assigned" />
    </id>

    <property
        name="type"
        type="java.lang.String"
        column="TYPE"
        not-null="true"
        length="1"
    />
    ....More....

    <!-- associations -->

  </class>
</hibernate-mapping>

When I try and use hibernator 0.9.6 within eclipse, i get the following...

Code:
Adding Mapping - C:/WorkspaceEclipse/hibernate/BPADBLayer/src/com/landg/bpa/hibernate/Tbpvalreqi.hbm.xml
net.sf.hibernate.MappingException: Could not interpret type: byte[]
   at net.sf.hibernate.cfg.Binder.getTypeFromXML(Binder.java:788)
   at net.sf.hibernate.cfg.Binder.bindValue(Binder.java:354)
   at net.sf.hibernate.cfg.Binder.bindRootClass(Binder.java:224)
   at net.sf.hibernate.cfg.Binder.bindRoot(Binder.java:1095)
   at net.sf.hibernate.cfg.Configuration.add(Configuration.java:230)
   at net.sf.hibernate.cfg.Configuration.addFile(Configuration.java:155)
   at net.sf.hibernator.HibernateConnection.createConnection(HibernateConnection.java:168)
   at net.sf.hibernator.views.ConnectionView$8.run(ConnectionView.java:199)
   at org.eclipse.jface.operation.ModalContext$ModalContextThread.run(ModalContext.java:101)
rethrown as net.sf.hibernate.MappingException: Could not interpret type: byte[]
   at net.sf.hibernate.cfg.Configuration.addFile(Configuration.java:159)
   at net.sf.hibernator.HibernateConnection.createConnection(HibernateConnection.java:168)
   at net.sf.hibernator.views.ConnectionView$8.run(ConnectionView.java:199)
   at org.eclipse.jface.operation.ModalContext$ModalContextThread.run(ModalContext.java:101)
Caused by: net.sf.hibernate.MappingException: Could not interpret type: byte[]
   at net.sf.hibernate.cfg.Binder.getTypeFromXML(Binder.java:788)
   at net.sf.hibernate.cfg.Binder.bindValue(Binder.java:354)
   at net.sf.hibernate.cfg.Binder.bindRootClass(Binder.java:224)
   at net.sf.hibernate.cfg.Binder.bindRoot(Binder.java:1095)
   at net.sf.hibernate.cfg.Configuration.add(Configuration.java:230)
   at net.sf.hibernate.cfg.Configuration.addFile(Configuration.java:155)
   ... 3 more


Is this a case of UDB not supporting byte[] types. I don't understand why middlegen, generates a byte[] type for a key column and java.lang.String types for non-key columns when the database type is CHARACTER.

Can you offer any suggestions.

Many thanks
Chris


Top
 Profile  
 
 Post subject:
PostPosted: Mon Nov 24, 2003 12:53 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
type="binary"


Top
 Profile  
 
 Post subject:
PostPosted: Wed Nov 26, 2003 6:55 am 
Beginner
Beginner

Joined: Mon Nov 24, 2003 12:44 pm
Posts: 40
Gavin, I'm not sure I understand. Why type="binary" when the key column is CHARACTER 13. Why not type="java.lang.String"?

Anyway, I changed the type="byte[]" to type="binary" in the *.hbm.xml file and tried the hibernator product again. I got the following result...

[code]net.sf.hibernate.MappingException: illegal use of an array as an identifier (arrays don't reimplement equals)
at net.sf.hibernate.cfg.Binder.bindRootClass(Binder.java:230)
at net.sf.hibernate.cfg.Binder.bindRoot(Binder.java:1095)
at net.sf.hibernate.cfg.Configuration.add(Configuration.java:230)
at net.sf.hibernate.cfg.Configuration.addFile(Configuration.java:155)
at net.sf.hibernator.HibernateConnection.createConnection(HibernateConnection.java:168)
at net.sf.hibernator.views.ConnectionView$8.run(ConnectionView.java:199)
at org.eclipse.jface.operation.ModalContext$ModalContextThread.run(ModalContext.java:101)
rethrown as net.sf.hibernate.MappingException: illegal use of an array as an identifier (arrays don't reimplement equals)
at net.sf.hibernate.cfg.Configuration.addFile(Configuration.java:159)
at net.sf.hibernator.HibernateConnection.createConnection(HibernateConnection.java:168)
at net.sf.hibernator.views.ConnectionView$8.run(ConnectionView.java:199)
at org.eclipse.jface.operation.ModalContext$ModalContextThread.run(ModalContext.java:101)
Caused by: net.sf.hibernate.MappingException: illegal use of an array as an identifier (arrays don't reimplement equals)
at net.sf.hibernate.cfg.Binder.bindRootClass(Binder.java:230)
at net.sf.hibernate.cfg.Binder.bindRoot(Binder.java:1095)
at net.sf.hibernate.cfg.Configuration.add(Configuration.java:230)
at net.sf.hibernate.cfg.Configuration.addFile(Configuration.java:155)
... 3 more[/code]


Thanks for the help so far.
Regards
Chris


Top
 Profile  
 
 Post subject:
PostPosted: Wed Nov 26, 2003 10:23 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
oh its an id property

please see "custom identifier type" pattern on the wiki.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jan 13, 2004 3:00 am 
Beginner
Beginner

Joined: Mon Nov 24, 2003 12:44 pm
Posts: 40
Finally got back to looking at this stuff again. I found out why Middlegen was picking byte[]. The Primary Key columns were actually CHAR FOR BIT DATA.

Having settled on byte[]. I looked through the Hibernate supported types and byte[] was in there....

net.sf.hibernate.type.TypeFactory

basics.put( byte[].class.getName(), Hibernate.BINARY);


I will look at the "custom identifier type". I presume this would be plugged into the Middlegen ANT script, which would then generate slightly different *.hbm.xml files i.e chaging the references to byte[] to something else.
Am I correct in this assumption?

Best regards
Chris


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jan 20, 2004 6:29 am 
Beginner
Beginner

Joined: Mon Nov 24, 2003 12:44 pm
Posts: 40
It suddenly dawned on me what you meant by type=binary. I changed the type="byte[]" references in the hbm.xml files to type="binary", leaving the java files as byte[] and got a bit further. doh!

Now Hibernator appears to be attempting to parse the files, manages the first of 3 and seizes up, so that the query view never becomes editable.

I'm using Eclipse 3m3 which appeared to have the right eclipse plugin versions to enable me to install hibernator and hibernate as a plugin project so I could debug through the process. I imported the source for hibernator 0.9.6 and hibernate 2.0.3, which appeared to be the matched pair. (Hopefully, hibernator will be upgraded soon to use hibernate 2.1.1), but hit a NoClassefFound exception for a bean-utils class which is definitely there in the plugin dependencies. I was hoping this would all be a bit easier than this but there ya go. I like a challenge!!!

Nuff said for now.

Chris


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jan 22, 2004 5:29 am 
Beginner
Beginner

Joined: Mon Nov 24, 2003 12:44 pm
Posts: 40
Finally got it. Gavins posts above were the correct pointer, just a little too brief to make it too easy.
Anyway, for anyone hitting the same problem as I did, you do have to create a custom type as per the wiki article. Here are the ones I created with at least some of the code bugs corrected from the article...

Code:
package com.myco.hibernate.types;

import java.io.Serializable;
import java.util.Arrays;

public final class Bytes implements Serializable {
   
    private final byte[] _bytes;

    public Bytes(byte[] bytes) {
        _bytes = bytes;
    }

    public boolean equals(Object other) {
        if (other == null || !(other instanceof Bytes)) {
            return false;
        }
        return Arrays.equals(((Bytes) other)._bytes, _bytes);
    }

    public byte[] getBytes() {
        byte[] dest = new byte[_bytes.length];
        System.arraycopy(_bytes, 0, dest, 0, _bytes.length);
        return dest;
    }

    public String toString() {
        return _bytes.toString();
    }
}


Code:
package com.myco.hibernate.types;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;

import net.sf.hibernate.HibernateException;
import net.sf.hibernate.UserType;

public class BytesType implements UserType {
   
    private static final int[] SQL_TYPES = new int[] { Types.VARBINARY };

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

    public boolean equals(Object x, Object y) {
        return (x == y) || (x != null && y != null && x.equals(y));
    }

    public boolean isMutable() {
        return false;
    }

    public Object nullSafeGet(ResultSet rs, String[] names, Object owner) throws HibernateException, SQLException {
        byte[] bytes = rs.getBytes(names[0]);
        if (rs.wasNull())
            return null;
        return new Bytes(bytes);
    }

    public void nullSafeSet(PreparedStatement st, Object value, int index) throws HibernateException, SQLException {
        if (value == null) {
            st.setNull(index, Types.VARBINARY);
        }
        else {
            st.setBytes(index, ((Bytes) value).getBytes());
        }
    }

    public Class returnedClass() {
        return Bytes.class;
    }

    public int[] sqlTypes() {
        return SQL_TYPES;
    }
}



Code:
package com.myco.hibernate.types;

import java.io.Serializable;
import java.sql.SQLException;

import net.sf.hibernate.HibernateException;
import net.sf.hibernate.engine.SessionImplementor;
import net.sf.hibernate.id.IdentifierGenerator;
import net.sf.hibernate.id.UUIDStringGenerator;

public class BytesGenerator implements IdentifierGenerator {

    private IdentifierGenerator uuid = new UUIDStringGenerator();

    public Serializable generate(SessionImplementor session, Object object) throws HibernateException {
        try {
            return new Bytes(((String) uuid.generate(session, object)).getBytes());
        }
        catch (SQLException e) {
            throw new HibernateException("SQL Exception caught", e);
        }
    }
}


The hbm.xml file is then changed as follows...

Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
    "-//Hibernate/Hibernate Mapping DTD 2.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd" >
   
<hibernate-mapping>
<!--
    Created by the Middlegen Hibernate plugin

    http://boss.bekk.no/boss/middlegen/
    http://hibernate.sourceforge.net/
-->

<class
    name="com.myco.myapp.hibernate.Tbpperson"
    schema="MYAPP"
    table="TBPPERSON"
>

    <id
        name="personId"
        type="com.myco.hibernate.types.BytesType"
        column="PERSON_ID"
    >
        <generator class="com.landg.bpa.hibernate.types.BytesGenerator" />
    </id>

    <property
        name="surname"
        type="java.lang.String"
        column="SURNAME"
        not-null="true"
        length="40"
    />
    <property
        name="firstForename"
        type="java.lang.String"
        column="FIRST_FORENAME"
        length="18"
    />
    ...etc

    <!-- associations -->

</class>
</hibernate-mapping>


and finally the java file....

Code:
package com.myco.myapp.hibernate;

import java.io.Serializable;
import java.util.Date;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ToStringBuilder;

import com.myco.hibernate.types.Bytes;

/** @author Hibernate CodeGenerator */
public class Tbpperson implements Serializable {

    /** identifier field */
    private Bytes personId;
    /** persistent field */
    private String surname;

    /** nullable persistent field */
    private String firstForename;

    ...etc

}


Note: You have to change ALL the files (generated by Middlegen in my case) to use Bytes instead of byte[] for the ID column.

Hope this is of use to someone out there.

Chris

P.S I got the Eclipse plugin working in the end so I could debug it, which is how I understood why I needed to do the above.
P.P.S I couldn't get Hibernator 0.9.6 working in Eclipse 3m6, the APIs have changed. It works with 3m3 fine though.


Top
 Profile  
 
 Post subject:
PostPosted: Sat Jan 24, 2004 11:38 am 
Beginner
Beginner

Joined: Mon Nov 24, 2003 12:44 pm
Posts: 40
Out of interest, if the use of binary data is common in ID fields, why doesn't Hibernate provide a Bytes like class for use by tools like Middlegen, when a FOR BIT DATA key column type is detected?

Regards
Chris


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