Oracle NVARCHAR2(Max) using nhibernate 2.1 - oracle

Here is my problem: I have Oracle Database 10g and I use nhibernete 2.1 for the mapping. Now when I create a table in oracle My table's hbm.xml file is like this
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="AssembleName" namespace="NamesapceName" >
<class name="ClassName" table="TableName" schema="ScheamName"
dynamic-update="true" dynamic-insert="true" select-before-update="true">
<id name="Id" column="id" type="integer" unsaved-value="0">
<generator class="native"></generator>
</id>
<property name="Name" column="name" type="StringClob" length="100000" not-null="true" />
</class>
and if I give the length of property greater than 4000 it created in this format
create table TableName (
id NUMBER(10,0) not null,
name NCLOB not null,
primary key (id)
)
and when I fetch the table item using my own function
I am encountering Oracle.DataAccess.Client.OracleException: ORA-00932: inconsistent datatypes: expected - got NCLOB problem
But When I set the property like
<property name="Name" column="name" type="string" length="2000" not-null="true" />
it created in this format
create table TableName (
id NUMBER(10,0) not null,
name NVARCHAR(2000) not null,
primary key (id)
)
and my function for fetching data was working fine. But I need a table that has string length > 4000 without Oracle.DataAccess.Client.OracleException: ORA-00932: inconsistent datatypes: expected - got NCLOB

Did you try just this?
<property name="Name" length="10000" not-null="true" />
I'm using SQL Server and I don't need to specify a type in such a case.

Related

How to create conditional unique constraint over nullable columns in with hibernate mapping file?

I have these tables in oracle database:
create table APP_BASEINFORMATIONHEADER
(
id NUMBER(10) not null,
topic VARCHAR2(50 CHAR) not null,
subsystem_type NUMBER(10)
);
create table APP_BASEINFORMATION
(
id NUMBER(10) not null,
code NUMBER(10),
parentid NUMBER(10)
);
alter table APP_BASEINFORMATION
add constraint FK_BASE_INFO_PARENT foreign key (PARENTID)
references APP_BASEINFORMATIONHEADER (ID);
CREATE UNIQUE INDEX UNQ_BASE_INFO_PARENT_CODE
ON APP_BASEINFORMATION
(CASE WHEN CODE IS NOT NULL THEN PARENTID || '-' || CODE END);
as you can see above, i create UNQ_BASE_INFO_PARENT_CODE unique constraint on table APP_BASEINFORMATION when the CODE column is not null. how i can put there condition on the .hbm.xml?
these is the hibernate mapping file of APP_BASEINFORNATION:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="org.my.framework.model.core.baseInfo.BaseInformation" table="App_BaseInformation">
<id name="id" type="int" >
<column name="ID" />
<generator class="sequence" >
<param name="sequence">SEQ_BaseInformation</param>
</generator>
</id>
<property column="Code" name="code" not-null="false" type="integer" unique-key="??" />
<property column="Topic" name="topic" not-null="true" type="string" length="100"/>
<many-to-one entity-name="org.my.framework.model.core.baseInfo.BaseInformationHeader" name="parent" unique-key="??" >
<column name="ParentId" not-null="false" />
</many-to-one>
</class>
</hibernate-mapping>
I mean where i should put (CASE WHEN CODE IS NOT NULL THEN PARENTID || '-' || CODE END) in hbm file and what is the correct syntax?

Liquibase and spring jpa

I'm having problem with deploy postgres on a linux environment though I don't sure it's related.
Linux version: 9.3.11
Windows version: 9.5
The error that I get:
2016-03-15_19:19:40.478 [http-nio-9090-exec-3] WARN o.h.e.jdbc.spi.SqlExceptionHelper - SQL Error: 0, SQLState: 42P01
2016-03-15_19:19:40.479 [http-nio-9090-exec-3] ERROR o.h.e.jdbc.spi.SqlExceptionHelper - ERROR: relation "rbac_roles" does not exist
Position: 125
2016-03-15_19:19:40.520 [http-nio-9090-exec-3] ERROR o.a.c.c.C.[.[.[.[dispatcherServlet] - Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.InvalidDataAccessResourceUsageException: could not extract ResultSet; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet] with root cause
org.postgresql.util.PSQLException: ERROR: relation "rbac_roles" does not exist
Position: 125
On my windows environment table definition created by Liquibase looks as following:
-- Table: public.rbac_roles
-- DROP TABLE public.rbac_roles;
CREATE TABLE public.rbac_roles
(
tenantid character varying(255) NOT NULL,
id integer NOT NULL DEFAULT nextval('rbac_roles_id_seq'::regclass),
name character varying(255) NOT NULL,
urlprefix character varying(255),
CONSTRAINT pk_rbac_roles PRIMARY KEY (id),
)
WITH (
OIDS=FALSE
);
ALTER TABLE public.rbac_roles
OWNER TO postgres;
On my linux (the prblematic) environment table definition created by Liquibase looks as following:
-- Table: public.rbac_roles
-- DROP TABLE public.rbac_roles;
CREATE TABLE public.rbac_roles
(
tenantid character varying(255) NOT NULL,
id serial NOT NULL,
name character varying(255) NOT NULL,
urlprefix character varying(255),
CONSTRAINT pk_rbac_roles PRIMARY KEY (id),
)
WITH (
OIDS=FALSE
);
ALTER TABLE public.rbac_roles
OWNER TO postgres;
The Spring Jpa object looks like this:
#Entity(name = "rbac_roles")
public class Role implements HasTenantId {
#Id
#SequenceGenerator(name="roles_seq", sequenceName = "rbac_roles_id_seq")
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "roles_seq")
private int id;
...
The Liquibase config looks like this:
<createTable tableName="rbac_roles">
<column name="tenantid" type="varchar(255)">
<constraints primaryKeyName="pk_roles" nullable="false" />
</column>
<column name="id" autoIncrement="true" type="integer">
<constraints primaryKey="true" nullable="false" />
</column>
...
</createTable>
The table rbac_roles created successfully but ID looks diffrent
What I'm doing wrong, why the behavior is different?
In your JPA Annotations you are using a sequence generator, but in your changelog there is an autoincrement type for ID attribute
<createTable tableName="rbac_roles">
<column name="tenantid" type="varchar(255)">
<constraints primaryKeyName="pk_roles" nullable="false" />
</column>
<!-- HERE you specify autoincrement -->
<column name="id" autoIncrement="true" type="integer">
<constraints primaryKey="true" nullable="false" />
</column>
...
</createTable>
It is confusing, and I don't know why this code is generating different tables on windows and linux, maybe your postgresql is not the same version ...
Please, fix your changelog and put the following
<createTable tableName="rbac_roles">
<column name="tenantid" type="varchar(255)">
<constraints primaryKeyName="pk_roles" nullable="false" />
</column>
<!-- Removed autoincrement -->
<column name="id" type="integer">
<constraints primaryKey="true" nullable="false" />
</column>
...
</createTable>
<!-- HERE I specify sequence -->
<createSequence sequenceName="rbac_roles_id_seq" incrementBy="1"/>
This way, it should generate same table on both systems.

Lazy loading hibernate

I use Spring 3 and hibernate 3.6.3.Final. I have to entities A and B. The hbm files are:
A.hbm.xml
<hibernate-mapping>
<class name="com.A" table="A" >
<id name="A_Id" type="string">
<column name="Id" length="100" />
<generator class="foreign">
<param name="property">B</param>
</generator>
</id>
<one-to-one name="B" class="B" constrained="true" fetch="select" ></one-to-one>
<property>...</property>
</class>
</hibernate-mapping>
and B.hbm.xml
<hibernate-mapping>
<class name="com.B" table="B">
<id name="B_Id" type="string">
<column name="Id" length="32" />
<generator class="assigned" />
</id>
...
<one-to-one name="some_A" class="com.A" lazy="proxy"></one-to-one> // FIRST
<one-to-one name="other_A" class="com.A" lazy="proxy" cascade="all" > // SECOND
<formula>other_BSRC_REG_REP_MESSAGE_ID</formula>
</one-to-one>
</class>
</hibernate-mapping>
From #Service I use the following code to get entity B by id:
getHibernateTemplate().get(getEntityClass(), id)
I enabled the show_sql mode in hibernate in order to check if my lazy loading works fine. Unfortunately I don't understand them
When either FIRST or SECOND line is commented out hibernate shows exactly one query (where all of the one-to-one associations are present as join),
When both FIRST and SECOND lines are uncommented hibernate shows two queries, one to get B and second to get an A entity.
Why this happens? Is it because all of the one-to-one association can't be lazy loaded so either they are eagerly loaded as a separate query or "joined" to the original query? If so, why hibernate didn't joined on the A table twice?

one-to-many relationshipt with database constrain and inverse=true

There are two classes A and B and hibernate mappings
<hibernate-mapping default-lazy="false">
<class name="A" table="A">
<id name="id" type="long">
<generator class="sequence"><param name="sequence">A_SEQUENCE</param></generator></id>
<set name="a" cascade="all" inverse="false" >
<key><column name="A_FK" not-null="true" /></key>
<one-to-many class="B" /></set>
</class>
</hibernate-mapping>
<hibernate-mapping default-lazy="false">
<class name="B" table="B">
<id name="id" type="long"> <column name="ID"/>
<generator class="sequence"><param name="sequence">B_SEQUENCE</param></generator></id>
</class>
</hibernate-mapping>
On the database there is a not null contraint and a foreign key constraint on the column A_FK of table B.
When I try to insert an A that contains a B I get the following error:
ORA-01400: cannot insert NULL into ("SCHEMA"."B"."A_FK")
Is it possible to insert this kind of data without having to specify the inverse=true flag? and the inverse relationship?
Not without getting rid of the way the id is generated. Can you switch how the Id is generated?
Converting the problem to a question is half the answer...
What was missing was the not-null="true" on the key of the set:
<set name="a" cascade="all" inverse="false" >
<key not-null="true"><column name="A_FK" not-null="true" /></key>
<one-to-many class="B" />
</set>

Mapping a composite primary key with a foreign key relation in Nhibernate

a company I am working for is using an ERP and it's legacy database is Oracle.
Until now I've used packages (oracle stored procedures) to access data but during the years the number has grown consistently and now I can't manage them anymore.
I was trying to do some experiments with Nhibernate and started mapping few tables.
All the tables have composite primary keys.
A brief description:
Table Order (table name: OCSAORH)
OCHORDN (PK) => OrderNumber
OCHAMND (PK)
OCHCOSC (PK) => Company
OCHCLII
...
Table OrderLine (table name: OCSALIN)
OCLORDN (PK) => OrderNumber
OCLAMND (PK)
OCLCOSC (PK) => Company
OCLLINN (PK) => Line Number
OCLSSEQ (PK)
OCLITMN
...
This is my mapping
Order:
<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="MvcOracleNhibernate"
namespace="MvcOracleNhibernate.Domain">
<class name="Order" table="OCSAORH">
<composite-id>
<key-property name="Number" column="OCHORDN"></key-property>
<key-property name="Ver" column="OCHAMND"></key-property>
<key-property name="Company" column="OCHCOSC"></key-property>
</composite-id>
<property name="CustomerCode" column="OCHCLII" type="String" length="10"></property>
<property name="Reference" column="OCHOCNO" type="String" length="25"></property>
<property name="Date" column="OCHOCDT" type="Double"></property>
<bag name="OrderLines" cascade="all-delete-orphan" generic="true" inverse="true" lazy="false">
<key>
<column name="OCLORDN" not-null="true"/>
<column name="OCLAMND" not-null="true"/>
<column name="OCLCOSC" not-null="true"/>
</key>
<one-to-many class="OrderLine" not-found="ignore"/>
</bag>
</class>
</hibernate-mapping>
OrderLine:
<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="MvcOracleNhibernate"
namespace="MvcOracleNhibernate.Domain">
<class name="OrderLine" table="OCSALIN">
<composite-id>
<key-property name="Number" column="OCLORDN"></key-property>
<key-property name="Ver" column="OCLAMND" ></key-property>
<key-property name="Company" column="OCLCOSC"></key-property>
<key-property name="Line" column="OCLLINN"></key-property>
<key-property name="Seq" column="OCLSSEQ"></key-property>
</composite-id>
<property name="Item" column="OCLITMN" type="String" length="19"></property>
<property name="Quantity" column="OCLQTYP" type="Double"></property>
</class>
</hibernate-mapping>
With these mappings everything works fine; I can load an order and the lazy loading loads my lines.
While reading some documentation I've noticed that I haven't defined the many-to-one relation so I've added this:
<many-to-one name="Order" class="Order" lazy="proxy">
<column name="OCHORDN" not-null="true"/>
<column name="OCHAMND" not-null="true"/>
<column name="OCHCOSC" not-null="true"/>
</many-to-one>
to the OrderLine mapping file.
Now if I run my test app the order is loaded properly but the order lines are not loaded.
I get a {NHibernate.ADOException} = {"could not initialize a collection: ... }
I've tried to investigate and noticed that the generated query to retrieve the rows is wrong. This is the SQL:
SELECT
orderlines0_.OCLORDN as OCLORDN1_,
orderlines0_.OCLAMND as OCLAMND1_,
orderlines0_.OCLCOSC as OCLCOSC1_,
orderlines0_.OCLLINN as OCLLINN1_,
orderlines0_.OCLSSEQ as OCLSSEQ1_,
orderlines0_.OCLORDN as OCLORDN13_0_,
orderlines0_.OCLAMND as OCLAMND13_0_,
orderlines0_.OCLCOSC as OCLCOSC13_0_,
orderlines0_.OCLLINN as OCLLINN13_0_,
orderlines0_.OCLSSEQ as OCLSSEQ13_0_,
orderlines0_.OCLITMN as OCLITMN13_0_,
orderlines0_.OCLQTYP as OCLQTYP13_0_,
orderlines0_.OCHORDN as OCHORDN13_0_,
orderlines0_.OCHAMND as OCHAMND13_0_,
orderlines0_.OCHCOSC as OCHCOSC13_0_
FROM OCSALIN orderlines0_
WHERE
orderlines0_.OCLORDN=?
and orderlines0_.OCLAMND=?
and orderlines0_.OCLCOSC=?
As you can notice the last 3 fields of the select (those with the prefix OCH instead of OCL) aren't members of the OCSALIN table; they are the key of the OCSAORH.
After 1 days spent reading documentation and examples I can't figure out what I am doing wrong.
Is there anybody there who can try to help?
This is the expected behavior. You're defining the foreign keys in your many-to-one mapping. So the columns need to exist in the object you're defining.
I think you want this
<many-to-one name="Order" class="Order" lazy="proxy">
<column name="OCLORDN" not-null="true"/>
<column name="OCLAMND" not-null="true"/>
<column name="OCLCOSC" not-null="true"/>
</many-to-one>

Resources