Re: [hibernate-dev] HHH-6726 LONG and LONG RAW column types in Oracle
by Łukasz Antoniak
Currently Oracle supports database versions from 10.1 to 11.2 [1]. LONG
and LONG RAW data types are deprecated since version 8 and 8i (released
before September 2000) [2]. Oracle keeps those column types only for
backward compatibility [3].
I tried the following scenario (Oracle 10gR2):
1. Create schema with "hibernate.hbm2ddl.auto" set to "create". The LONG
column is created.
2. Insert some data.
3. Modify Oracle dialect as Gail suggested. Avoid setting
"hibernate.hbm2ddl.auto".
4. Insert some data.
To my surprise the test actually passed :). However, I think that we
cannot guaranty the proper behavior in every situation.
As for performance, ImageType is extracted by calling
ResultSet.getBytes() method, which fetches all data in one call [4]. I
don't suppose a major performance difference when data is streamed in
another call. oracle.jdbc.driver.LongRawAccessor.getBytes also fetches
data by reading the stream.
The bug reading LONG column affects JDBC drivers since version 10.2.0.4.
I think that we have to choose between:
- changing Oracle10gDialect. Make a not about it in migration guide to
4.0 and update "5.2.2. Basic value types" chapter in Hibernate
documentation.
- introducing Oracle11gDialect. It can sound weird to access Oracle 10g
database with Oracle 11g dialect.
- disabling execution of Hibernate tests that fail because of this issue
with @SkipForDialect (and maybe develop another version of them with
CLOBs and BLOBs, @RequiresDialect). Hibernate is written correctly
according to "Default Mappings Between SQL Types and Java Types"
(referenced earlier by Gail) and this is more Oracle's JDBC
implementation issue. This option came to my mind, but it's weird :P.
I would vote for the first option.
Regards,
Lukasz Antoniak
[1]
http://www.oracle.com/us/support/library/lifetime-support-technology-0691...
(page 4)
[2]
http://download.oracle.com/docs/cd/A91202_01/901_doc/server.901/a90120/ch...
[3]
http://download.oracle.com/docs/cd/B28359_01/server.111/b28318/datatype.htm
[4] "Getting a LONG RAW Data Column with getBytes"
http://download.oracle.com/docs/cd/B19306_01/java.102/b14355/jstreams.htm
Strong Liu pisze:
> I think oracle 11g is the only one supported DB version by oracle, can we just introduce a new oracle dialect with suggested changes, and deprecate all other existed oracle dialects? this won't affects users app
>
> -----------
> Strong Liu <stliu(a)hibernate.org>
> http://hibernate.org
> http://github.com/stliu
>
> On Oct 15, 2011, at 11:14 AM, Scott Marlow wrote:
>
>> How does this impact existing applications? Would they have to convert
>> LONGs to CLOBs (and LONGRAWs to BLOBs) to keep the application working?
>>
>> As far as the advantage of CLOB over TEXT, if you read every character,
>> which one is really faster? I would expect TEXT to be a little faster,
>> since the server side will send the characters before they are asked
>> for. By faster, I mean from the application performance point of view. :)
>>
>> Could this be changed in a custom Oracle dialect? So new
>> applications/databases could perhaps use that and existing applications
>> might use LONGs a bit longer via the existing Oracle dialect.
>>
>> On 10/14/2011 09:22 PM, Gail Badner wrote:
>>> In [1], I am seeing the following type mappings:
>>>
>>> Column type: LONG -> java.sql.Types.LONGVARCHAR -> java.lang.String
>>> Column type: LONGRAW -> java.sql.Types.LONGVARBINARY -> byte[]
>>>
>>> org.hibernate.type.TextType is consistent with the mapping for LONG.
>>>
>>> org.hibernate.type.ImageType is consistent with the mapping for LONGRAW.
>>>
>>> From this standpoint, the current settings are appropriate.
>>>
>>> I understand there are restrictions when LONG and LONGRAW are used and I see from your other message that there is Oracle documentation for migrating to CLOB and BLOB.
>>>
>>> I agree that changing column type registration as follows (for Oracle only) should fix this:
>>> registerColumnType( Types.VARBINARY, 2000, "raw($l)" );
>>> registerColumnType( Types.VARBINARY, "blob" );
>>>
>>> registerColumnType( Types.LONGVARCHAR, "clob" );
>>> registerColumnType( Types.LONGVARBINARY, "blob" );
>>>
>>> registerColumnType( Types.VARCHAR, 4000, "varchar2($l char)" );
>>> registerColumnType( Types.VARCHAR, "clob" );
>>>
>>> Steve, what do you think? Is it too late to make this change for 4.0.0?
>>>
>>> [1] Table 11-1 of Oracle® Database JDBC Developer's Guide and Reference, 11g Release 1 (11.1) (http://download.oracle.com/docs/cd/B28359_01/java.111/b31224/datacc.htm#g...)
>>> [2] Hibernate Core Migration Guide for 3.5 (http://community.jboss.org/wiki/HibernateCoreMigrationGuide35)
>>> [3] Table 2-10 of Oracle® Database SQL Language Reference
>>> 11g Release 1 (11.1) (http://download.oracle.com/docs/cd/B28359_01/server.111/b28286/sql_elemen...)
>>>
>>> ----- Original Message -----
>>>> From: "Łukasz Antoniak"<lukasz.antoniak(a)gmail.com>
>>>> To: hibernate-dev(a)lists.jboss.org
>>>> Sent: Thursday, October 13, 2011 12:50:13 PM
>>>> Subject: [hibernate-dev] HHH-6726 LONG and LONG RAW column types in Oracle
>>>>
>>>> Welcome Community!
>>>>
>>>> I have just subscribed to the list and wanted to discuss HHH-6726
>>>> JIRA
>>>> issue.
>>>>
>>>> Gail Badner wrote
>>>> (http://lists.jboss.org/pipermail/hibernate-dev/2011-October/007208.html):
>>>> HHH-6726 (Oracle : map TextType to clob and ImageType to blob)
>>>> https://hibernate.onjira.com/browse/HHH-6726
>>>> There have been a number of issues opened since the change was made
>>>> to
>>>> map TextType (LONGVARCHAR) 'long' and ImageType (LONGVARBINARY) to
>>>> 'long
>>>> raw'. This change was already documented in the migration notes.
>>>> Should
>>>> the mapping for Oracle (only) be changed back to clob and blob?
>>>>
>>>> HHH-6726 is caused by an issue in Oracle JDBC driver (version
>>>> 10.2.0.4
>>>> and later). This bug appears when LONG or LONG RAW columns are
>>>> accessed
>>>> not as first or last while processing SQL statement.
>>>>
>>>> I have discussed the topic of mapping TextType to CLOB and ImageType
>>>> to
>>>> BLOB (only in Oracle dialect) with Strong Liu. Reasons for doing so:
>>>> - Oracle allows only one LONG / LONG RAW column per table. This might
>>>> be
>>>> the most important from Hibernate's perspective.
>>>> - LONG / LONG RAW - up to 2 GB, BLOB / CLOB - up to 4 GB.
>>>> - In PL/SQL using LOBs is more efficient (random access to data).
>>>> LONG
>>>> only sequential.
>>>> - LONG and LONG RAW are deprecated.
>>>>
>>>> What is your opinion?
>>>>
>>>> Regards,
>>>> Lukasz Antoniak
>>>> _______________________________________________
>>>> hibernate-dev mailing list
>>>> hibernate-dev(a)lists.jboss.org
>>>> https://lists.jboss.org/mailman/listinfo/hibernate-dev
>>>>
>>> _______________________________________________
>>> hibernate-dev mailing list
>>> hibernate-dev(a)lists.jboss.org
>>> https://lists.jboss.org/mailman/listinfo/hibernate-dev
>> _______________________________________________
>> hibernate-dev mailing list
>> hibernate-dev(a)lists.jboss.org
>> https://lists.jboss.org/mailman/listinfo/hibernate-dev
>
8 years, 7 months
Changelog file in Hibernate ORM
by Sanne Grinovero
The file changelog.txt in the root ot the Hibernate ORM project seems outdated.
Is it not maintained anymore? I found it handy.
Sanne
9 years, 3 months
JdbcSession proposal
by Steve Ebersole
I found a few spare minutes to work on this a little and move it into
the next stage with some actual interfaces, impls and usages to help
illustrate some of the proposed concepts.
https://github.com/sebersole/JdbcSession
The README.md is very up-to-date and detailed. Would be good to get
input from others.
P.S. I probably dislike the *Inflow naming more than you do :)
10 years
5.0 metamodel binding
by Steve Ebersole
Gail,
I am working on some changes to metamodel and have come across some things
that I need your help deciphering in terms of things you do Binder. The
background is this...
At the moment all of metamodel binding completely mis-handles
MappedSuperclasses. The annotation source processor handles them somewhat,
but in a very unusable way; it basically flattens all MappedSuperclass info
into the nearest Entity. This is because the source package does not at
all support the definition of MappedSuperclass. And then of course
bindings do nothing with it, since it is not accounted for in source.
To add this support I plan on the following changes:
1) Move lots of the information currently defined by RootEntitySource into
EntityHierarchy. The identifier, version, etc is actually a function of
the hierarchy as a whole, so conceptually it makes more sense there anyway.
And that mirrors the way we modeled it in the binding spi.
2) Generalize the EntityHierarchy tree to allow mixing Entity and
MappedSuperclass sources. A MappedSuperclass source actually needs to be
defined.
3) Model MappedSuperclass in the binding spi as well.
Which leads to my confusion. I have no idea how to account for such
changes in the Binder code and its calls through various executors and
contexts. I really need some pointers here.
10 years, 4 months
Another @Access quandry
by Steve Ebersole
>From the test
org.hibernate.test.annotations.access.jpa.AccessMappingTest#testExplicitPropertyAccessAnnotationsWithHibernateStyleOverride
we have the following:
@Entity
@Access(AccessType.PROPERTY)
public class Course3 {
private long id;
...
@Id
@GeneratedValue
@Access(AccessType.FIELD)
public long getId() {
return id;
}
...
}
The test asserts that this is a valid mapping. Granted that the spec is
very unclear here, so I might be missing something. The pertinent spec
section here states:
*<quote>When Access(PROPERTY) is applied to an entity class, mapped
superclass, or embeddableclass, mapping annotations may be placed on the
properties of that class, and the persistenceprovider runtime accesses
persistent state via the properties defined by that class. All proper-ties
that are not annotated with the Transient annotation are persistent.
WhenAccess(PROPERTY) is applied to such a class, it is possible to
selectively designate indi-vidual attributes within the class for instance
variable access. To specify a persistent instancevariable for access by the
persistence provider runtime, that instance variable must be desig-nated
Access(FIELD).</quote>*
I can see a few different ways to read that:
1) @Access can be placed on the attribute to define both where to look for
mapping annotations and the runtime access strategy for a given attribute.
Here, we'd do:
@Entity
@Access(AccessType.PROPERTY)
public class Course3 {
@Id
@GeneratedValue
@Access(AccessType.FIELD)
private long id;
...
public long getId() {
return id;
}
...
}
2) @Access can be placed on the attribute to define the runtime access
strategy for a given attribute, but the class/hierarchy AccessType controls
where to look for mapping annotations. This would lead to:
@Entity
@Access(AccessType.PROPERTY)
public class Course3 {
@Access(AccessType.FIELD)
private long id;
...
@Id
@GeneratedValue
public long getId() {
return id;
}
...
}
The test seems to illustrate that our legacy code made yet a 3rd reading of
this passage such that @Access is still considered a "mapping annotation"
even though that seems to directly contradict "To specify a persistent
instance
variable for access by the persistence provider runtime, that instance
variable must be desig-
nated Access(FIELD)."
Is there some other passage I am missing that bears on what to do here?
How do y'all feel about that passage and its implications on this test
mapping?
10 years, 5 months
[OGM] Move container integration test to a separate default test cycle
by Emmanuel Bernard
This is a follow up on
https://github.com/hibernate/hibernate-ogm/pull/307#issuecomment-38453092
We keep piling up new backends, new containers to test and new rules
checked at build time. A consequence is that it is becoming less and
less pleasant to work on OGM.
You can see that n version of Naked+WF+EAP+... multiplied by m backends
simply will make this project horrendously slow to contribute to.
I imagine n = 3 or 4 and m = 10 in a medium term.
I see two options that would keep us around for a while:
1. Make the container integration tests only run with a specific option
activated on the CI.
2. Move the container integration tests outside in a different repo
altogether.
I do prefer 1.
Emmanuel
10 years, 5 months
[Search] OSGi split packages
by Hardy Ferentschik
Hi there,
As part of my work for making Search OSGi ready [1], I am looking into addressing HSEARCH-1560 [2] which is about
split packages which we have between some of our Search bundles (or modules to use Maven lingo).
Basically a split package "is caused where two or more bundles export the same package name and version, usually with different contents”. [3]
In terms of OSGi, split packages are bad and should be avoided. There exists a work around [3], but afaiu it is frowned upon.
While working on an integration test trying to run Search in Apache Karaf, I was running into this problem and basically needed (for the time being)
revert to the mentioned work around.
The biggest for getting rid of split packages is org.hibernate.search which is a split packages between the engine and orm bundle. In org.hibernate.search of engine
we have:
- Environment,
- FullTextFilter,
- ProjectionConstants,
- SearchException,
- SearchFactory
- Version.
org.hibernate.search of orm contains:
- FullTextQuery,
- FullTextSession,
- FullTextSharedSessionBuilder,
- MassIndexer
- Search.
As you can see, these are quite central classes and moving any of them around will break existing code (even though updating just requires
to change import statements). If we are serious with OSGi we should address this. We always said, that Search 5 is the release where we can break
API backwards compatibility. So if we want to do this, we should do it now. On the other hand, it is a big change.
I went ahead and tried to refactor org.hibernate.search in engine, applying the following changes:
org.hibernate.search.Environment -> org.hibernate.search.cfg.Environment
org.hibernate.search.SearchFactory -> org.hibernate.search.spi.SearchFactory
org.hibernate.search.SearchException -> org.hibernate.search.exception.SearchException
org.hibernate.search.FullTextFilter -> org.hibernate.search.filter.FullTextFilter
org.hibernate.search.Version -> org.hibernate.search.engine.Version
Some of these changes I actually find quite fitting independently of the split package problem. FullTextFilter seems to have found its true home now
and Version and Environment don’t seem too bad either. The big change is SearchFactory and .SearchException.
WDYT? Is this package refactoring something worth doing and if so what do you think about the new locations of the classes? Any better suggestions?
Or do you think the orm bundle should be refactored instead?
You can see the preliminary result here [4].
—Hardy
[1] https://hibernate.atlassian.net/browse/HSEARCH-1465
[2] https://hibernate.atlassian.net/browse/HSEARCH-1560
[3] http://wiki.osgi.org/wiki/Split_Packages
[4] https://github.com/hferentschik/hibernate-search/compare/HSEARCH-1560
10 years, 5 months
ORM 3 JIRA tickets
by Brett Meyer
Recently, we've been trying to clean up ORM's JIRA tickets. There are a lot of duplication, stale issues, etc. One thought was pushing all ORM 3 tickets to the "Awaiting Test Case" state and requesting a reproducer on ORM 4 or 5. They would then fall under our policy of automatically rejecting those tickets that did not receive a test case within 3 months or so. This obviously would not include new features/improvements, anything assigned to someone, etc.
Here's an example filter that would be used:
https://hibernate.atlassian.net/issues/?filter=14660
project = HHH AND issuetype = Bug AND status in (Open, "In Progress", Reopened, "Awaiting Test Case") AND affectedVersion in ([all ORM 3 version]) AND affectedVersion not in ([all ORM 4/5 versions]) AND assignee in (EMPTY) AND reporter not in ([core contributors]) AND updated < -90d
That results in 716 tickets, providing a considerable dent.
I thought it would be important to solicit other opinions. Any suggestions or alternate ideas? Anything missing from the query that might make it too aggressive?
Brett Meyer
Red Hat, Hibernate ORM
10 years, 5 months
Session and carrying 3rd party state
by Emmanuel Bernard
I took some more time to think about our conversation from 2 IRC meeting ago
about offering the ability to carry session bound state not related to
ORM per se.
Below is a sum and a potential solution.
If you are short on time, read Goals, then the SessionSessionEventListener
approach and ignore the rest.
## Goals
The goal is to be able to carry session bound state for non-ORM projects
like search and OGM.
We want to avoid ThreadLocal use, in particular when it cannot be
protected by a try / catch for proper resource cleaning.
We want to avoid a structure that would be shared across threads concurrently
i.e. using ConcurrentHashMap with a Weak reference to the session.
It needs to be informed of a call to session.clear()
It needs to be informed of a call to session.close()
The state needs to be accessed from event listener implementations and custom
persister / loader implementations i.e. SessionImplementor and maybe
EventSource?
## Approaches
I'll discuss the approaches we explored in the meeting and then offer an
alternative one that I think is pretty interesting and fit better with
the current Session model.
### Map
This is essentially sticking a map on SessionImpl and use it to carry
state.
The following is a pseudo implementation
/**
* interface implemented by SessionImpl and the like
*/
interface SessionCompanion {
Object getCompanion(String key);
void addCompanion(String key, Object companion);
void removeCompanion(String key);
}
/**
* adds a map to the SessionImpl
*/
SessionImpl {
private Map<String, Object> companions;
public Object getCompanion(String key) { return companions.get(key); }
public void addCompanion(String key, Object value) { companions.add(key, companion); }
public void removeCompanion(String key) { companions.remove(key) }
}
The persister or event listener would call SessionCompation.*Companion method
to put and retrieve its state.
There is no clear / close event listener loop and it would need to be added.
### Delegator
Gunnar and teve discussed an approach where the delegator would be passed to
the underlying session and be accessible via an `unwrap` method.
I have not followed the details but this approach has one major flaw: the
delegator (OgmSession, FullTextSession etc) is not always created and thus
would not be necessarily available.
A somewhat similar idea involving passing the session owner has the same
drawback. And another one described by Gunnar in
https://hibernate.atlassian.net/browse/OGM-469
### The type-safe map approach
This approach is vaguely similar to the Map approach except that the payload is
represented and looked up by Class. This has the benefit of not having
namespace problems and is generally less String-y.
/**
* interface implemented by SessionImpl and the like
*/
interface SessionCompanion {
T getCompanion(Class<T> type);
void addCompanion(Object companion);
void removeCompanion(Class<?> type)
}
SessionImpl {
//could also use an array or an ArrayList
private Map<Class<?>, Object> companions;
public T getCompanion(Class<T> type) { return (T) companions.get(type); }
public void addCompanion(Object companion) { companions.add(companion.getClass(), type); }
public void removeCompanion(Class<T> type) { companions.remove(type); }
}
Like in the Map approach, the persister or custom event listener would interact
with SessionCompanion.
There are open issues like what should be done when two objects of the same
type are added to the same session.
Likewise the clear / close hook issues need to be addressed.
### the SessionEventListener approach
I did not know but there is a concept of `SessionEventListener` which can be
added to a `SessionImplementor`. It has hooks that are addressing most of the
goals.
//interface already exists
interface SessionImplementor {
public SessionEventListenerManager getEventListenerManager();
}
//interface already exists
public interface SessionEventListenerManager extends SessionEventListener {
// add this method to be able to retrieve a specific listener holding some state for a 3rd party project
List<SessionEventListener> getSessionEventListeners();
}
OGM or Search would implement a `SessionEventListener` and attach an instance to a session via `Session.addEventListeners()`.
It would require to add a method to retrieve the list of `SessionEventListener`s attached to a `SessionEventListenerManager`.
List<SessionEventListeners> listeners = sessionImplementor.getSessionEventListenerManager().getEnlistedListeners();
OgmSessionEventListener ogmListener = findOrAddOgmListener(sessionImplementor, listeners);
ogmListener.someStuff();
## What about clear and close?
We have a few ways to react to these.
SessionEventListener is already called back when a flush begins / ends as well as when Session closes.
We need to either:
- add a clear begins / ends callback
- have the third party project add a ClearEventListener which would access the SessionEventListeners and do some magic.
The first approach has my preference and would do:
public interface SessionEventListener {
[...]
void clearStart();
void clearEnd();
}
What do you guys think? The SessionEventListener approach feels more natural.
Emmanuel
10 years, 5 months