[Hibernate-JIRA] Created: (HHH-3298) Hibernate does not correcly apply LockMode.UPGRADE when performing a polymorphic select to a leaf-class via a mapped superclass on Oracle
by Mike Everett (JIRA)
Hibernate does not correcly apply LockMode.UPGRADE when performing a polymorphic select to a leaf-class via a mapped superclass on Oracle
-----------------------------------------------------------------------------------------------------------------------------------------
Key: HHH-3298
URL: http://opensource.atlassian.com/projects/hibernate/browse/HHH-3298
Project: Hibernate3
Issue Type: Bug
Components: core
Affects Versions: 3.2.6
Environment: Hibernate 3.2.6, Oracle 10gR2
Reporter: Mike Everett
Attachments: src.zip
Greetings All,
I'm experiencing an issue with Hibernate generated SQL when I attempt to retrieve a union-subclass entity via a concrete mapped superclass with LockMode.UPGRADE.
Hibernate will generate SQL with a UNION ALL of the sub-classes and then apply FOR UPDATE to the query which is not allowed with Oracle.
This leads to the following error:
java.sql.SQLException: ORA-02014: cannot select FOR UPDATE from view with DISTINCT, GROUP BY, etc.
It seems that "etc." part includes UNION and UNION ALL.
Example with three classes:
Entity (abstract) <--extends--- ConcreteInheritorOne (concrete) <--extends-- ConcreteInheritorTwo (concrete)
assume:
inheritorTwoId == the id of an item of class ConcreteInheritorTwo
session == a Hibernate Session
// These lookups will cause the error
Entity e = (Entity) session.get(Entity.class, inheritorTwoId, LockMode.UPGRADE);
Entity e = (Entity) session.get(ConcreteInheritorOne.class, inheritorTwoId, LockMode.UPGRADE);
// This will not cause the error
Entity e = (Entity) session.get(ConcreteInheritorTwo.class, inheritorTwoId, LockMode.UPGRADE);
I have attached entity classes and a Test class which illustrate this effect.
I spelunked into the code a bit, but an easy fix did not present itself to my hibernate-code-virgin eyes.
Thanks for making Hibernate great!
--Mje
#### Workaround ####
If anyone else is experiencing this problem, I've implemented code similar to the method below as a work-around in an abstraction layer:
public Object getEntityForUpdate(Class entityClass, String entityId)
{
Session s = getSession();
ClassMetadata meta = s.getSessionFactory().getClassMetadata(entityClass);
Boolean doTwoPhaseLock = false;
if(meta instanceof UnionSubclassEntityPersister)
{
if(((UnionSubclassEntityPersister)meta).getEntityMetamodel().getSubclassEntityNames().size() > 1)
doTwoPhaseLock = true;
}
if(doTwoPhaseLock)
{
Entity e = (Entity)s.get(entityClass, entityId);
System.out.println("Using Two-Phase Lock on: EntityId[" + entityId + "] EntityClass[" + entityClass.getName() + "]");
s.lock(e, LockMode.UPGRADE);
return e;
}
else
{
System.out.println("Using One-Phase Lock on: EntityId[" + entityId + "] EntityClass[" + entityClass.getName() + "]");
return s.get(entityClass, entityId, LockMode.UPGRADE);
}
}
#### Hibernate Generated SQL Example ####
select
entity0_.id as id6_0_,
entity0_.versionNumber as versionN2_6_0_,
entity0_.clazz_ as clazz_0_
from
(
select versionNumber, id, 2 as clazz_
from BASE_ConcreteInheritorTwo
union all
select versionNumber, id, 1 as clazz_
from BASE_ConcreteInheritorOne
) entity0_ where entity0_.id=?
for update
#### Stack Trace ####
15:18:14,484 ERROR JDBCExceptionReporter:78 - ORA-02014: cannot select FOR UPDATE from view with DISTINCT, GROUP BY, etc.
15:18:14,484 INFO DefaultLoadEventListener:111 - Error performing load command
org.hibernate.exception.SQLGrammarException: could not load an entity: [org.example.domain.hibernate.Entity#1211505494256]
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:67)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
at org.hibernate.loader.Loader.loadEntity(Loader.java:1874)
at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:48)
at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:42)
at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:3049)
at org.hibernate.event.def.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:399)
at org.hibernate.event.def.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:375)
at org.hibernate.event.def.DefaultLoadEventListener.load(DefaultLoadEventListener.java:139)
at org.hibernate.event.def.DefaultLoadEventListener.lockAndLoad(DefaultLoadEventListener.java:297)
at org.hibernate.event.def.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:106)
at org.hibernate.impl.SessionImpl.fireLoad(SessionImpl.java:878)
at org.hibernate.impl.SessionImpl.get(SessionImpl.java:869)
at org.hibernate.impl.SessionImpl.get(SessionImpl.java:864)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.hibernate.context.ThreadLocalSessionContext$TransactionProtectionWrapper.invoke(ThreadLocalSessionContext.java:301)
at $Proxy0.get(Unknown Source)
at org.example.test.Test.doTest2(Test.java:68)
at org.example.test.Test.main(Test.java:35)
Caused by: java.sql.SQLException: ORA-02014: cannot select FOR UPDATE from view with DISTINCT, GROUP BY, etc.
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:112)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:331)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:288)
at oracle.jdbc.driver.T4C8Oall.receive(T4C8Oall.java:745)
at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:216)
at oracle.jdbc.driver.T4CPreparedStatement.executeForDescribe(T4CPreparedStatement.java:810)
at oracle.jdbc.driver.OracleStatement.executeMaybeDescribe(OracleStatement.java:1039)
at oracle.jdbc.driver.T4CPreparedStatement.executeMaybeDescribe(T4CPreparedStatement.java:850)
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1134)
at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3339)
at oracle.jdbc.driver.OraclePreparedStatement.executeQuery(OraclePreparedStatement.java:3384)
at org.hibernate.jdbc.AbstractBatcher.getResultSet(AbstractBatcher.java:186)
at org.hibernate.loader.Loader.getResultSet(Loader.java:1787)
at org.hibernate.loader.Loader.doQuery(Loader.java:674)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:236)
at org.hibernate.loader.Loader.loadEntity(Loader.java:1860)
... 19 more
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://opensource.atlassian.com/projects/hibernate/secure/Administrators....
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
12 years, 1 month
[Hibernate-JIRA] Created: (ANN-654) Generated SQL includes a column named "null" when referencing a map entry by key and using @LazyCollection(LazyCollectionOption.EXTRA)
by Paul Roe (JIRA)
Generated SQL includes a column named "null" when referencing a map entry by key and using @LazyCollection(LazyCollectionOption.EXTRA)
--------------------------------------------------------------------------------------------------------------------------------------
Key: ANN-654
URL: http://opensource.atlassian.com/projects/hibernate/browse/ANN-654
Project: Hibernate Annotations
Issue Type: Bug
Components: binder
Affects Versions: 3.2.0.ga
Environment: Oracle 10g, hibernate 3.2
Reporter: Paul Roe
We have an Product entity with a map of RegionProduct by Region.
@MapKey(name="region")
@OneToMany(mappedBy="product", targetEntity= RegionProductImpl.class, fetch = FetchType.LAZY)
@LazyCollection(LazyCollectionOption.EXTRA)
private Map<Region, RegionProduct> regionProducts = new HashMap<Region, RegionProduct>();
When accessing an element of the map by key, the SQL that is generated includes a "null" column in the WHERE condition.
where regionprod0_.PROD_ID=? and regionprod0_.null=?
resulting in the stack trace
org.hibernate.exception.SQLGrammarException: could not collection element by index
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:67)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
at org.hibernate.loader.Loader.loadEntity(Loader.java:1841)
at org.hibernate.loader.entity.CollectionElementLoader.loadElement(CollectionElementLoader.java:72)
at org.hibernate.persister.collection.OneToManyPersister.getElementByIndex(OneToManyPersister.java:360)
at org.hibernate.collection.AbstractPersistentCollection.readElementByIndex(AbstractPersistentCollection.java:158)
at org.hibernate.collection.PersistentMap.get(PersistentMap.java:146)
Iterating over the collection works successfully, but populates the entire collection, which is what Extra-Lazy is meant to avoid.
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://opensource.atlassian.com/projects/hibernate/secure/Administrators....
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
12 years, 1 month
[Hibernate-JIRA] Created: (HHH-4953) Inconsistent behavior when fetching cached subclass entities from 2L
by Guenther Demetz (JIRA)
Inconsistent behavior when fetching cached subclass entities from 2L
--------------------------------------------------------------------
Key: HHH-4953
URL: http://opensource.atlassian.com/projects/hibernate/browse/HHH-4953
Project: Hibernate Core
Issue Type: Bug
Components: caching (L2)
Affects Versions: 3.5.0-CR-2, 3.5.0-CR-1, 3.5.0-Beta-4, 3.5.0-Beta-3, 3.5.0-Beta-2, 3.5.0.Beta-1, 3.3.1, 3.2.5
Environment: Hibernate3.5.0CR2,HSQLDB, EHCache as 2L-cache Impl
Reporter: Guenther Demetz
Attachments: Test2LCache.jar
Enabling the hibernate second-level cache is leading to inconsistent behavior when fetching cached subclass entities as opposed to fetching non-cached subclass entities.
For more informations, please see
https://forum.hibernate.org/viewtopic.php?f=1&t=1002880&p=2425931#p2425931
Testcase attached.
Cause:
IMHO the bug consists in the fact, that
persister.getRootEntityName() instead to persister.getEntityName() is passed as 3thrd parameter
to the constructor of CacheKey in most places where CacheKey is used, for example in DefaultLoadEventListener.java:
new CacheKey(
event.getEntityId(),
persister.getIdentifierType(),
persister.getRootEntityName(),
source.getEntityMode(),
source.getFactory()
In this way the real entity name get swallowed and the type-saveness is not guaranteed anymore.
Workaround:
Subclass2 tofind = null;
try {
tofind = (Subclass2) em.find(Subclass2.class,"identifier1");
}
catch (ClassCastException cc) {
// swallow , this is a workaround
}
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://opensource.atlassian.com/projects/hibernate/secure/Administrators....
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
12 years, 1 month
[Hibernate-JIRA] Created: (HHH-3854) Issue with greedy loading of associations (default-lazy=false )
by Amar Singh (JIRA)
Issue with greedy loading of associations (default-lazy=false )
---------------------------------------------------------------
Key: HHH-3854
URL: http://opensource.atlassian.com/projects/hibernate/browse/HHH-3854
Project: Hibernate Core
Issue Type: Bug
Components: envers
Environment: Hibernate - core 3.4.0-SNAPSHOT, Hibernate-envers (from trunk)
Reporter: Amar Singh
Attachments: greedy-loading.zip
I have an Entity GP which has a many to one association to entity CA.
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="org.hibernate.envers.test.integration.onetoone.bidirectional" default-lazy="false">
<class name="BidirectionalRefIngPK" table="BIDIRECTIONAL_REFERENCING_ENTITY">
<id name="id" type="long" column="BIDIRECTIONAL_REFERENCING_ID" >
<generator class="native"/>
</id>
<property name="data"/>
<many-to-one name="reference" cascade="save-update" class="BidirectionalRefEdPK" column="BIDIRECTIONAL_REFERENCED_ID"/>
</class>
<class name="BidirectionalRefEdPK" table="BIDIRECTIONAL_REFERENCED_ENTITY">
<id name="longId" type="long" column="BIDIRECTIONAL_REFERENCED_ID">
<generator class="native"/>
</id>
<property name="data"/>
</class>
</hibernate-mapping>
With this when I load a previous version of BidirectionalRefIngPK, the loading mechanism tries to create a proxy for BidirectionalRefEdPK, but in my case lazy is false so an internal call to createProxy will return NULL hence .
This happens in ToOneIdMapper.java in method mapToEntityFromMap around line 82, which then internally calls for AbstractEntityTuplizer.java line 395 for getProxyFactory() ending in NULL pointer exception because proxy factory is null as mine is a greedy loading.
TO REPRODUCE
~~~~~~~~~~~~~
Please find a zipped folder attached. The zipped file has 4 files:
- GreedyLoading.java (actual testng test case)
- BidirectionalRefEdPK.java (Entity 1)
- BidirectionalRefIngPK.java (Entity 2)
- greedyloading.hbm.xml
Please place the three java files in its package (org.hibernate.envers.test.integration.onetoone.bidirectional), couldn't find the right package so created test case accordingly. Put the greedyloading.hbm.xml in src/test/resources.
Now when testng runs GreedyLoading.java you should see NPE.
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://opensource.atlassian.com/projects/hibernate/secure/Administrators....
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
12 years, 1 month