Hibernate reverse engineers (oracle) NUMBER to zero-precision big_decimal - oracle

When reverse engineering a column in an Oracle view with data type "NUMBER", the resultant column in *.hbm.xml is a big_decimal with precision="0".
I also use these mapping files with Derby to do acceptance tests, but from the Derby docs:
The precision must be between 1 and 31.
I do not have control over the definition of the view. I read through the reverse engineering docs and I can't see a way of controlling the precision.
How do I instruct hibernate to give me a valid (derby) precision?

you should modify hibernate.reveng.xml as example below with your needs (precision,scale) and set output type (hibernate-type) then generate classess and mapping files.
<hibernate-reverse-engineering>
<type-mapping>
<sql-type jdbc-type="NUMERIC" precision="1" scale="0" hibernate-type="boolean"/>
<sql-type jdbc-type="NUMERIC" precision="22" scale="0" hibernate-type="long"/>
<sql-type jdbc-type="OTHER" hibernate-type="..."/>
</type-mapping>
....

Related

ODI 12c DB to XML

I am trying to map oracle db to an XML file and have come to a blocker.Would appreciate any help.My xml file has the following structure
<Root>
<Import>
<Add-Item1>
.
.
<Add-Item n></Add-Item n>
</Import>
Odi 12c xml driver generates a ParentElementFK CurrentElementPK and CurrentElementOrder,corresponding to every tag that is there in xml.
My issue is in spite of scouring oracle forums i have not found a good definition of what data we need to populate in these ODI generated columns. Are these only for maintaining the hierarchical relationship?if so,wouldn't they be populated automatically on reverse engineering?.suppose the data that i would fill in this xml structure would be of an item with properties-brand,description item id(child tags under ) .Do these generated columns play any role in the mapping?
I have tried multiple things and found the answer myself . here is what i understood. Suppose you have Import complex type and Add-Item complexType . It will generate two datastores in model one for Import and one for Add-Item. First populate the primary key of the Import Complex type. Then you will see IMport FK in the Add-item complex type populate this value with the same value as you populated above that works . All other order and can be left optional if you don't need any particular order of these

DB Insert if not present - Spring Integration

We have a int-jms:message-driven-channel-adapter --> a transformer --> a filter --> another transformer --> int-jdbc:outbound-channel-adapter (to insert in table_1)
(considering --> as channels)
I want to change this flow to insert into 2 tables instead of 1 but for table_2 I want to insert only if data corresponding to some fields in the message is already not present in the table i.e. insert if not present.
One thing I figured is that I will now need a pub-sub-channel with ignore-failures=false to split the flow into 2 tables.
My question is that what component should I use to select the data to check if data exists in table_2? I first thought inbound-channel-adapter is the right choice but couldn't figure out how to slide it between 2 components i.e. say a transformer and outbound-channel-adapter.
Some things I can think of are:
1. Use a filter, passing it jdbcTemplate so that the filter itself can fire a JDBC query to accept if record doesn't exist.
2. Use a outbound-channel-adapter and the insert query should have the check for data existence also, something like insert-if. I am not sure if Oracle has something like this. I am researching.
Please point me to an example or documentation or tell me the best way.
Thanks
Actually you can use
<chain>
<header-enricher>
<header name="original" expression="payload"/>
</header-enricher>
<int-jdbc:outbound-gateway query="SELECT count(*) from TABLE where ..."/>
<filter expression="payload == 0"/>
<transformer expression="headers.original"/>
</chain>
From other side <filter> with JdbcTemplate direct usage is good choice too.
Re. insert-if. It can work too if you have a unique constraint on the table. In this case an Exception will be thrown. And if you have <publish-subscribe-channel ignore-failures=false>, it would work too.

How do I create an index online with liquibase?

I have a migration that will create an index in a table of our Oracle database. The DBA would like the index to be created ONLINE. (Something like CREATE INDEX ..... ONLINE;) Is there something I can add to the tag below to accomplish what I want or do I need to write the SQL into the migration?
<createIndex tableName="USER" indexName="IX_USER_TX_ID">
<column name="TX_ID" />
</createIndex>
There is no standard tag to specify it as ONLINE. Your 3 options to create it as ONLINE are:
Fall back to the tag where you specify the exact SQL you want
Use the modifySql tag to append to the generated SQL.
Create an extension to createIndex that always generates ONLINE at the end of the SQL or adds a parameter to createIndex that allows you to control if it is added or not.
Option #2 is probably the best mix of easy yet flexible and would look something like this:
<changeSet id="1" author="nvoxland">
<createIndex tableName="USER" indexName="IX_USER_TX_ID">
<column name="TX_ID" />
</createIndex>
<modifySql dbms="oracle">
<append value=" ONLINE"/>
</modifySql>
</changeSet>
Notice the space in the value tag. Append does a very simple text append with no built-in logic.

Convert Int32 to Oracle number(5) with EF4

I am using EF 4 (database first, model fully generated from it) with an oracle 10g database and I have a problem with one field.
My field is defined as a NUMBER(5) in my database. In my model, EF has defined it as a short.
My problem is that i have some values that are greater than 32,767 (max of a short)
I found this post : Entity Framework generates short instead of int. I follow the instruction and it works, my model contain now Int32 values.
But I have a new problem :
Error 2019: Member Mapping specified is not valid. The type 'Edm.Int32[Nullable=True,DefaultValue=]' of member 'XX' in type 'Model.XXX' is not compatible with 'OracleEFProvider.number[Nullable=True,DefaultValue=,Precision=5,Scale=0]' of member 'XX' in type 'Model.Store.XXX'.
This error is always show in the Error List tab of Visual Studio. However, the build success, and it half works:
read a value in database works
write a value do not work : 99999 was transformed in -31073 (see edit)
Is there a solution to have it works on both ways ?
BTW, is there any way to tell entity to use int32 for oracle INTEGER fields ? It use decimal by default.
EDIT
While debuging step by step, I found why my value was -31073. I forgot this line :
dao.Value = (short)dto.Value;
My two values were int, but the implicit conversion in short was the origin.
I found how to remove the error.
I edited the edmx file in xml mode, found my field in the ssdl section :
<Property Name="SIT_INSEE" Type="number" Precision="5" />
I removed the Precision="5" and the warning disappeared.
Just to add my two cents in case anyone else is having similar problems. I noticed if you add the following to mappings in web.config and then recreate the edmx model from scratch (delete it and re-generate from database) it resolves some of these issues. Where simply adding the values to web.config resolved nothing (probably re-generating some of the code behind the scenes would be my guess).
<oracle.dataaccess.client>
<settings>
<add name="int32" value="edmmapping number(9,0)" />
</settings>
</oracle.dataaccess.client>

Mapping a long text string in Oracle and NHibernate

Using NHibernate 3.1 with both SQL Server and Oracle DBs, we need to store a text string that is longer than 4000 characters. The text is actually XML, but that is not important - we just want to treat it as raw text. With SQL Server, this is easy. We declare the column as NVARCHAR(MAX) and map it thusly:
<property name="MyLongTextValue" length="100000"/>
The use of the length property tells NHibernate to expect a string that may be longer than 4000 characters.
For the life of me, I cannot figure out how to make this work on Oracle 11g. I've tried declaring the column as both XMLTYPE and LONG with no success. In the first case, we end up with ORA-01461: can bind a LONG value only for insert into a LONG column when trying to insert a row. In the second case, the data is inserted correctly but comes back as an empty string when querying.
Does anyone know how to make this work? The answer has to be compatible with both SQL Server and Oracle. I'd rather not have to write custom extensions such as user types and driver subclasses. Thanks.
You should use something like this
<property name="MyLongTextValue" length="100000" type="StringClob"
not-null="false"/>
This should work with Oracle CLOB type and SqlServer NTEXT type.
Make sure the property on your model is nullable
public virtual string MyLongTextValue {get;set;}
You should always use the Oracle.DataAccess when dealing with CLOBs
For whom this may interest, I solved my problem following the step 3 of this article:
3. Using correct Mapping attributes: type="AnsiString"
Normally we can use type="String" default for CLOB/NCLOB. Try to use > type="AnsiString" if two steps above not work.
<property name="SoNhaDuongPho" column="SO_NHA_DUONG_PHO" type="AnsiString"/>
In my case I set it with FluentNHibernate:
.CustomType("AnsiString")
You might be interested in this article.
<property column="`LARGE_STRING`" name="LargeString" type="StringClob" sql-type="NCLOB" />

Resources