[Hibernate-JIRA] Updated: (HHH-1668) PersistentSet write methods mark collection as dirty even if entry is not written
by Josh Moore (JIRA)
[ http://opensource.atlassian.com/projects/hibernate/browse/HHH-1668?page=all ]
Josh Moore updated HHH-1668:
----------------------------
Attachment: PersistentList.patch
Added a patch for PersistentList.java to make it pass the also attached test.
> PersistentSet write methods mark collection as dirty even if entry is not written
> ---------------------------------------------------------------------------------
>
> Key: HHH-1668
> URL: http://opensource.atlassian.com/projects/hibernate/browse/HHH-1668
> Project: Hibernate3
> Type: Bug
> Components: core
> Versions: 3.1.3
> Reporter: Koda Janh
> Assignee: Steve Ebersole
> Fix For: 3.2.1
> Attachments: PersistentList.patch, PersistentSet.patch, hhh-1668.tests.txt
>
> Original Estimate: 5 minutes
> Remaining: 5 minutes
>
> PersistentSet gets marked as dirty even if it hasn't changed. This has negative implications for concurrency because the optimistic-lock version is incremented and StaleObjectStateException is thrown even if the underlying data remains unchanged.
> I stepped through the code and narrowed down the problem to a bug in PersistentSet.add(). A simple fix is to replace:
> if (exists==null) {
> write();
> return set.add(value);
> }
> by:
> if (exists==null) {
> boolean result = set.add(value);
> if (result) {
> write();
> }
> return result;
> }
> I verified that this fixed the problem on my end. The old code was always marking the Set as dirty whereas the new code only does so if it actually has been modified. Please commit this patch.
--
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
16 years, 8 months
[Hibernate-JIRA] Commented: (HHH-1668) PersistentSet write methods mark collection as dirty even if entry is not written
by Josh Moore (JIRA)
[ http://opensource.atlassian.com/projects/hibernate/browse/HHH-1668?page=c... ]
Josh Moore commented on HHH-1668:
---------------------------------
The PeristentMapTest additions in hhh-1668.tests.txt are no longer valid. Somewhere a change has made the keySet() and values() sets immutable (perfect). The PersistentListTest and Co. however still fail.
> PersistentSet write methods mark collection as dirty even if entry is not written
> ---------------------------------------------------------------------------------
>
> Key: HHH-1668
> URL: http://opensource.atlassian.com/projects/hibernate/browse/HHH-1668
> Project: Hibernate3
> Type: Bug
> Components: core
> Versions: 3.1.3
> Reporter: Koda Janh
> Assignee: Steve Ebersole
> Fix For: 3.2.1
> Attachments: PersistentSet.patch, hhh-1668.tests.txt
>
> Original Estimate: 5 minutes
> Remaining: 5 minutes
>
> PersistentSet gets marked as dirty even if it hasn't changed. This has negative implications for concurrency because the optimistic-lock version is incremented and StaleObjectStateException is thrown even if the underlying data remains unchanged.
> I stepped through the code and narrowed down the problem to a bug in PersistentSet.add(). A simple fix is to replace:
> if (exists==null) {
> write();
> return set.add(value);
> }
> by:
> if (exists==null) {
> boolean result = set.add(value);
> if (result) {
> write();
> }
> return result;
> }
> I verified that this fixed the problem on my end. The old code was always marking the Set as dirty whereas the new code only does so if it actually has been modified. Please commit this patch.
--
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
16 years, 8 months
[Hibernate-JIRA] Updated: (HHH-1401) session.merge() executes unnecessary updates when one-to-many relationship is defined.
by Josh Moore (JIRA)
[ http://opensource.atlassian.com/projects/hibernate/browse/HHH-1401?page=all ]
Josh Moore updated HHH-1401:
----------------------------
Attachment: HHH1401Test.java
Attached new HHH1401Test (replaces version in zip). Has second test using collections which fail despite the fixes Steve made to HHH-1668.
> session.merge() executes unnecessary updates when one-to-many relationship is defined.
> --------------------------------------------------------------------------------------
>
> Key: HHH-1401
> URL: http://opensource.atlassian.com/projects/hibernate/browse/HHH-1401
> Project: Hibernate3
> Type: Bug
> Components: core
> Versions: 3.1.1
> Environment: Hibernate 3.1.1
> Postgres 8.03
> Java 1.4.2_09
> Reporter: David Trott
> Assignee: Steve Ebersole
> Fix For: 3.2.1
> Attachments: HHH-1401.zip, HHH1401Test.java, Screenshot-Debug - AbstractPersistentCollection.class - Eclipse SDK .png, TEST-org.hibernate.test.optlock.OptimisticLockTest.txt
>
>
> I am attempting to use the session.merge() functionality in order to synchronize the state of the data coming from the web tier with the database, however I am seeing unnecessary updates (when nothing has changed).
> In order to track down the problem I created a test case with four tables and four classes (A,B,C and D)
> Where:
> A is the parent of B.
> B is the parent of C.
> C is the parent of D.
> And there are no other relationships present.
> All these relationships are bi-directional with the one-to-many side marked as inverse="true" and cascade="all-delete-orphan".
> The merge() is working fine (the data gets updated correctly) except that when there is no change to the data hibernate still runs updates on A,B and C however not on D (D has no one-to-many relationships).
> I am including the code and hibernate mapping for B as it is representative of the code for all the other classes.
> I am no expect on the hibernate implementation, but my suspicion of the cause is when hibernate substitutes a PersistentBag for the ArrayList in the merged object (associated with the session) it detects this as a change and hence triggers the update, unfortunately the data itself has not changed hence no update is necessary.
> FYI: If I change the initialization of the bags from "new ArrayList()" to "new PersistentBag()" the extra updates go away, however then it doesn't save real changes correctly.
> package com.mycompany.dal.transfer.impl;
> import org.apache.commons.lang.builder.EqualsBuilder;
> import org.apache.commons.lang.builder.HashCodeBuilder;
> import org.apache.commons.lang.builder.ToStringBuilder;
> import java.util.ArrayList;
> import java.util.Collections;
> import java.util.List;
> import com.mycompany.dal.transfer.interfaces.ADTO;
> import com.mycompany.dal.transfer.interfaces.BDTO;
> import com.mycompany.dal.transfer.interfaces.CDTO;
> import org.apache.commons.collections.Closure;
> import org.apache.commons.collections.CollectionUtils;
> public class BDTOImpl implements BDTO {
> public BDTOImpl () {
> }
> private Long bId;
>
> public Long getBId() {
> return bId;
> }
> public void setBId(Long bId) {
> this.bId = bId;
> }
> private Long concurrentVersion;
>
> public Long getConcurrentVersion() {
> return concurrentVersion;
> }
> public void setConcurrentVersion(Long concurrentVersion) {
> this.concurrentVersion = concurrentVersion;
> }
> // Package level protection so that overrides can access it.
> boolean deleting = false;
> private String name;
> /**
> * Returns the Name.
> *
> * @return String - The Name
> */
> public String getName() {
> return name;
> }
> /**
> * Set the Name.
> *
> * @param name String - The Name.
> */
> public void setName(String name) {
> this.name = name;
> }
> private ADTO a;
> /**
> * Returns the A.
> *
> * @return ADTO - The A.
> */
> public ADTO getA() {
> return a;
> }
>
> public ADTO getAInternal() {
> return a;
> }
> /**
> * Updates the A.
> *
> * @param a - ADTO The A.
> */
> public void setA(ADTO a) {
> if (this.a == a) {
> return;
> }
> if (this.a != null) {
> ((ADTOImpl) this.a).removeBInternal(this);
> }
> this.a = a;
> if (a != null) {
> ((ADTOImpl) a).addBInternal(this);
> }
> }
> public void setAInternal(ADTO a) {
> if (deleting) {
> return;
> }
> if (this.a != a &&
> this.a != null && a != null) {
> throw new IllegalStateException("BDTO cannot be a member of two A collections: " + toString());
> }
> this.a = a;
> }
> private List cs;
> private List csMutable;
> { setCsMutable(new ArrayList()); }
> public List getCsMutable() {
> return csMutable;
> }
> public void setCsMutable(List cs) {
> this.cs = Collections.unmodifiableList(cs);
> this.csMutable = cs;
> }
> public List getCs() {
> return cs;
> }
>
> public void addC(CDTO c) {
> csMutable.add(c);
> ((CDTOImpl) c).setBInternal(this);
> }
> public void addCInternal(CDTO c) {
> csMutable.add(c);
> }
>
> public void removeC(CDTO c) {
> csMutable.remove(c);
> ((CDTOImpl) c).setBInternal(null);
> }
> public void removeCInternal(CDTO c) {
> if (!deleting) {
> csMutable.remove(c);
> }
> }
> public void beforeDelete() {
> // Guard to prevent infinite loop.
> if (deleting) {
> return;
> }
>
> deleting = true;
> if (this.a != null) {
> ((ADTOImpl) this.a).removeBInternal(this);
> }
> CollectionUtils.forAllDo(new ArrayList(csMutable), new Closure() {
> public void execute(Object ob) {
> ((CDTOImpl) ob).beforeDelete();
> }
> });
> }
> public int hashCode() {
> return (new HashCodeBuilder(17,37)
> .append(getBId())
> ).toHashCode();
> }
> public boolean equals(Object o) {
> boolean equals = false;
> if (o != null && o instanceof BDTO) {
> BDTO other = (BDTO) o;
> return (new EqualsBuilder()
> .append(getBId(), other.getBId())
> ).isEquals();
> }
> return equals;
> }
>
> public String toString() {
> return new ToStringBuilder(this)
> .append("bId", getBId())
> .append("name", getName())
> .toString();
> }
> }
> ******************************
> *** Mapping Document ****
> ******************************
> <?xml version="1.0" encoding="UTF-8"?>
> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
> "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
> <hibernate-mapping package="com.mycompany.dal.transfer.impl" auto-import="true">
> <class name="com.mycompany.dal.transfer.impl.BDTOImpl" table="b">
> <id name="BId" type="long">
> <column name="b_id" not-null="true"/>
> <generator class="native"/>
> </id>
> <version name="concurrentVersion" column="concurrent_version" type="long"/>
> <property name="Name" type="string">
> <column name="name" length="60" not-null="false"/>
> </property>
> <many-to-one name="AInternal" class="com.mycompany.dal.transfer.impl.ADTOImpl">
> <column name="a_id" not-null="true"/>
> </many-to-one>
> <bag name="CsMutable" cascade="all-delete-orphan" inverse="true">
> <key>
> <column name="b_id" not-null="true"/>
> </key>
> <one-to-many class="com.mycompany.dal.transfer.impl.CDTOImpl"/>
> </bag>
> </class>
> </hibernate-mapping>
> *************************
> *** Generated SQL ****
> *************************
> 05:35:39,887 INFO [STDOUT] Hibernate: select adtoimpl0_.a_id as a1_162_2_, adtoimpl0_.concurrent_version as concurrent2_162_2_, adtoimpl0_.name as name162_2_, bsmutable1_.a_id as a4_4_, bsmutable1_.b_id as b1_4_, bsmutable1_.b_id as b1_164_0_, bsmutable1_.concurrent_version as concurrent2_164_0_, bsmutable1_.name as name164_0_, bsmutable1_.a_id as a4_164_0_, csmutable2_.b_id as b4_5_, csmutable2_.c_id as c1_5_, csmutable2_.c_id as c1_165_1_, csmutable2_.concurrent_version as concurrent2_165_1_, csmutable2_.name as name165_1_, csmutable2_.b_id as b4_165_1_ from a adtoimpl0_ left outer join b bsmutable1_ on adtoimpl0_.a_id=bsmutable1_.a_id left outer join c csmutable2_ on bsmutable1_.b_id=csmutable2_.b_id where adtoimpl0_.a_id=?
> 05:35:39,992 INFO [STDOUT] Hibernate: select ddtoimpl0_.d_id as d1_168_0_, ddtoimpl0_.concurrent_version as concurrent2_168_0_, ddtoimpl0_.name as name168_0_, ddtoimpl0_.c_id as c4_168_0_ from d ddtoimpl0_ where ddtoimpl0_.d_id=?
> 05:35:40,007 INFO [STDOUT] Hibernate: select dsmutable0_.c_id as c4_1_, dsmutable0_.d_id as d1_1_, dsmutable0_.d_id as d1_168_0_, dsmutable0_.concurrent_version as concurrent2_168_0_, dsmutable0_.name as name168_0_, dsmutable0_.c_id as c4_168_0_ from d dsmutable0_ where dsmutable0_.c_id=?
> *** Start Extra Updates **
> 05:35:40,030 INFO [STDOUT] Hibernate: update b set concurrent_version=?, name=?, a_id=? where b_id=? and concurrent_version=?
> 05:35:40,038 INFO [STDOUT] Hibernate: update c set concurrent_version=?, name=?, b_id=? where c_id=? and concurrent_version=?
> 05:35:40,044 INFO [STDOUT] Hibernate: update a set concurrent_version=?, name=? where a_id=? and concurrent_version=?
> *** End Extra Updates **
> **************************
> *** Accessing code ****
> **************************
> DataAccessLayer dal = DataAccessLayerBuilder.getInstance();
>
> ADAO aDAO = dal.getADAO();
> BDAO bDAO = dal.getBDAO();
> CDAO cDAO = dal.getCDAO();
> DDAO dDAO = dal.getDDAO();
>
> ADTO a = aDAO.newA();
> a.setAId(new Long(1));
> a.setConcurrentVersion(new Long(0));
> a.setName("A");
>
> BDTO b = bDAO.newB();
> CDTO c = cDAO.newC();
> DDTO d = dDAO.newD();
> b.setBId(new Long(2));
> c.setCId(new Long(3));
> d.setDId(new Long(4));
> b.setConcurrentVersion(new Long(0));
> c.setConcurrentVersion(new Long(0));
> d.setConcurrentVersion(new Long(0));
> b.setName("B");
> c.setName("C");
> d.setName("D");
> b.setA(a);
> c.setB(b);
> d.setC(c);
>
> aDAO.mergeA(a);
--
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
16 years, 8 months
[Hibernate-JIRA] Commented: (HHH-1895) HqlSqlWalker throws NullPointerException with explicit joins and component mapping
by Sam Wilson (JIRA)
[ http://opensource.atlassian.com/projects/hibernate/browse/HHH-1895?page=c... ]
Sam Wilson commented on HHH-1895:
---------------------------------
I have a very similar issue with 3.2.0CR2 (about to test 3.2.0CR4) running on SQL Server 2000/2005.
I'm going to do more research on the issue and post it here and may open a separate defect if it turns out to be different.
> HqlSqlWalker throws NullPointerException with explicit joins and component mapping
> ----------------------------------------------------------------------------------
>
> Key: HHH-1895
> URL: http://opensource.atlassian.com/projects/hibernate/browse/HHH-1895
> Project: Hibernate3
> Type: Bug
> Versions: 3.1.3
> Environment: Oracle 9i, Hibernate 3.1.3
> Reporter: Victor Suarez
> Priority: Minor
>
>
> HqlSqlWalker throws a NPE if a explicit join is used with fields that are mapped with component mapping. If explicit join is removed and implicit join is used, the HQL works fine. This kind of problem didn't occur with Hibernate2.
> Examples (hbm below):
> The query:
> String query = "FROM " + Pais.class.getName() + " AS pais JOIN pais.metaInfo AS minfo WHERE minfo.activo = true";
> fails with this stacktrace:
> Exception in thread "main" java.lang.NullPointerException
> at org.hibernate.hql.ast.HqlSqlWalker.createFromJoinElement(HqlSqlWalker.java:317)
> at org.hibernate.hql.antlr.HqlSqlBaseWalker.joinElement(HqlSqlBaseWalker.java:3268)
> at org.hibernate.hql.antlr.HqlSqlBaseWalker.fromElement(HqlSqlBaseWalker.java:3060)
> at org.hibernate.hql.antlr.HqlSqlBaseWalker.fromElementList(HqlSqlBaseWalker.java:2938)
> at org.hibernate.hql.antlr.HqlSqlBaseWalker.fromClause(HqlSqlBaseWalker.java:688)
> at org.hibernate.hql.antlr.HqlSqlBaseWalker.query(HqlSqlBaseWalker.java:544)
> at org.hibernate.hql.antlr.HqlSqlBaseWalker.selectStatement(HqlSqlBaseWalker.java:281)
> at org.hibernate.hql.antlr.HqlSqlBaseWalker.statement(HqlSqlBaseWalker.java:229)
> at org.hibernate.hql.ast.QueryTranslatorImpl.analyze(QueryTranslatorImpl.java:218)
> at org.hibernate.hql.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:158)
> at org.hibernate.hql.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:109)
> at org.hibernate.engine.query.HQLQueryPlan.<init>(HQLQueryPlan.java:75)
> at org.hibernate.engine.query.HQLQueryPlan.<init>(HQLQueryPlan.java:54)
> at org.hibernate.engine.query.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:71)
> at org.hibernate.impl.AbstractSessionImpl.getHQLQueryPlan(AbstractSessionImpl.java:133)
> at org.hibernate.impl.AbstractSessionImpl.createQuery(AbstractSessionImpl.java:112)
> at org.hibernate.impl.SessionImpl.createQuery(SessionImpl.java:1583)
> This one works fine:
> String query = "FROM " + Pais.class.getName() + " AS pais WHERE pais.metaInfo.activo = true";
> With this behaviour, HQL seems not to be totally transparent to mappings.
> Mapping file:
> <hibernate-mapping>
> <class name="Pais" table="Paises" lazy="true">
> <id name="id" type="long" column="id">
> <generator class="increment"/>
> </id>
> <component name="metaInfo" class="MetaInfo">
> <property name="usuarioAlta" column="usuarioAltaMetaInfo" type="string" not-null="false"/>
> <property name="fechaBaja" column="fechaBajaMetaInfo" type="timestamp" not-null="false"/>
> <property name="fechaAlta" column="fechaAltaMetaInfo" type="timestamp" not-null="false"/>
> <property name="activo" column="activoMetaInfo" type="boolean" not-null="false"/>
> <property name="usuarioBaja" column="usuarioBajaMetaInfo" type="string" not-null="false"/>
> </component>
> <property name="nombre" column="nombre" type="string" not-null="true"/>
> <property name="codigo" column="codigo" type="string" not-null="false"/>
>
> <set name="localidades" access="field" inverse="true"
> cascade="all-delete-orphan" lazy="true" batch-size="5">
> <key column="pais" />
> <one-to-many class="Localidad"/>
> </set>
> <set name="provincias" access="field" inverse="true"
> cascade="all-delete-orphan" lazy="true" batch-size="5">
> <key column="pais" />
> <one-to-many class="Provincia"/>
> </set>
>
> <property name="codAS400" type="string" not-null="false"/>
> </class>
> </hibernate-mapping>
--
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
16 years, 8 months
[Hibernate-JIRA] Created: (HBX-753) Hibernate Tools generates ID class with Oracle LONG data type
by Dan Madoni (JIRA)
Hibernate Tools generates ID class with Oracle LONG data type
-------------------------------------------------------------
Key: HBX-753
URL: http://opensource.atlassian.com/projects/hibernate/browse/HBX-753
Project: Hibernate Tools
Type: Bug
Components: reverse-engineer
Environment: Hibernate 3.0, Oracle, Hibernate Tools 3.2 beta 7
Reporter: Dan Madoni
Priority: Minor
If an Oracle table PK includes a LONG data type, Hibernate Tools dutifully generates an ID class that includes that LONG field. Later on when you query with the generated mapped classes, you get an "illegal use of LONG datatype" error (ORA-00997). This can be particularly frustrating since the typical lazy developer (like me) happily goes off and uses these generated classes, then is bewildered to run into an error in code he didn't create or bother to look at since the nice tool did all the work. :)
The first thing you're going to say, "what kind of moron includes a LONG data type as a PK anyway?" Suffice to say, such PK's exist and people like me have no say in the matter. So considering that some of us are forced between a rock (some zany db administrator) and a hard place (a requirement to use Hibernate), you can hopefully feel our pain. :)
--
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
16 years, 8 months
[Hibernate-JIRA] Commented: (HHH-1361) creating temporary table for bulk delete will commit current transaction in managed environment such as J2EE
by Tushar (JIRA)
[ http://opensource.atlassian.com/projects/hibernate/browse/HHH-1361?page=c... ]
Tushar commented on HHH-1361:
-----------------------------
Steve, the problem hasn't gone away - transactions are still being committed too early in Hibernate 3.1.3.
Could I please request a change to the Oracle9Dialect to the safest default, because it's quite a show stopper if Hibernate commits early.
{code}
public class HHH1361Oracle9Dialect extends Oracle9Dialect {
public boolean dropTemporaryTableAfterUse() {
return false;
}
public boolean performTemporaryTableDDLInIsolation() {
return true;
}
}
{code}
> creating temporary table for bulk delete will commit current transaction in managed environment such as J2EE
> ------------------------------------------------------------------------------------------------------------
>
> Key: HHH-1361
> URL: http://opensource.atlassian.com/projects/hibernate/browse/HHH-1361
> Project: Hibernate3
> Type: Bug
> Components: core
> Versions: 3.1
> Environment: J2EE container; Oracle
> Reporter: Jifeng Liu
> Assignee: Steve Ebersole
> Fix For: 3.1.1
> Attachments: hibernate.cfg.xml, stacktrace.txt
>
>
> I have a table mapping with joined-subclass as following. When I execute bulk delete statement:
> session.createQuery( "delete from Job j where j.status = :status" )
> .setString( "status", pStatus )
> .executeUpdate()
> Hibernate will automatically create a temporary table called HT_Job to store job ids. This will cause current database transaction committed. Because I am using J2EE container managed transaction (CMT), this commit behavior is not good. And I also lose opportunity to rollback the transaction.
> <class name="com.senior.bll.shared.jobs.Job"
> table="job" rowid="rowid">
> <id name="id" column="job_id"/>
> <version name="updateDateTime" column="update_date_time" type="oracle_date"></version>
> <property name="type" column="job_type"/>
> <joined-subclass name="com.senior.bll.entity.constituent.messaging.schedules.MessageJob"
> table="message_job_data" >
> <key column="job_id" />
> <property name="queryId" column="query_id"/>
> </joined-subclass>
> </class>
--
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
16 years, 8 months