-
Notifications
You must be signed in to change notification settings - Fork 27
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[ORM] Blog post on Boolean type type mapping in ORM 6 #164
Conversation
posts/Jan/2022-04-29-mapping-basic-custom-type-in-hibernate-orm-600.adoc
Outdated
Show resolved
Hide resolved
posts/Jan/2022-04-29-mapping-basic-custom-type-in-hibernate-orm-600.adoc
Outdated
Show resolved
Hide resolved
50b66fd
to
f1da3ec
Compare
ece6fed
to
5736f30
Compare
2df319f
to
9b924ef
Compare
14a2401
to
1f96743
Compare
posts/Jan/2022-04-29-mapping-boolean-types-in-hibernate-orm-6.adoc
Outdated
Show resolved
Hide resolved
posts/Jan/2022-04-29-mapping-boolean-types-in-hibernate-orm-6.adoc
Outdated
Show resolved
Hide resolved
posts/Jan/2022-04-29-mapping-boolean-types-in-hibernate-orm-6.adoc
Outdated
Show resolved
Hide resolved
[source, JAVA, indent=0] | ||
---- | ||
// this Boolean attribute will be converted to a CHAR in the database | ||
@JdbcTypeCode(SqlTypes.CHAR) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have you verified that this actually works?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Believe it or not, but yes, I actually have ;)
What makes you doubt it wouldn't, btw?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This tells Hibernate which JDBC type to use, not how to perform a conversion from boolean -> char.
What gets stored when you do this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in H2: CHAR(1) CHECK ("B" IN('N', 'Y'))
So, Hibernate does magic even beyond it's makers' knowledge ... :D
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might be worth mentioning in the blog post, that Y
/N
is the "default" representation as per BooleanJavaType
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
YesNoConverter:: encodes boolean values as 'Y' or 'N'
posts/Jan/2022-04-29-mapping-boolean-types-in-hibernate-orm-6.adoc
Outdated
Show resolved
Hide resolved
posts/Jan/2022-04-29-mapping-boolean-types-in-hibernate-orm-6.adoc
Outdated
Show resolved
Hide resolved
posts/Jan/2022-04-29-mapping-boolean-types-in-hibernate-orm-6.adoc
Outdated
Show resolved
Hide resolved
|
||
This default, 'implicit' mapping can be modified in several ways. | ||
|
||
== JPA compliant, using AttributeConverter |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need for JPA compliant,
here. It adds no value.
I'd also condense this whole conversation into something like:
== AttributeConverter
Using an `AttributeConverter` is a natural way to map a boolean accounting for different storage representations.
See the link:{url-hibernate-ug}#basic-jpa-convert[User Guide] for details about using `AttributeConverter`.
Hibernate provides 3 built-in `AttributeConverter` implementations for the most common cases:
YesNoConverter:: encodes boolean values as 'Y' or 'N'
TrueFalseConverter:: encodes boolean values as 'T' or 'F'
NumericBooleanConverter:: encodes boolean values as an integer, 1 for true and 0 for false
[[convert]]
.Using AttributeConverter
====
[source, JAVA, indent=0]
----
@Entity
class TheEntity {
...
// this will get mapped to CHAR or NCHAR
@Basic
@Convert(converter = org.hibernate.type.YesNoConverter.class)
boolean convertedYesNo;
// this will get mapped to CHAR or NCHAR
@Basic
@Convert(converter = org.hibernate.type.TrueFalseConverter.class)
boolean convertedTrueFalse;
// this will get mapped to TINYINT
@Basic
@Convert(converter = org.hibernate.type.NumericBooleanConverter.class)
boolean convertedNumeric;
// use our custom converter
@Basic
@Convert(converter = CustomBooleanConverter.class)
boolean convertedCustom;
}
@Converter
public class CustomBooleanConverter implements AttributeConverter<Boolean, Character> {
...
}
----
====
== Auto-applied AttributeConverter
In the above <<convert,examples>>, the conversions will only be applied to the annotated attribute.
Usually, however, this storage representation will be the same across an entire application or organization. In such cases, annotating each and every boolean attribute individually is tedious and error prone.
Jakarta Persistence defines a portable way to auto-apply a converter to all boolean types found in the domain model using `jakarta.persistence.Converter#autoApply`.
[[convert-auto]]
.Auto-applied AttributeConverter
====
[source, JAVA, indent=0]
----
@Converter( autoApply = true )
public class CustomBooleanConverter implements AttributeConverter<Boolean, Character> {
...
}
----
====
// We should actually move this discussion about how Hibernate becomes aware of auto-applied
// converters into the User Guide. I just noticed we don't really have any content there about that.
// And then:
See the link:{user-guide-url}[User Guide] for details about auto-applied converters.
[[convert-reg]]
== ConverterRegistration
Starting with the imminent 6.1 release, Hibernate also supports registering converters using the new `@ConverterRegistration` annotation. This annotation is a corollary to the `orm.xml` `<converter/>` element.
Consider Hibernate's built-in `YesNoConverter`, and let's say we want to auto-apply it. The converter itself is not defined for auto-application (and that would not be appropriate given potential discovery problems).
One option is to explicitly tell Hibernate about it using `orm.xml`:
.<converter/>
====
[source, JAVA, indent=0]
----
<entity-mappings>
...
<converter>org.hibernate.type.YesNoConverter</converter>
...
</entity-mappings>
----
====
Another is to use this new annotation, which can be specified at the class or package level. It's scope is global regardless.
.@ConverterRegistration
====
[source, JAVA, indent=0]
----
@ConverterRegistration( converter=org.hibernate.type.YesNoConverter.class, autoApply=true )
----
====
`ConverterRegistration` will be covered in more detail in the 6.1 version of the User Guide.
// == Hibernate Extensions
// === `@JdbcTypeCode / @JdbcType`
== `@JdbcTypeCode / @JdbcType`
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seriously though Steve, it's one thing to correct obvious errors and/or omissions and suggest improvements, and another to rewrite the whole thing. At one point or another you're gonna have to either accept the fact that if someone else wrote something it's not gonna be 100% like you would have done it, or just write it yourself.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are new to writing public blogs. You asked me for help. I am suggesting that you write way too much content for a blog post and how you can make the content simpler. If that irks you, sure.. I'll do it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It doesn't irk me, I just feel maybe you're overthinking this a bit. But sure, we can keep chipping away at this until it's reduced to nothing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I've given my own 'twist' to your suggestions.
For one, I don't see the need for an Auto-applied AttributeConverter section, after all it's about attributeconverters with just an attribute set to true, imo a section of its own suggests that those are some kind of special entities in their own right.
I did not know that (or forgot about) putting a converter in orm.xml auto-applies it, so obviously that has to go in there.
c29bc25
to
594acaf
Compare
posts/Jan/2022-04-29-mapping-boolean-types-in-hibernate-orm-6.adoc
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Personally, I would love to see a some kind of "conclusion" that gives a "recommendation" maybe (given that we can provide that). I think that with converters, literals might not work as expected i.e. the following code:
CriteriaBuilder cb = session.getCriteriaBuilder();
CriteriaQuery cq = session.createQuery( TestEntity.class );
cq.where( cb.equal( root.get( "convertedBoolean" ), cb.literal( true ) ) );
but we'd have to check to make sure. It would be nice though, if it doesn't work as expected (rendering as literal to SQL), that we "warn" users about this and hence provide guidance.
They should. At least from HQL. Fairly certain there are tests for that. But more tests always ok :D |
17416ba
to
11f556e
Compare
e9926c3
to
26fd761
Compare
42ec8d8
to
e03dd42
Compare
7e2128e
to
1b1bcf3
Compare
cc2207c
to
96e0e71
Compare
7c4bbf3
to
569b896
Compare
a90b9dd
to
135273f
Compare
Hey @jrenaat @sebersole @beikov, should we close this or do you still plan to merge it someday? |
Bump. |
Ok I'm pretty sure nobody cares by now... Closing, feel free to reopen :) |
Signed-off-by: Jan Schatteman jschatte@redhat.com