-->
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.  [ 18 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: reverse engineering oracle and yes_no
PostPosted: Tue Oct 02, 2007 3:29 am 
Newbie

Joined: Tue Oct 02, 2007 3:09 am
Posts: 5
Location: Canberra
Hi
I have an Oracle 10g table with a CHAR(1) column.

I run hbm2java with a reveng.xml file indicating that the column is a yes_no hibernate type.

I expect an annotation of @Type(type="yes_no") in the generated java class but it doesn't happen.

What am I doing wrong please?

Here's the relevant stuff:

Code:
<hibernate-reverse-engineering>

   <schema-selection match-schema="SCHEMA" match-table="TEMP_HIBERNATE" />

   <type-mapping>
      <!-- jdbc-type is name fom java.sql.Types -->
      <!-- the type-mappings are ordered -->
      <sql-type jdbc-type="CHAR" length='1' hibernate-type="yes_no"/>
      <sql-type jdbc-type="VARCHAR" length='1' hibernate-type="yes_no"/>
      <sql-type jdbc-type="NUMERIC"  hibernate-type="long" />
   </type-mapping>

</hibernate-reverse-engineering>


and in the build.xml file:

Code:
<hibernatetool destdir="${generated}" >
         <jdbcconfiguration propertyfile="${src}/er.hibernate.db.properties" packagename="database.hibernate.generated" revengfile="${src}/er.hibernate.reveng.xml" />
         <hbm2java jdk5="true" ejb3="true" />
         <!-- Export a hibernate.cfg.xml file -->
         <!--<hbm2cfgxml ejb3="true" /> -->
      </hibernatetool>


the generated java class fragment:
Code:
@Column(name="OK_YN", length=1)
    public Boolean getOkYn() {
        return this.okYn;
    }
   
    public void setOkYn(Boolean okYn) {
        this.okYn = okYn;
    }

and what I need to make it work:
Code:
@Column(name="OK_YN", length=1)
@Type(type="yes_no")
    public Boolean getOkYn() {
        return this.okYn;
    }
   
    public void setOkYn(Boolean okYn) {
        this.okYn = okYn;
    }


Thanks!
Dave


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 02, 2007 3:34 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 7:19 pm
Posts: 2364
Location: Brisbane, Australia
Looks reasonable to me but I have not tested it. Unless Max disagrees then I would think a JIRA entry should be created.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Oct 03, 2007 3:02 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 6:10 am
Posts: 8615
Location: Neuchatel, Switzerland (Danish)
looks like custom hibernate types are not generated correctly for jpa pojo's.

yes - a jira should be done for this.

_________________
Max
Don't forget to rate


Top
 Profile  
 
 Post subject:
PostPosted: Thu Mar 27, 2008 11:16 pm 
Newbie

Joined: Thu Mar 27, 2008 11:12 pm
Posts: 4
Location: Sydney
Hi,

Has there been any progress made on this? I was unable to find the related JIRA post.

Thanks!
Rob


Top
 Profile  
 
 Post subject:
PostPosted: Thu Mar 27, 2008 11:43 pm 
Newbie

Joined: Tue Oct 02, 2007 3:09 am
Posts: 5
Location: Canberra
Hi
I'm not sure who was supposed to raise the JIRA from this issue but nethertheless I have a workaround that I've been using for a number of months successfully. Namely, I got a hold of the source code and overrode the file templates/pojo/Ejb3PropertyGetAnnotation.ftl in the classpath with a copy that included this addition:
Code:
<#if pojo.getJavaTypeName(property, jdk5)="Boolean">
@${pojo.importType("org.hibernate.annotations.Type")}(type="yes_no")
</#if>


I also overrode the class EntityPOJOClass with my own version so that many to many mappings were reverse engineered correctly. Is working a treat. Perhaps I should contribute to the project but not sure how you go about it.
Cheers
Dave


Ejb3PropertyGetAnnotation.ftl:

Code:
<#if ejb3>
<#if pojo.hasIdentifierProperty()>
<#if property.equals(clazz.identifierProperty)>
${pojo.generateAnnIdGenerator()}
<#-- if this is the id property (getter)-->
<#-- explicitly set the column name for this property-->
</#if>
</#if>
<#if c2h.isManyToOne(property)>
<#--TODO support @OneToOne true and false-->   
${pojo.generateManyToOneAnnotation(property)}
<#--TODO support optional and targetEntity-->   
${pojo.generateJoinColumnsAnnotation(property)}
<#elseif c2h.isCollection(property)>
${pojo.generateCollectionAnnotation(property, cfg)}
<#else>
${pojo.generateBasicAnnotation(property)}
${pojo.generateAnnColumnAnnotation(property)}
</#if>
<#-- Dave Moten made this addition -->
<#if pojo.getJavaTypeName(property, jdk5)="Boolean">
@${pojo.importType("org.hibernate.annotations.Type")}(type="yes_no")
</#if>
<#-- down to here -->
</#if>


Top
 Profile  
 
 Post subject:
PostPosted: Fri Mar 28, 2008 2:41 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 6:10 am
Posts: 8615
Location: Neuchatel, Switzerland (Danish)
you go to our jira and contribute patches.

pretty simple ;)

When you say "it generates many-to-many correctly" i'm interested in what you mean by that ;)

_________________
Max
Don't forget to rate


Top
 Profile  
 
 Post subject: many to many
PostPosted: Fri Mar 28, 2008 6:44 am 
Newbie

Joined: Tue Oct 02, 2007 3:09 am
Posts: 5
Location: Canberra
Hi Max
Re the many to many stuff, when I reverse engineered from Oracle 10g database a many to many relationship I ended up with the two endpoint classes having the same annotation and from my rusty memory I needed to manually change one of the annotations for it all to work. So I changed the EntityPOJOClass so that it recorded in a singleton instance of a class ManyToManyMappings when each class had been paired with another in a many to many relationship so that the two sides received the different annotations. Scuse the vagueness of my description I'm not at work at the moment, I'm starting the weekend!

Perhaps this situation doesn't occur any more with updated Hibernate Tools or perhaps my understanding is bogus. Happy to have things clarified to me.

I understand that many people just reverse engineer the database once but I do it every major build so I don't want to manually intervene. It's a pretty large (hundreds of tables) data model that is worked on by many developers independently (!) and I like getting compile time indication of differences in the database over time in the development environment and also between environments.

Incidentally the reverse engineer is pretty slow (say 7 or 8 minutes for me to run). Would be nice to have a reverse engineer that obtained the oracle metadata fast so that this stage just zipped along. Haven't looked at the source for that bit yet.

Cheers
Dave


Top
 Profile  
 
 Post subject:
PostPosted: Fri Mar 28, 2008 11:12 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 6:10 am
Posts: 8615
Location: Neuchatel, Switzerland (Danish)
does your way of fixing many-to-many ensure that it is generated deterministically ? e.g. the order the tables are found in the database should not affect it.

about oracle metadata performance then OracleMetaDataDialect shold be used automatically if you use an OracleDialect ..

any chance you haven't set the initial schema selection either via hiberante.default_schema or <schema-selection> in reveng.xml ?

_________________
Max
Don't forget to rate


Top
 Profile  
 
 Post subject:
PostPosted: Sat Mar 29, 2008 10:48 pm 
Newbie

Joined: Thu Mar 27, 2008 11:12 pm
Posts: 4
Location: Sydney
Hi,

Thanks for the response Dave. Your work-around works a treat for Boolean types. Unfortunately, it doesn't work with Oracle Clobs. The problem with Clob is that the JDBC type is a Clob, the hibernate type needs to be Text, but the Java type needs to be a String. Currently, the reveng.xml schema does not support 3 different types nor does hbm2java produce proper @Type annotations.

Using your work-around for Booleans, I can add this to the Ejb3PropertyGetAnnotation.ftl:

Code:
<#if pojo.getJavaTypeName(property, jdk5)="Clob">
@${pojo.importType("org.hibernate.annotations.Type")}(type="text")
</#if>


which will render the appropriate Type annotation, but it also uses Clob as the Java type for the setters, getters, fields, and constructors. In this case, what I need is a String. I modified other ftl files to change the setters, getters, and fields to change occurrences of Clob to String, but because the constructors are generated within the Pojo java code using methods like this:

Code:
${c2j.asParameterList(pojo.getPropertyClosureForMinimalConstructor(), jdk5, pojo)}


I am unable to change the Clob type to a String in the constructor and manual changes to the domain model is required. Something I want to avoid.

Rather than hacking my way through the ftl files to work-around this, perhaps the reveng.xml schema needs the flexibility to do something like this:

Code:
<hibernate-reverse-engineering>
    <type-mapping>
        <sql-type jdbc-type="CLOB" java-type="java.lang.String" hibernate-type="org.hibernate.type.TextType" />
    </type-mapping>

...

</hibernate-reverse-engineering>


which would generate this:

Code:
private String stringX;

... appropriate constructors as needed

@Type(type="text")
public String getStringX(){
     return this.stringX;
}

public void setStringX(String stringX) {
     this.stringX = stringX;
}


The java type would need be an optional attribute.

Of course, if there is a solid work-around for this I'm very happy to try it!

Thanks!
Rob


Top
 Profile  
 
 Post subject:
PostPosted: Sun Mar 30, 2008 8:25 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 6:10 am
Posts: 8615
Location: Neuchatel, Switzerland (Danish)
salad_spork wrote:
the hibernate type needs to be Text, but the Java type needs to be a String. Currently, the reveng.xml schema does not support 3 different types nor does hbm2java produce proper @Type annotations.


Why don't you just use the hibernate-type "text" ? Then hbm2java will ask the Texttype what the java type should be and voila - you then have java.lang.String in the code.

If hbm2java does not produce proper @Type annotations and you know what/how to fix it then please submit a patch - thanks.

Quote:
Rather than hacking my way through the ftl files to work-around this, perhaps the reveng.xml schema needs the flexibility to do something like this:

Code:
<hibernate-reverse-engineering>
    <type-mapping>
        <sql-type jdbc-type="CLOB" java-type="java.lang.String" hibernate-type="org.hibernate.type.TextType" />
    </type-mapping>
</hibernate-reverse-engineering>



Since TextType getReturnedClass() already returns java.lang.String this is what will happen....I have not yet seen any proof that there is a need for a third java-type in sql-type...what we do need though is a native-type to handle DB-specific types that jdbc-types does not support/handle.

_________________
Max
Don't forget to rate


Top
 Profile  
 
 Post subject:
PostPosted: Sun Mar 30, 2008 6:55 pm 
Newbie

Joined: Thu Mar 27, 2008 11:12 pm
Posts: 4
Location: Sydney
Hey Max,

Thanks for the suggestion - but that will not work in this case. I should have probably explained in the previous post that I did attempt to use 'text' hibernate-type for this solution but ran... into other difficulties. :)

I tried using this in the reveng.xml:

Code:
<hibernate-reverse-engineering>
    <type-mapping>
        <sql-type jdbc-type="CLOB" hibernate-type="text" />
    </type-mapping>
</hibernate-reverse-engineering>

And this in the EjbPropertyGetAnnotaion.ftl:

Code:
<#if pojo.getJavaTypeName(property, jdk5)="text">
@${pojo.importType("org.hibernate.annotations.Type")}(type="text")
</#if>

But ran into an issue. The problem with 'text' is that although it does use a Java type of String, in doing so, the pojo.getJavaTypeName(property, jdk5) will return 'String' rather than 'text' and the if statement shown above will never be true. And once again, I'm stuck with manual intervention! :)

Is there a way to retrieve the hibernate-type from within the in the EjbPropertyGetAnnotaion.ftl? If there is, that will definitely solve my problem.

Thanks,
Rob


Top
 Profile  
 
 Post subject:
PostPosted: Sun Mar 30, 2008 9:52 pm 
Newbie

Joined: Tue Oct 02, 2007 3:09 am
Posts: 5
Location: Canberra
Hi Rob
I use the 'text' hibernate type for CLOBs and all works fine with some limitations. I can manipulate a clob using an object from an EntityManager but I think due to oracle limitations/bugs you may need a fresh EntityManager instance from the EntityManagerFactory if you want to eg. both write and read the a clob field on the same object obtained from one entitymanager. Don't know if this is relevant to you!
Cheers
Dave


Top
 Profile  
 
 Post subject:
PostPosted: Mon Mar 31, 2008 12:55 am 
Newbie

Joined: Thu Mar 27, 2008 11:12 pm
Posts: 4
Location: Sydney
Hey Dave,

Thanks for the response again. I'm not sure about the limitations with Oracle, it's early days and we haven't run extensive tests yet. I have no doubt we will run into similar problems though. :)

I was wondering, if you use 'text' with Clob types, how do you generate the @Type(type="text") annotation?

Or am I missing something?

Thanks,
Rob


Top
 Profile  
 
 Post subject: CLOB type
PostPosted: Mon Mar 31, 2008 1:19 am 
Newbie

Joined: Tue Oct 02, 2007 3:09 am
Posts: 5
Location: Canberra
Hi Rob
excuse my last comment, I hadn't checked my code. This is actually what I do:

I've checked my reveng.xml and the generated code (this code works!):
Code:
<hibernate-reverse-engineering>
   <type-mapping>
      <sql-type
           jdbc-type="CLOB"
           hibernate-type="org.hibernate.type.StringClobType" />
   </type-mapping> ..

Didn't have to do anything to the generated java via the .ftl (the xbody field below is a clob in the database):
Code:
    @Column(name="XBODY")
    public String getXbody() {
        return this.xbody;
    }

See how you go with this.
By the way StringClobType comes from hibernate-annotations.jar.
Dave


Top
 Profile  
 
 Post subject:
PostPosted: Mon Mar 31, 2008 4:11 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 6:10 am
Posts: 8615
Location: Neuchatel, Switzerland (Danish)
Code:
property.getType().getName()


easy - huh ? :)

Remember you have full access to the org.hibernate.cfg.* from the ftl code.

_________________
Max
Don't forget to rate


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 18 posts ]  Go to page 1, 2  Next

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.