Обсуждение: Re: [BUGS] Mapping Hibernate boolean to smallint(Postgresql)

Поиск
Список
Период
Сортировка

Re: [BUGS] Mapping Hibernate boolean to smallint(Postgresql)

От
"Kevin Grittner"
Дата:
[Sigh.  Moving to the PostgreSQL JDBC list; I accidentally picked up
the Sun JDBC address in a previous attempt to move this.  :-( ]

I wrote:
> stagirus  wrote:
>
>> I guess it would be set/getBoolean methods, right?
>
> Maybe.  I'd rather not guess at what it is you need though.
>
>> If you need, I will get the exception report from my developer.
>
> Please do.  That would allow us to make sure that if we try to
> help, we're working on the right part of the code.  It's so much
> harder to hit a target when shooting in the dark.  ;-)

Any progress on getting exception reports?

-Kevin

Re: [BUGS] Mapping Hibernate boolean to smallint(Postgresql)

От
stagirus
Дата:
My developer sent me the following error report. It does not include stack
trace. But I can get it shortly.

 ERROR: column "deleted" is of type smallint but expression is of type
boolean

It appears that the queries generated by Hibernate contains boolean
expressions that are not being accepted as valid values by Postgresql DB.
Does anybody have experience with the following Hibernate's query
substitutions will work (Dean's suggestion)?
<property name="hibernate.query.substitutions">true 1, false 0</property>

It seems to be promising but I want to be sure it works before I recommend
to my team. They are already burnt with this boolean related issues in
Postgresql.

Ideally DB Engine/JDBC Drivers should be flexible(smart?) enough to
recognize integer values for boolean values. It is unfortunate that RDMBS
vendors nor ANSI SQL standardized boolean values. Am I making sense?

Thanks.
--
View this message in context:
http://postgresql.1045698.n5.nabble.com/Re-BUGS-Mapping-Hibernate-boolean-to-smallint-Postgresql-tp2855367p2855475.html
Sent from the PostgreSQL - jdbc mailing list archive at Nabble.com.

Re: [BUGS] Mapping Hibernate boolean to smallint(Postgresql)

От
"Kevin Grittner"
Дата:
stagirus <mamasa@stagirus.com> wrote:

> Ideally DB Engine/JDBC Drivers should be flexible(smart?) enough
> to recognize integer values for boolean values. It is unfortunate
> that RDMBS vendors nor ANSI SQL standardized boolean values. Am I
> making sense?

Sure.  I finally tracked down a current copy of the JDBC spec.  For
some reason, this seems to have become more difficult to find in
recent months; if anyone else is looking, I found it here:

http://jcp.org/aboutJava/communityprocess/final/jsr221/index.html

The relevant portions are TABLE B-5 and TABLE B-6.  What matters for
purposes of this discussion is that, when the driver is specifically
requested to convert between any of these Java classes:

String
java.math.BigDecimal
Boolean
Byte
Short
Integer
Long
Float
Double

and any of these database types:

TINYINT
SMALLINT
INTEGER
BIGINT
REAL
FLOAT
DOUBLE
DECIMAL
NUMERIC
BIT
BOOLEAN
CHAR
VARCHAR
LONGVARCHAR

it should attempt to do so.  Obviously that can sometimes fail due
to size or format issues.  But getBoolean against a SMALLINT is
clearly supposed to be attempted on demand.  I didn't happen across
the specification of how values map there, but in the absence of
evidence to the contrary I'd assume zero is false and anything else
is true;  Likewise, setObject using a Boolean against a SMALLINT
target is supposed to work.

What kinds of values do you see in the SMALLINT column when you set
a TRUE into a SMALLINT column?  1?  -1?

-Kevin

Re: [BUGS] Mapping Hibernate boolean to smallint(Postgresql)

От
stagirus
Дата:
Kevin's response above seems to be very promising.
From your comments/observations, are you saying that there could be some
coding issues regarding these conversions between boolean and integers?

Reg your question of "What kinds of values do you see in the SMALLINT column
when you set a TRUE into a SMALLINT column?  1?  -1?"
: Nothing. Because it fails before any inserts or updates happen. We
discussed the error above.

Because I have not worked with the internals of Hibernate/JDBC drivers, I
cannot definitively state if Hibernate is calling setters and getters
(setBoolean) using prepared statements or directly executes INSERT/UPDATE
statements. Anything is possible.

Thanks.
--
View this message in context:
http://postgresql.1045698.n5.nabble.com/Re-BUGS-Mapping-Hibernate-boolean-to-smallint-Postgresql-tp2855367p2855614.html
Sent from the PostgreSQL - jdbc mailing list archive at Nabble.com.

Re: [BUGS] Mapping Hibernate boolean to smallint(Postgresql)

От
"Kevin Grittner"
Дата:
stagirus <mamasa@stagirus.com> wrote:

> Reg your question of "What kinds of values do you see in the
> SMALLINT column when you set a TRUE into a SMALLINT column?  1?
> -1?" : Nothing. Because it fails before any inserts or updates
> happen. We discussed the error above.

I meant with other database products.  Are they consistent?

-Kevin

Re: [BUGS] Mapping Hibernate boolean to smallint(Postgresql)

От
stagirus
Дата:
Yes. It works without any issues on Oracle. We have not yet tested with other
databases except Postgresql. For the past 40 days, we have been trying to
get the product work with Postgresql. Ran into too many issues just related
to "Boolean" fields. We were hoping to deploy our Cloud System (SaaS) on
Postgreql -if we can get it to work.
--
View this message in context:
http://postgresql.1045698.n5.nabble.com/Re-BUGS-Mapping-Hibernate-boolean-to-smallint-Postgresql-tp2855367p2855630.html
Sent from the PostgreSQL - jdbc mailing list archive at Nabble.com.

Re: [BUGS] Mapping Hibernate boolean to smallint(Postgresql)

От
"Kevin Grittner"
Дата:
stagirus <mamasa@stagirus.com> wrote:

> From your comments/observations, are you saying that there could
> be some coding issues regarding these conversions between boolean
> and integers?

I'm saying that while the code is probably behaving as the person
who contributed it to PostgreSQL intended, it appears not to comply
with the current standard.  The PostgreSQL community generally makes
a pretty good effort toward conforming to standards.  If it's
relatively easy to make it conform to the standard, someone will
probably just do it.  (Heck, it could even be me.)  If it's a lot of
work, someone who needs the feature may have to take on the burden
of the change, either by offering a patch to implement it or paying
someone to do so.

> Because I have not worked with the internals of Hibernate/JDBC
> drivers, I cannot definitively state if Hibernate is calling
> setters and getters (setBoolean) using prepared statements or
> directly executes INSERT/UPDATE statements. Anything is possible.

Hence the request for the stack trace.  Most people have a pretty
full plate, and aren't eager to volunteer their time to work on
something which might not actually help anyone.

-Kevin

Re: [BUGS] Mapping Hibernate boolean to smallint(Postgresql)

От
"Kevin Grittner"
Дата:
stagirus <mamasa@stagirus.com> wrote:

> It works without any issues on Oracle.

The question was -- when you set a SMALLINT column with a Boolean
which is TRUE, what value is stored in the database column.  You've
mentioned doing this on multiple databases; do they all set the same
value, and if so, what is it?

-Kevin

Re: [BUGS] Mapping Hibernate boolean to smallint(Postgresql)

От
stagirus
Дата:
Point is well-taken. I will supply the stack trace. Thanks.

We are inserting 0 for false and 1 for true. Oracle and Hibernate has been
pretty happy so far. We just have to make Postgresql happy too.

I am impressed with your comment that Postgresql tries to comply with the
standards. If so do you have sufficient test cases for converting between
the data types you mentioned above. Any test cases for
Hibernate-JDBC-Postgresql scenarios? If I were (Postgres team), I would
include them to ensure the compatibility.

Thanks.
--
View this message in context:
http://postgresql.1045698.n5.nabble.com/Re-BUGS-Mapping-Hibernate-boolean-to-smallint-Postgresql-tp2855367p2855656.html
Sent from the PostgreSQL - jdbc mailing list archive at Nabble.com.

Re: [BUGS] Mapping Hibernate boolean to smallint(Postgresql)

От
"Kevin Grittner"
Дата:
stagirus <mamasa@stagirus.com> wrote:

> If I were (Postgres team), I would include them to ensure the
> compatibility.

Feel free to contribute a patch.  The "PostgreSQL Team" is a pretty
loose and varied lot.  I've read that the changes for the 9.0
release were contributed by over 100 different people, although some
people are obviously a lot more active than others.  One great thing
about free, open source software is that "you can scratch your own
itch." Many contributions come from people who use the product in a
way others don't, and run into an issue which isn't bothering anyone
else -- much like you.

Welcome to the team!  ;-)

-Kevin

Re: [BUGS] Mapping Hibernate boolean to smallint(Postgresql)

От
Oliver Jowett
Дата:
Kevin Grittner wrote:

> The relevant portions are TABLE B-5 and TABLE B-6. [...]

> But getBoolean against a SMALLINT is
> clearly supposed to be attempted on demand.  I didn't happen across
> the specification of how values map there, but in the absence of
> evidence to the contrary I'd assume zero is false and anything else
> is true;  Likewise, setObject using a Boolean against a SMALLINT
> target is supposed to work.

If I read the original report right, it's about setBoolean(), not
getBoolean() (the error is a type mismatch while executing the query,
not a problem processing the results)

Note that table B-5 is specifically about "What combinations of
java.sql.Types value and actual instance type are valid for
setObject()?". So, for example, if you called "setObject(column,
Boolean.TRUE, Types.SMALLINT)", that should work - you're explicitly
asking the driver to represent a Boolean as a SMALLINT. (As noted, the
mapping's not standard, so you may not get exactly the same as other
databases).

However, if you just call setBoolean() in a context where the database
is expecting a SMALLINT, then it's not going to work - how does the
driver know, in the general case, that it should apply a conversion
there? (Consider fun cases where the parameter isn't just directly
mapped to a column, it's part of an expression, etc).

The driver could in theory ask the backend to always infer a type for
positional parameters, then apply its own conversions, but this requires
an extra round trip per query and would actually break other cases where
valid queries with correct types would suddenly start complaining about
being unable to infer a type. And anyway, it's not the right place for
it - the backend already has a large set of type conversion
functionality, why are we suddenly trying to duplicate that in the driver?

You can think of setBoolean(column, boolValue) as essentially the same
as setObject(column, Boolean.valueOf(boolValue), Types.BOOLEAN) - if you
look at it that way, there's obviously no conversion required, because
the type you passed is already a BOOLEAN as you requested ..

I would suggest that the OP either:

* use a real boolean column in their schema (I mean, the data you're
representing IS a boolean value in this case, right?); or
* use setObject(column, value, Types.SMALLINT) instead of the implied
setBoolean() call when setting the column (this may be tricky to do
since you have a layer between you and the driver, but that's not really
the driver's fault..); or
* add a suitable implicit cast on the backend side from boolean ->
smallint (not sure if this works, haven't looked at the details)

-O

Re: [BUGS] Mapping Hibernate boolean to smallint(Postgresql)

От
Samuel Gendler
Дата:
On Mon, Sep 27, 2010 at 1:43 PM, Oliver Jowett <oliver@opencloud.com> wrote:
I would suggest that the OP either:

* use a real boolean column in their schema (I mean, the data you're
representing IS a boolean value in this case, right?); or
* use setObject(column, value, Types.SMALLINT) instead of the implied
setBoolean() call when setting the column (this may be tricky to do
since you have a layer between you and the driver, but that's not really
the driver's fault..); or
* add a suitable implicit cast on the backend side from boolean ->
smallint (not sure if this works, haven't looked at the details)


I would actually suggest running your problem past the hibernate community.  It seems unlikely that you're the first team to encounter this problem.  How do you have the property mapped in the hibernate mapping?  Is it possible that explicitly setting the hibernate type of the property in the mapping will solve your problem?


Re: [BUGS] Mapping Hibernate boolean to smallint(Postgresql)

От
Craig Ringer
Дата:
On 28/09/10 07:01, Samuel Gendler wrote:

> I would actually suggest running your problem past the hibernate
> community.  It seems unlikely that you're the first team to encounter
> this problem.  How do you have the property mapped in the hibernate
> mapping?  Is it possible that explicitly setting the hibernate type of
> the property in the mapping will solve your problem?

There's way too much guesswork happening here.

OP ("stagirus"), please supply *code*, *stack traces* and *exact error
messages*.

Please show at least one mapping that you are having problems with - the
Java class with annotations, or if you're using XML mapping the
associated XML configuration. Show the stack trace that results from the
failure, and what appears in the PostgreSQL error logs.

Even better, produce buildable source code that demonstrates your
problem without depending on other parts of your application. If you
don't use Hibernate's DDL generation to populate your database, include
a SQL script containing you would use to populate the database too. This
should be a twenty minute job for any competent developer on your team.

That way, instead of lots of hand-waving and guesswork, it'll be
possible to discuss concrete problems and possible solutions.

You should also specify:

- Your Hibernate version
- How you're mapping your entity classes
- Your PostgreSQL JDBC driver versions
- What dialect, if any, is configured for Hibernate
- Your JDK version
- Which version of PostgreSQL you are targeting

See:
  http://wiki.postgresql.org/wiki/Guide_to_reporting_problems


Personally, I suspect you're overriding Hibernate's DDL generation but
not its type mappings, so the PostgreSQL dialect can't do it's job. But
without actual code, it's nigh-on impossible to tell.

--
Craig Ringer

Tech-related writing: http://soapyfrogs.blogspot.com/

Re: [BUGS] Mapping Hibernate boolean to smallint(Postgresql)

От
Craig Ringer
Дата:
I got sick of the guesswork and hand-waving, so here's a test case
demonstrating that Hibernate works just fine with PostgreSQL when
mapping booleans as shorts or as booleans.

Executable:

http://www.postnewspapers.com.au/~craig/weblinks/pghiberboolean-1.0-SNAPSHOT-jar-with-dependencies.jar

Sources including build README and Maven pom:

http://www.postnewspapers.com.au/~craig/weblinks/pghiberboolean-1.0-SNAPSHOT-project.zip

Run the test case as:

java -jar target/pghiberboolean-1.0-SNAPSHOT-jar-with-dependencies.jar \
      jdbc:postgresql://localhost/DBNAME DBUSER DBPASSWORD

(all on one line, replace DBNAME, DBUSER, DBPASSWORD with settings for a
test database on your machine).



Now: please show your code so we can see what's actualling going wrong,
as this case demonstrates that Hibernate gets it right when left to its
own devices.

Are you using your own DDL to define your tables, so you're mapping
types as shorts in hibernate but using booleans in the database? Because
that's not how Hibernate expects it to be, it expects a short if you
tell it you're mapping a short.

I'm going to guess that what you're doing is equivalent to running the
attached test program to create the tables, then connecting to the
database and running:

  ALTER TABLE test_entity DROP COLUMN not_boolean;
  ALTER TABLE test_entity ADD COLUMN not_boolean boolean;

thus changing the "shortint" typed column to "boolean". This will cause
the test program to fail with:


SEVERE: ERROR: column "not_boolean" is of type boolean but expression is
of type smallint
  Hint: You will need to rewrite or cast the expression.
  Position: 67



If this is the case, you can:

- Let hibernate generate the DDL in a database-independent manner;

- Fix your SQL DDL so it declares booleans where Hibernate expects
  booleans;

- Fix your mappings so they're Boolean in java if they're boolean in
  the database, and let Hibernate take care of mapping them to shorts
  when the database doesn't understand booleans natively;

- Write a UserType to hack around this by using the short-typed get and
  set methods in JDBC rather than the boolean ones, overriding
  Hibernate's defaults.

Basically, I think you're throwing a spanner in the works by trying to
override Hibernate, but only doing it half-way.



--
Craig Ringer

Tech-related writing: http://soapyfrogs.blogspot.com/

Re: [BUGS] Mapping Hibernate boolean to smallint(Postgresql)

От
stagirus
Дата:
Thank you for the information provided above. It appears that we are all not
on the same page regarding the issue we are discussing. My apologies for my
share of communication gaps. Let me try again.

1. Create the table (DDL): CREATE TABLE st_employee (e_name varchar(30),
active SMALLINT);
2. Define a POJO: class Employee{ name String; active boolean};
3. Hibernate mapping:
    <class name="Employee" table="st_employee">
        <property name="name" type="string">
            <column name="e_name" />
        </property>
        <property name="active" type="boolean">
            <column name="active" />
        </property>
4. Use Hibernate templates (DAO) to store and read the DB.

Observation: this works for Oracle and other DBs. Postgresql (9.0 and latest
JDBC drivers) complain about boolean cannot be cast to SMALLINT. I would
expect Postgresql work like other RDBMS like Oracle.

Thanks.




--
View this message in context:
http://postgresql.1045698.n5.nabble.com/Re-BUGS-Mapping-Hibernate-boolean-to-smallint-Postgresql-tp2855367p2865634.html
Sent from the PostgreSQL - jdbc mailing list archive at Nabble.com.

Re: [BUGS] Mapping Hibernate boolean to smallint(Postgresql)

От
"Kevin Grittner"
Дата:
stagirus <mamasa@stagirus.com> wrote:

> Observation: this works for Oracle and other DBs.

That doesn't carry that much weight in this community, unless it is
a barrier to a lot of people converting.  If you can demonstrate
that we're out of compliance with a standard, or that it is a
problem in some common usage, that would carry some weight.  So far
you haven't provided evidence of anything.  A complete stranger took
the time to post an example of how Hibernate works fine doing what
you appeared to him to be describing.  Code and instructions how to
run it and everything.  The ball is in your court to actually show
enough information about the failure case for us to understand what
you're doing and where it fails.

If you haven't already done so, you should probably read this page:

http://wiki.postgresql.org/wiki/Guide_to_reporting_problems

-Kevin

Re: [BUGS] Mapping Hibernate boolean to smallint(Postgresql)

От
stagirus
Дата:
Kevin:
This discussion is getting overly political, legal and religious. I have no
interest in any of these.

You have already noted above that boolean values and integer values are
interchangeable as per the JDBC 4.0 Spec. Why are you now asking me to prove
it? (I am not married to Oracle either!)

I posted a common sense question. I requested for an advice why Postgresql
is not working in a seemingly obvious scenario. My hope was that Postgresql
community appreciates this sort of feedback.

Otherwise, when we can dedicate resources, we will troubleshoot these issues
and provide a patch, if that helps. Until then, fortunately life is full of
options.

Please advise so that we can put this discussion to rest.

Thanks.


--
View this message in context:
http://postgresql.1045698.n5.nabble.com/Re-BUGS-Mapping-Hibernate-boolean-to-smallint-Postgresql-tp2855367p2916249.html
Sent from the PostgreSQL - jdbc mailing list archive at Nabble.com.

Re: [BUGS] Mapping Hibernate boolean to smallint(Postgresql)

От
stagirus
Дата:
>>Are you using your own DDL to define your tables, so you're mapping
types as shorts in hibernate but using booleans in the database? Because
that's not how Hibernate expects it to be, it expects a short if you
tell it you're mapping a short.<<<

Craig: the scenario you have described is different from the one we are
facing.

1. Yes, we define and manage our own DDL, not generate from Hibernate. We
prefer to keep it that way.
2. We define the column in the database table as SMALLINT not boolean.
Please refer to my post below.
3. As described below, in the Hibernate we map Java boolean to DB SMALLINT.
Below I showed the mapping.
Obviously we assume java boolean values and DB integer values (columns) are
interchangeable. Poor "boolean" values have no real shape among DB vendors
and ANSI SQL.

I hope this makes sense.

Thanks.


--
View this message in context:
http://postgresql.1045698.n5.nabble.com/Re-BUGS-Mapping-Hibernate-boolean-to-smallint-Postgresql-tp2855367p2918544.html
Sent from the PostgreSQL - jdbc mailing list archive at Nabble.com.

Re: [BUGS] Mapping Hibernate boolean to smallint(Postgresql)

От
Oliver Jowett
Дата:
stagirus wrote:

> You have already noted above that boolean values and integer values are
> interchangeable as per the JDBC 4.0 Spec.

They're not actually - see my post. You can ask the driver to convert
between types for you, but Hibernate does not appear to be doing that
(presumably because you've told it that the column is a boolean, which
doesn't match your DDL!)

To repeat my suggestions:

* use a real boolean column in their schema (I mean, the data you're
representing IS a boolean value in this case, right?); or
* use setObject(column, value, Types.SMALLINT) instead of the implied
setBoolean() call when setting the column (this may be tricky to do
since you have a layer between you and the driver, but that's not really
the driver's fault..); or
* add a suitable implicit cast on the backend side from boolean ->
smallint (not sure if this works, haven't looked at the details)

Do any of these work for you? The first suggestion seems to be the
simplest to me, since you really are storing a boolean, not a smallint,
and you have control over the DDL.

-O

Re: [BUGS] Mapping Hibernate boolean to smallint(Postgresql)

От
stagirus
Дата:
Oliver:
>>* use a real boolean column in their schema (I mean, the data you're
representing IS a boolean value in this case, right?);
--- No, we already tried this path. Unfortunately boolean is not portable
column type among DB vendors. So, we ruled out this option.

or
* use setObject(column, value, Types.SMALLINT) instead of the implied
setBoolean() call when setting the column (this may be tricky to do
since you have a layer between you and the driver, but that's not really
the driver's fault..); or
---I am not sure if our application developers have this option. Hibernate
handles this for us. I am not pointing fingers. I am curious how other DBs
or JDBC drivers handle it so transparently.

* add a suitable implicit cast on the backend side from boolean ->
smallint (not sure if this works, haven't looked at the details)
-- we will look into it.

Do any of these work for you? The first suggestion seems to be the
simplest to me, since you really are storing a boolean, not a smallint,
and you have control over the DDL.
--Not yet, please.

--
View this message in context:
http://postgresql.1045698.n5.nabble.com/Re-BUGS-Mapping-Hibernate-boolean-to-smallint-Postgresql-tp2855367p3005405.html
Sent from the PostgreSQL - jdbc mailing list archive at Nabble.com.

Re: [BUGS] Mapping Hibernate boolean to smallint(Postgresql)

От
Oliver Jowett
Дата:
stagirus wrote:
> Oliver:
>>> * use a real boolean column in their schema (I mean, the data you're
> representing IS a boolean value in this case, right?);
> --- No, we already tried this path. Unfortunately boolean is not portable
> column type among DB vendors. So, we ruled out this option.

You can't ship different DDL for different vendors?

I thought part of the point of using a mapping layer like Hibernate was
so Hibernate could handle the details of the mapping to different DBs
(which might be done in different ways) without having to know about the
different mappings in your application. So a Java boolean might be
mapped to either a Postgresql boolean or an Oracle SMALLINT (since
oracle doesn't have a real boolean type?), but your app code doesn't
care about that detail - it's just dealing with a Java boolean either way.

-O

Re: [BUGS] Mapping Hibernate boolean to smallint(Postgresql)

От
Craig Ringer
Дата:
On 29/09/2010 9:02 PM, Oliver Jowett wrote:
> stagirus wrote:
>> Oliver:
>>>> * use a real boolean column in their schema (I mean, the data you're
>> representing IS a boolean value in this case, right?);
>> --- No, we already tried this path. Unfortunately boolean is not portable
>> column type among DB vendors. So, we ruled out this option.
>
> You can't ship different DDL for different vendors?
>
> I thought part of the point of using a mapping layer like Hibernate was
> so Hibernate could handle the details of the mapping to different DBs
> (which might be done in different ways) without having to know about the
> different mappings in your application. So a Java boolean might be
> mapped to either a Postgresql boolean or an Oracle SMALLINT (since
> oracle doesn't have a real boolean type?), but your app code doesn't
> care about that detail - it's just dealing with a Java boolean either way.

That is indeed a significant part of Hibernate's feature set. If you
don't use it, you have to expect to have to maintain different DDL for
different databases yourself, or be prepared to customise Hibernate's
behaviour where necessary.

That said, I do think the OP ("stagirus") has a point. Pg's JDBC driver
is passing boolean literals through to Pg, which tries to insert them
into a smallint column and fails due to a type error. This is IMO overly
strict, and appears to be outside the JDBC spec too.

The underlying problem is that Pg won't permit implicit casts between
smallint and boolean. I see the rationale behind that, but it's a pain.
It's not a JDBC driver bug as such, because it's Pg not JDBC that's
rejecting the query, and JDBC is sending a boolean when asked to send a
boolean by Hibernate, as instructed by the OP's mappings. The JDBC
driver has no way to know the column is really a smallint, so a casting
error will occur.

It looks like "stagirus" may be right about the JDBC spec requiring
conversion between all numeric types, and considering "boolean" to be a
numeric special case. Page 217 of the JDBC4 spec (see
http://java.sun.com/products/jdbc/download.html#corespec40) contains a
table that suggests that setting a Java 'boolean' to a database
'smallint' (and vice versa) should be valid and permitted.

So I guess the question is: what do we do about it? Does the JDBC driver
have to find out what the database's expectations of parameter types are
and perform appropriate casts Java side? Or might it be possible to
offer a more permissive casting mode server-side that the JDBC driver
can set for the session?

--
Craig Ringer

Tech-related writing at http://soapyfrogs.blogspot.com/

Re: [BUGS] Mapping Hibernate boolean to smallint(Postgresql)

От
stagirus
Дата:
Craig:
Finally, you made my day SIR! We reached to the bottom of the issue. (My
original post tried to convey this very fact.) Anyway, thank you for
referring to the JDBC specs and reaching this very powerful conclusion. You
sound very grown up person! My cudos!

I cannot wait to hear your group's consensus on how you all like to resolve
this issue. As far as how we resolve this issue or what decisions stagirus
makes should our internal headache. We are competent in that side of the
house. When we do need other help from you all, we will surely contact you.

Regarding other comments on Cloud. No, we are not looking to use Postgresql
on the Cloud. Postgresql DB will be on our own servers/hardware locally.
Just our software (SaaS) like Salesforce.com would be on the Cloud. Sorry
for the confusion.

Best wishes.


--
View this message in context:
http://postgresql.1045698.n5.nabble.com/Re-BUGS-Mapping-Hibernate-boolean-to-smallint-Postgresql-tp2855367p3047370.html
Sent from the PostgreSQL - jdbc mailing list archive at Nabble.com.

Re: [BUGS] Mapping Hibernate boolean to smallint(Postgresql)

От
Dave Cramer
Дата:
On Thu, Sep 30, 2010 at 1:31 PM, stagirus <mamasa@stagirus.com> wrote:
>
> Craig:
> Finally, you made my day SIR! We reached to the bottom of the issue. (My
> original post tried to convey this very fact.) Anyway, thank you for
> referring to the JDBC specs and reaching this very powerful conclusion. You
> sound very grown up person! My cudos!

Actually that table B-5 refers to setObject conversions, table B-6
refers to resultset gettter methods. There is no explicit conversion
specified for settters. I think Oliver already pointed this out in a
previous post.

Dave

Re: [BUGS] Mapping Hibernate boolean to smallint(Postgresql)

От
Oliver Jowett
Дата:
Craig Ringer wrote:

> It looks like "stagirus" may be right about the JDBC spec requiring
> conversion between all numeric types, and considering "boolean" to be a
> numeric special case. Page 217 of the JDBC4 spec (see
> http://java.sun.com/products/jdbc/download.html#corespec40) contains a
> table that suggests that setting a Java 'boolean' to a database
> 'smallint' (and vice versa) should be valid and permitted.

This is not correct. I covered this in a previous mail. This table
(table B-5) is specifically about the conversions that setObject() will
do on require. See page 192 at the start of appendix B:

> TABLE B-5 Conversions by setObject and setNull from Java Object Types to JDBC
> Types
> This table shows which JDBC types may be specified as the target JDBC type to the
> methods PreparedStatement.setObject, PreparedStatement.setNull, RowSet.setNull
> and RowSet.setObject.

Section 13.2.2.1, page 100:

> The data type specified in a PreparedStatement setter method is a data type in
> the Java programming language. The JDBC driver is responsible for mapping this to
> the corresponding JDBC type (one of the SQL types defined in java.sql.Types) so
> that it is the appropriate type to be sent to the data source. The default mapping is
> specified in Appendix B TABLE B-2.

(Table B-2 specifies that a Java boolean is mapped to JDBC datatypes BIT
or BOOLEAN)

And section 13.2.2.3, page 101:

> The method setObject can be used to convert an object in the Java programming
> language to a JDBC type.
> The conversion is explicit when setObject is passed a Java Object and a JDBC
> data type. [...]
> If setObject is called without a type parameter, the Java Object is implicitly
> mapped using the default mapping for that object type. [...]
> The default mapping is described in Appendix B TABLE B-4

(Table B-4 specifies that a Java boolean is mapped to JDBC datatypes BIT
or BOOLEAN)

So, in summary: If you explicitly ask for a Java boolean to be mapped to
a JDBC SMALLINT, by passing Types.SMALLINT to setObject(), then that
should be supported and the driver will do the conversion for you; if
that doesn't work, that's a bug! However, if you don't specify a type
when calling setObject() or setBoolean(), it is mapped to BOOLEAN. If
BOOLEAN is then not a suitable type for the actual query you're trying
to run, then you'll get a SQL error, but that's not the driver's fault,
it just did what you asked!

So the driver is working just fine here - the problem is that the
application (via Hibernate) is expecting that a BOOLEAN value should be
implicitly cast to a SMALLINT, which is really nonportable behaviour
which only happens to work with Oracle because Oracle doesn't have a SQL
boolean type in the first place and so the app is using SMALLINT in its
DDL ..

-O


Re: [BUGS] Mapping Hibernate boolean to smallint(Postgresql)

От
stagirus
Дата:
Oliver should be a lawyer by nature! In my opinion Software is about solving
problems! I carefully read many of your writings on this/related topics.

I respectfully disagree with your interpretations and conclusions. You seem
to be more interested in proving somebody is WRONG rather than being open to
truly understand the issues at hand and discovering helpful solutions.
Anybody can prove anything is wrong. For one to understand and admit the
limitations/weaknesses requires one to be very brave and mature.

Anyway, I got to go. Take care.

Best wishes.




--
View this message in context:
http://postgresql.1045698.n5.nabble.com/Re-BUGS-Mapping-Hibernate-boolean-to-smallint-Postgresql-tp2855367p3047671.html
Sent from the PostgreSQL - jdbc mailing list archive at Nabble.com.

Re: [BUGS] Mapping Hibernate boolean to smallint(Postgresql)

От
Oliver Jowett
Дата:
stagirus wrote:
> Oliver should be a lawyer by nature! In my opinion Software is about solving
> problems! I carefully read many of your writings on this/related topics.
>
> I respectfully disagree with your interpretations and conclusions. You seem
> to be more interested in proving somebody is WRONG rather than being open to
> truly understand the issues at hand and discovering helpful solutions.
> Anybody can prove anything is wrong. For one to understand and admit the
> limitations/weaknesses requires one to be very brave and mature.

Well - I've tried to explain why the driver is behaving as it is, why I
believe that is the correct behavior according to the spec, and why it's
difficult for the driver to behave in any other way. I've even suggested
ways you can modify your software to do what you want. I'm not sure what
more I can do here.

Since it seems that you're not prepared to change your application, and
you're not prepared to listen to feedback that disagrees with you, I
think your only real option is to modify the driver to behave as you
think it should, and post that patch for review. The source is available
- go and prove that you're right!

(And I'm certainly not getting into passive-aggressive games about how I
am a terrible person because I disagreed with you)

-O

Re: [BUGS] Mapping Hibernate boolean to smallint(Postgresql)

От
stagirus
Дата:
Oliver: Thank you for your generous response. The options you suggested were
not yet viable. Disagreeing is part of human nature. No worries there.

But if you review Craig's remarks carefully, this issue is likely outside
the scope of JDBC drivers. It is more to do with the Postgresql DB Engine
that is not happy to cast or convert boolean values to SMALLINT columns.

Craig.. is my interpretation of your comments right?

Thanks


--
View this message in context:
http://postgresql.1045698.n5.nabble.com/Re-BUGS-Mapping-Hibernate-boolean-to-smallint-Postgresql-tp2855367p3047721.html
Sent from the PostgreSQL - jdbc mailing list archive at Nabble.com.

Re: [BUGS] Mapping Hibernate boolean to smallint(Postgresql)

От
Oliver Jowett
Дата:
stagirus wrote:

> But if you review Craig's remarks carefully, this issue is likely outside
> the scope of JDBC drivers. It is more to do with the Postgresql DB Engine
> that is not happy to cast or convert boolean values to SMALLINT columns.

I refer you to my previous emails that discuss exactly this, and a
possible workaround.

(Nice backpedalling)

-O

Re: [BUGS] Mapping Hibernate boolean to smallint(Postgresql)

От
Mark Kirkwood
Дата:
On 01/10/10 10:50, stagirus wrote:
> Oliver: Thank you for your generous response. The options you suggested were
> not yet viable. Disagreeing is part of human nature. No worries there.
>
> But if you review Craig's remarks carefully, this issue is likely outside
> the scope of JDBC drivers. It is more to do with the Postgresql DB Engine
> that is not happy to cast or convert boolean values to SMALLINT columns.
>
> Craig.. is my interpretation of your comments right?
>
>

This could be an interesting related factor (using 9.0 here):

test=# create table smallinttest(val smallint);
CREATE TABLE

test=# create table booltest(val bool);
CREATE TABLE

test=# insert into booltest values (1);
ERROR:  column "val" is of type boolean but expression is of type integer
LINE 1: insert into booltest values (1);

test=# insert into booltest values ((1::smallint)::bool);
ERROR:  cannot cast type smallint to boolean
LINE 1: insert into booltest values ((1::smallint)::bool);
                                                   ^
                                   ^
HINT:  You will need to rewrite or cast the expression.
test=# insert into booltest values (1::bool);
INSERT 0 1

test=# insert into smallinttest values (true);
ERROR:  column "val" is of type smallint but expression is of type boolean
LINE 1: insert into smallinttest values (true);
                                          ^
HINT:  You will need to rewrite or cast the expression.
test=# insert into smallinttest values (true::smallint);
ERROR:  cannot cast type boolean to smallint
LINE 1: insert into smallinttest values (true::smallint);
                                              ^
test=# insert into smallinttest values (true::int);
INSERT 0 1


So looks like we are missing type casts BOOLEAN <-> SMALLINT, given that
we can happily cast to and from INTEGER.

Before getting too excited, note that the server is clearly not doing
automated casts under any circumstances, I had to coerce it - so might
not help you even if we added such casts.

Cheers

Mark

Re: [BUGS] Mapping Hibernate boolean to smallint(Postgresql)

От
stagirus
Дата:
Yes. we will try the following two options.
1. Operator overloading - add a suitable implicit cast on the backend side
from boolean -> smallint (not sure if this works, haven't looked at the
details)
2. Hibernate query subs: <property name="hibernate.query.substitutions">true
1, false 0</property>

I already indicated earlier these two are viable options for us.  It might
take sometime before I can post the update. Thank you for your help. See
you.

Best wishes.

--
View this message in context:
http://postgresql.1045698.n5.nabble.com/Re-BUGS-Mapping-Hibernate-boolean-to-smallint-Postgresql-tp2855367p3047745.html
Sent from the PostgreSQL - jdbc mailing list archive at Nabble.com.

Re: [BUGS] Mapping Hibernate boolean to smallint(Postgresql)

От
Craig Ringer
Дата:
On 10/01/2010 04:38 AM, Oliver Jowett wrote:

> This is not correct. I covered this in a previous mail.

[snip]

> So, in summary: If you explicitly ask for a Java boolean to be mapped to
> a JDBC SMALLINT, by passing Types.SMALLINT to setObject(), then that
> should be supported and the driver will do the conversion for you; if
> that doesn't work, that's a bug! However, if you don't specify a type
> when calling setObject() or setBoolean(), it is mapped to BOOLEAN. If
> BOOLEAN is then not a suitable type for the actual query you're trying
> to run, then you'll get a SQL error, but that's not the driver's fault,
> it just did what you asked!

Aah, thanks for the clarification. I didn't notice your earlier message
on the topic.

Given that, it's pretty clear that the OP has to fix their app to:

- Trust Hibernate to generate their DDL, taking care of their db
portability issues;

- Use per-database DDL with the data types Hibernate expects;

- Use a short in Java if they want a short in the database, and convert
it in their accessor methods; or

- Use a Hibernate UserType to call the appropriate set() and get() JDBC
methods, overriding the default type-based options in the dialect.


--
Craig Ringer

Re: [BUGS] Mapping Hibernate boolean to smallint(Postgresql)

От
Craig Ringer
Дата:
On 10/01/2010 05:50 AM, stagirus wrote:
>
> Oliver: Thank you for your generous response. The options you suggested were
> not yet viable. Disagreeing is part of human nature. No worries there.
>
> But if you review Craig's remarks carefully, this issue is likely outside
> the scope of JDBC drivers. It is more to do with the Postgresql DB Engine
> that is not happy to cast or convert boolean values to SMALLINT columns.
>
> Craig.. is my interpretation of your comments right?

Yes, but that's not inherently a problem. It'd only be an issue if the
JDBC driver was required to ensure that those conversions occurred
correctly. As it seems it isn't require to do so, the server isn't
obliged to handle these conversions and the JDBC driver isn't obliged to
work around the server's restriction.

I have no strong opinion on whether Pg should accept 'short' inputs for
'boolean' columns. I see good arguments in both directions. All I was
saying earlier was that my casual reading of the JDBC spec (incorrectly,
it turns out) said that jdbc drivers had to support this.

Since the JDBC spec doesn't require drivers to support this, you should
stop relying on behaviour that isn't guaranteed by the spec.

I still don't understand why you won't fix your application code to use
Hibernate how it's designed to be used. You're using half of Hibernate's
database dialect and automatic type selection features (runtime SQL),
but not the other half (DDL), so it's breaking. If you'll let Hibernate
do it's job and produce your DDL, or stop lying to Hibernate about how
you've defined the database by mapping the smallint fields as shorts,
your problem will go away.

How hard is this?

@Entity
class Something {

     @Basic
     @Column
     private boolean fakeBoolean;

     public boolean getFakeBoolean() {
         return fakeBoolean != 0;
     }

     public void setFakeBoolean(boolean fakeBoolean) {
         this.fakeBoolean = (short)(fakeBoolean ? 1 : 0);
     }

}



?

Note, by the way, that Java won't let you implicitly cast between
boolean and short. Just like Pg.



It's also easy to use a UserType to get what you want, like the one I
wrote recently because PostgreSQL won't implicitly cast 'text' to 'xml':

http://wiki.postgresql.org/wiki/Hibernate_XML_Type



For what it's worth, I think this is partly a Hibernate/JPA issue. At
least in JPA, there's no way to specify the SQLTYPE associated with a
given column, which is mildly annoying, as it'd let the JDBC driver
handle this issue.

--
Craig Ringer

Re: [BUGS] Mapping Hibernate boolean to smallint(Postgresql)

От
stagirus
Дата:
>>I still don't understand why you won't fix your application code to use
Hibernate how it's designed to be used. You're using half of Hibernate's..

If it was a simple thing on our application side, why would I be wasting my
time and your time this much!

Our product is developed based on certain architectural principles. It was
all developed for the past four years. Unfortunately, your suggestions are
too invasive and not even feasible. Per our architecture, Hibernate is
simply an ORM tool. Period. Not any sort of database administration tool.
There are better tools for that job.

Your argument of boolean is not same as short in Java. Agreed. Do you
believe programing languages are same as RDBMS engines? I do not think so.

We all know there is no universal definition or support for boolean columns
(storage class as it is called) in RDBMS except in Postgresql. Check ANSI
SQL. Sorry no boolean!

So the real question to the JDBC experts as you all - how is this difference
between boolean in programming language(Java) and RDBMS/JDBC should be
resolved? I like the way other RDBMS have resolved this difference.

Why wouldn't you (Postgresql)?

If you observe the discussions on this topic, unfortunately Postgresql has
created the biggest incompatibility for boolean fields. You know the reasons
- you treat boolean as chars unlike everybody else (0, 1 or -1). PLEASE
LISTEN TO THE CRIES OF THE WORLD!





--
View this message in context:
http://postgresql.1045698.n5.nabble.com/Re-BUGS-Mapping-Hibernate-boolean-to-smallint-Postgresql-tp2855367p3073409.html
Sent from the PostgreSQL - jdbc mailing list archive at Nabble.com.

Re: [BUGS] Mapping Hibernate boolean to smallint(Postgresql)

От
Craig Ringer
Дата:
On 2/10/2010 6:17 AM, stagirus wrote:
>
>>> I still don't understand why you won't fix your application code to use
> Hibernate how it's designed to be used. You're using half of Hibernate's..
>
> If it was a simple thing on our application side, why would I be wasting my
> time and your time this much!
>
> Our product is developed based on certain architectural principles. It was
> all developed for the past four years. Unfortunately, your suggestions are
> too invasive and not even feasible.

OK, then let's add another:

- Subclass the PostgreSQL dialect for Hibernate to map boolean to
tinyint instead of to boolean

It's like using a UserType, but applies globally across your application.

Hibernate (specifically Hibernate's PostgreSQL dialect) knows about
PostgreSQL's boolean type, and assumes you want to use it. If you don't,
you have to tell Hibernate so.

If the Hibernate designers agreeed with you about booleans, they
wouldn't have mapped java boolean to postgresql boolean in Hibernate.
Because it's hibernate that's doing it, via
org.hibernate.dialect.PostgreSQLDialect. Go argue with them if you want
them to change how it works to suit your code.

> Your argument of boolean is not same as short in Java. Agreed. Do you
> believe programing languages are same as RDBMS engines? I do not think so.

No, I'm merely making the point that implicitly casting between boolean
and integer isn't universally supported and isn't considered so obvious
as to be a no-brainer.

> We all know there is no universal definition or support for boolean columns
> (storage class as it is called) in RDBMS except in Postgresql. Check ANSI
> SQL. Sorry no boolean!

AFAIK, boolean was added in SQL:1999 . More than 10 years ago. It's also
fully supported by JDBC. Note, for example, the presence of
java.sql.Types.BOOLEAN .

> So the real question to the JDBC experts as you all - how is this difference
> between boolean in programming language(Java) and RDBMS/JDBC should be
> resolved?

There is no difference between boolean in Java and boolean in
PostgreSQL. Both have distinct true/false values, and neither are
convertable to/from integer. Nor is there at the JDBC level, as
java.sql.Types.BOOLEAN maps perfectly to Java's boolean.

The difference you are experiencing is because you're *lying* to the
JDBC driver, via Hibernate, while you enforce your fixed view of how
relational databases should store boolean values. By mapping boolean
fields as boolean, you're effectively calling:

   s.setObject(n, false, java.sql.Types.BOOLEAN);

which tells the JDBC driver the column type is boolean. It isn't,
because while you've defined it as a boolean in Java and mapped it that
way with Hibernate, you've defined it in the database as a smallint.

Hibernate knows about PostgreSQL's boolean type, and will use it for
boolean java fields, because it expects the database field to be defined
as boolean. If you don't want Hibernate to behave that way, you need to
change how it behaves so it instead sends the SQL type you want:

   s.setObject(n, false, java.sql.Types.SMALLINT);

You can do this with a UserType, by subclassing
org.hibernate.dialect.PostgreSQLDialect, or by writing your own dialect
subclass.

I know you want PostgreSQL to implicitly cast between boolean and
smallint, so this works transparently. PostgreSQL doesn't. Personally, I
have no strong opinon on whether it should or not am not in a position
to change how it works anyway. So, unless you're going to develop a
patch to PostgreSQL that enables that and prove that it won't break
existing code, you should probably be focusing on how to make your code
work how you want with PostgreSQL.

> I like the way other RDBMS have resolved this difference.
>
> Why wouldn't you (Postgresql)?

Because nobody seems to have wanted it/needed it until now? It used to
be handled via implicit casts to text, and now that those are gone you
seem to be the first one who misses the lack of the cast.

Because there are also solid reasons NOT to permit implicit casts from
boolean to integer, catching unintended errors being only one of them?

If you like you can always add a cast from boolean to smallint yourself.
See "CREATE CAST" in the documentation and the contents of the
pg_catalog.pg_cast table.

> If you observe the discussions on this topic, unfortunately Postgresql has
> created the biggest incompatibility for boolean fields. You know the reasons
> - you treat boolean as chars unlike everybody else (0, 1 or -1).

Nonsense. PostgreSQL booleans are not char. The literal representation
looks like a char, but so do dates, NUMERIC literals, and all sorts of
other things - and you're not telling me PostgreSQL represents dates as
char are you?

I think you need to understand how your tools work - PostgreSQL, PgJDBC,
Hibernate, and your mapping code. Because right now, I don't think
you're properly aware of how Hibernate maps types and how its dialects
influence its behaviour.

Anyway, I'm done wasting my time here; I've spent about four hours of my
own time trying to be patient and help, and that's four hours too many.
If you're not satisfied with the answers, it's time to pay a
professional consultant to help you, 'cos I'm done.

--
Craig Ringer

Tech-related writing at http://soapyfrogs.blogspot.com/

Re: [BUGS] Mapping Hibernate boolean to smallint(Postgresql)

От
stagirus
Дата:
Of course my very first post on this topic indicated that we were looking for
a solution for a problem with booleans. It took this long for all of us to
reach a conclusion that the business of type mappings are handled by
Hibernate. The following dialect class/API clearly states it.
http://ajava.org/online/hibernate3api/org/hibernate/dialect/PostgreSQLDialect.html#toBooleanValueString(boolean)

Oliver did refer to Hibernate Dialect. Not very clear though. So it is
becoming evident that the types can be managed within Hibernate API or
configurations. Overriding just the above API might suffice. I wish you guys
have pointed me to this earlier.

I am good. thanks.




--
View this message in context:
http://postgresql.1045698.n5.nabble.com/Re-BUGS-Mapping-Hibernate-boolean-to-smallint-Postgresql-tp2855367p3073605.html
Sent from the PostgreSQL - jdbc mailing list archive at Nabble.com.

Re: [BUGS] Mapping Hibernate boolean to smallint(Postgresql)

От
Samuel Gendler
Дата:
subclassing the dialect is almost certainly overkill for what you are trying to accomplish.  Why not just define a UserType that works with a smallint column and then use it in your mappings wherever you need to map a boolean to a smallint.  That will work in Oracle just as it will in postgres, so you won't have an incompatibility that requires a code change in order to switch platforms - it will just be explicit in both platforms.  That's way less invasive (and probably a lot less side effect prone) than trying to modify the dialect.

As for why no one mentioned it, I think that is because probably every one of us thinks that's the worst solution to your problem of all those that have been presented so far. If you lack the experience with hibernate such that you aren't even aware of the existence of the dialect classes, then you probably shouldn't be mucking about with modifying them - especially when hibernate provides a mechanism to solve exactly your problem in the form of user defined types.  I cannot fathom what your resistance to using a user type might be.  Your problem is exactly what they are designed for - to map an arbitrary java class to an arbitrary database structure.  In your case, the user type will be incredibly simple, since it is mapping a built-in type to a single column via a nearly trivial conversion mechanism.  You could fix this in 20 minutes or less with a hibernate book and a user type.



On Fri, Oct 1, 2010 at 9:50 PM, stagirus <mamasa@stagirus.com> wrote:

Of course my very first post on this topic indicated that we were looking for
a solution for a problem with booleans. It took this long for all of us to
reach a conclusion that the business of type mappings are handled by
Hibernate. The following dialect class/API clearly states it.
http://ajava.org/online/hibernate3api/org/hibernate/dialect/PostgreSQLDialect.html#toBooleanValueString(boolean)

Oliver did refer to Hibernate Dialect. Not very clear though. So it is
becoming evident that the types can be managed within Hibernate API or
configurations. Overriding just the above API might suffice. I wish you guys
have pointed me to this earlier.

I am good. thanks.




--
View this message in context: http://postgresql.1045698.n5.nabble.com/Re-BUGS-Mapping-Hibernate-boolean-to-smallint-Postgresql-tp2855367p3073605.html
Sent from the PostgreSQL - jdbc mailing list archive at Nabble.com.

--
Sent via pgsql-jdbc mailing list (pgsql-jdbc@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-jdbc

Re: [BUGS] Mapping Hibernate boolean to smallint(Postgresql)

От
stagirus
Дата:
Thank you all. I have heard and looked at all the options including the
UserType. This indeed has been an insightful discussion. I enjoyed speaking
to you. It is my honor to getting to know you all.

Now I am in a much better position to advise my architects and developers on
this issue. I would be happy to update you with the solution we would
implement and our rationale, if that helps. I am sure we will talk in the
near future.

Thank you very much.

--
View this message in context:
http://postgresql.1045698.n5.nabble.com/Re-BUGS-Mapping-Hibernate-boolean-to-smallint-Postgresql-tp2855367p3074149.html
Sent from the PostgreSQL - jdbc mailing list archive at Nabble.com.

Re: [BUGS] Mapping Hibernate boolean to smallint(Postgresql)

От
stagirus
Дата:
Good morning. Please find the attached log file regarding our problem. The
main issue is with "DELETED" column as SMALLINT. Postgres is not accepting
'0' in the values(..) for DELETED column. (This was the original issue that
I posted.)

http://postgresql.1045698.n5.nabble.com/file/n3199236/PostgresForum.log
PostgresForum.log

--
View this message in context:
http://postgresql.1045698.n5.nabble.com/Re-BUGS-Mapping-Hibernate-boolean-to-smallint-Postgresql-tp2855367p3199236.html
Sent from the PostgreSQL - jdbc mailing list archive at Nabble.com.

Re: [BUGS] Mapping Hibernate boolean to smallint(Postgresql)

От
Oliver Jowett
Дата:
stagirus wrote:
> Good morning. Please find the attached log file regarding our problem. The
> main issue is with "DELETED" column as SMALLINT. Postgres is not accepting
> '0' in the values(..) for DELETED column. (This was the original issue that
> I posted.)
>
> http://postgresql.1045698.n5.nabble.com/file/n3199236/PostgresForum.log
> PostgresForum.log

> ERROR 04-10 15:26:32,937 (JDBCExceptionReporter.java:logExceptions:101)  -Batch entry 0 /* insert
com.stagirus.subsystem.suppliermaster.domain.Provider*/ insert into ST_PROVIDER (GEOGRAPHY_ID, ADDRESS_ID,
PROVIDER_NAME,DESCRIPTION, WEBSITE, EMAIL, PHONE, FAXNO, PRIMARY_ORG_ID, DELETED, CREATED_ON, CREATED_BY,
LAST_MODIFIED_ON,LAST_MODIFIED_BY, PROVIDER_ID) values ('1', '2', 'supplier1', NULL, NULL, NULL, '1245874123', '', '1',
'0','2010-10-04 15:26:32.734000 +05:30:00', '1', '2010-10-04 15:26:32.734000 +05:30:00', '1', '1') was aborted.  Call
getNextExceptionto see the cause. 

Not shown in your logs is the type which Hibernate is binding the
parameters as. I expect that the '0' is actually bound with Oid.BOOL
because Hibernate is using setBoolean() or setObject(...,Types.BOOLEAN).

For example, the implementation of setBoolean does this:

>     public void setBoolean(int parameterIndex, boolean x) throws SQLException
>     {
>         checkClosed();
>         bindString(parameterIndex, x ? "1" : "0", Oid.BOOL);
>     }

which means that the value parameter is indeed "0" or "1" - but its type
is BOOL. (I'm guessing that the query logged by Hibernate above is the
result of PreparedStatement.toString(), which just substitutes the raw
parameter values into the query string without respect for their bound
types)

You could check this by setting loglevel=2 and looking at the messages
sent to the backend, or by looking at a packet capture with wireshark
(IIRC, it has a decent protocol analyzer for the postgresql FE/BE protocol)

Oliver


Re: [BUGS] Mapping Hibernate boolean to smallint(Postgresql)

От
Jeff Hubbach
Дата:
I found this post in Hibernate's forums:

https://forum.hibernate.org/viewtopic.php?f=1&t=944165&p=2247802&hilit=postgres+boolean+smallint#p2247802

In summary, Hibernate will handle converting a char(1) in the database to/from boolean in java, and from that post, it
worksin DB2 and PostgreSQL. 

So here's another option. Change your smallint in the database to a char(1). The only thing it affects is the DDL for
eachdatabase, any existing data you have in the database, and the Hibernate mapping files. Your java code remains
untouched.

-- Jeff Hubbach

Re: [BUGS] Mapping Hibernate boolean to smallint(Postgresql)

От
stagirus
Дата:
Jeff:
Your research and the recommendation is viable. The conclusion was Java
boolean and DB char(1) are interoperable. By the same token, why wasn't Java
boolean and DB smallint interoperable? Is it the Hibernate issue (Dialect?),
JDBC driver issue, or the DB Engine issue? In our case, it works with Oracle
DB indicates to me that we are missing something. Or I am just missing
something.

I am afraid the boolean to char(1) might run into similar issues with other
databases. Just because it worked with DB2 and Postgres does not mean it
would work with other DBs. We are already noticing such incompatibilities
though our solution worked with Oracle.

Thanks.

--
View this message in context:
http://postgresql.1045698.n5.nabble.com/Re-BUGS-Mapping-Hibernate-boolean-to-smallint-Postgresql-tp2855367p3200613.html
Sent from the PostgreSQL - jdbc mailing list archive at Nabble.com.

Re: [BUGS] Mapping Hibernate boolean to smallint(Postgresql)

От
stagirus
Дата:
>>Not shown in your logs is the type which Hibernate is binding the
>>parameters as. I expect that the '0' is actually bound with Oid.BOOL
>>because Hibernate is using setBoolean() or setObject(...,Types.BOOLEAN)...

Oliver - your observations could possibly be right.

One simple question though. Is the reported exception generated by the
Postgresql JDBC driver or Postgresql DB Engine?

Thanks.

--
View this message in context:
http://postgresql.1045698.n5.nabble.com/Re-BUGS-Mapping-Hibernate-boolean-to-smallint-Postgresql-tp2855367p3200618.html
Sent from the PostgreSQL - jdbc mailing list archive at Nabble.com.

Re: [BUGS] Mapping Hibernate boolean to smallint(Postgresql)

От
Oliver Jowett
Дата:
stagirus wrote:

> One simple question though. Is the reported exception generated by the
> Postgresql JDBC driver or Postgresql DB Engine?

The BatchUpdateException in this case is built by the driver using error
details reported by the backend.

Oliver

Re: [BUGS] Mapping Hibernate boolean to smallint(Postgresql)

От
c_h_thakar
Дата:
stagirus,

How did you solve this issue ? Did you use UserType ?

Could you please send the details ?


--
View this message in context:
http://postgresql.1045698.n5.nabble.com/Re-BUGS-Mapping-Hibernate-boolean-to-smallint-Postgresql-tp2855367p5582702.html
Sent from the PostgreSQL - jdbc mailing list archive at Nabble.com.

Re: [BUGS] Mapping Hibernate boolean to smallint(Postgresql)

От
Radosław Smogura
Дата:
Dnia środa, 21 marca 2012 o 05:07:43 c_h_thakar napisał(a):
> stagirus,
>
> How did you solve this issue ? Did you use UserType ?
>
> Could you please send the details ?
>
>
> --
> View this message in context:
> http://postgresql.1045698.n5.nabble.com/Re-BUGS-Mapping-Hibernate-boolean-t
> o-smallint-Postgresql-tp2855367p5582702.html Sent from the PostgreSQL - jdbc
> mailing list archive at Nabble.com.
I may give you alternative solution, I use it for different situations, but
currently I write it "by hand". It's JPA aware, not bound to hibernate. Try
this:
public class entity {
    private int intAsBool;
    private boolean boolValue;

    @Column()
    protected int getIntAsBool() {...}
    protected void setIntAsBool(int val) {...}

    @Transient
    public boolean getBoolValue() {...}
    public boolean setBoolValue() {...}

    @PostLoad
    protected void postLoad() {
        setBoolValue(getIntAsBool() == 1);
    }

    @PrePersist
    @PreUpdate
    protected void preStore() {
        setIntAsBool(getBoolValue() ? 1 : 0);
    }
}

Bear in mind you need to choose only one way to mark JPA annotations field or
ancestors, 2nd one is better for many reasons.

Hope this help. I use this construct to store and map T/N char(1) values to
boolean.

Regards,
Radosław Smogura
http://softperience.eu/