Return-Path: Delivered-To: apmail-cayenne-user-archive@www.apache.org Received: (qmail 21794 invoked from network); 19 Sep 2008 09:26:57 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 19 Sep 2008 09:26:57 -0000 Received: (qmail 12172 invoked by uid 500); 19 Sep 2008 09:26:53 -0000 Delivered-To: apmail-cayenne-user-archive@cayenne.apache.org Received: (qmail 12159 invoked by uid 500); 19 Sep 2008 09:26:53 -0000 Mailing-List: contact user-help@cayenne.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: user@cayenne.apache.org Delivered-To: mailing list user@cayenne.apache.org Received: (qmail 12138 invoked by uid 99); 19 Sep 2008 09:26:53 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 19 Sep 2008 02:26:53 -0700 X-ASF-Spam-Status: No, hits=2.0 required=10.0 tests=HTML_MESSAGE,SPF_HELO_PASS,SPF_PASS X-Spam-Check-By: apache.org Received-SPF: pass (athena.apache.org: domain of contact@genux.fr designates 88.191.42.248 as permitted sender) Received: from [88.191.42.248] (HELO genux.fr) (88.191.42.248) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 19 Sep 2008 09:25:54 +0000 Received: from [200.190.12.96] (unknown [212.51.168.10]) by genux.fr (Postfix) with ESMTP id 7EBFB4C010; Fri, 19 Sep 2008 11:29:46 +0200 (CEST) Message-ID: <48D37020.2070606@genux.fr> Date: Fri, 19 Sep 2008 11:25:52 +0200 From: Laurent Marchal User-Agent: Thunderbird 2.0.0.16 (X11/20080724) MIME-Version: 1.0 To: user@cayenne.apache.org CC: Francois Eyl Subject: Re: 3.0M4 : Fetching from relationship returns TRANSIENT objects. Content-Type: multipart/mixed; boundary="------------080604070503060107030704" X-Virus-Checked: Checked by ClamAV on apache.org --------------080604070503060107030704 Content-Type: multipart/alternative; boundary="------------080709070403050600090305" --------------080709070403050600090305 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Hi Andrus, I post on the mailing list with a new mail adress, because my provider sucks.... I will try to detail more what i do, so you can reproduce this in your test case. Maybe i'ts because you don't have prefetching or "to dep PK". There is a relationship between MasterJob--->MasterJobAux where i checked "To Dep PK" since no ARTIST_AUX rows can exists without corresponding MasterJob. When i fetch a MasterJob i have added a prefetch for MasterJobAux : query.addPrefetch(MasterJob.RELATED_MASTER_JOB_AUX_PROPERTY); Code I use to get/create/delete MasterJobAux protected MasterJobAux createAux(ILookupFieldCodes fieldCode, Short seqNo, String value) { MasterJobAux aux = MasterJob.this.getObjectContext().newObject(MasterJobAux.class); aux.setScheduleId(MasterJob.this.getScheduleId()); aux.setJobName(MasterJob.this.getJobName()); aux.setJaFieldCode((int) fieldCode.getID()); aux.setJaSequenceNumber(seqNo); aux.setJavalue(value); aux.setRelatedMasterJob(MasterJob.this); return aux; } protected List fetchAuxList() throws OpconException { return MasterJob.this.getRelatedMasterJobAux(); } protected void deleteAux(MasterJobAux toDelete) throws OpconException { MasterJob.this.removeFromRelatedMasterJobAux(toDelete); MasterJob.this.getObjectContext().deleteObject(toDelete); } Cayenne XML : To reproduce the problem : 1) Fetch MasterJobAux using the relationships MasterJob.getRelatedMasterJobAux(); 2) delete/create some MasterJobAux MasterJob.removeFromRelatedMasterJobAux(toDelete); MasterJob.getObjectContext().deleteObject(toDelete); 3) Rollback 4) re-Fetch MasterJobAux using the relationships MasterJob.getRelatedMasterJobAux(); I get TRANSIENT objects, you can look a the SQL log attached where there is some others details. Thanks. Laurent marchal. > Hi, > > Sorry, you posted this earlier and looks like nobody replied yet. > > So my question is : is this normal to get *TRANSIENT* objects from a > relationship after a rollback ? > > No, it is not normal. I just created a test case to reproduce it and > things seem to be working ok: > > PaintingInfo info = ctxt.newObject(PaintingInfo.class); > info.setTextReview("XXX"); p1.setToPaintingInfo(info); > > assertSame(info, p1.getToPaintingInfo()); ctxt.rollbackChanges(); > assertNull(p1.getToPaintingInfo()); > > Does it look like the scenario that you have, or am I missing something? > > Thanks, Andrus > > On Sep 15, 2008, at 12:22 PM, Laurent Marchal wrote: > > Hello again ! > > I have a strange thing happening in Cayenne 3.0M4 : I have two tables > ARTIST and ARTIST_AUX where extended artist's properties are stored. > > There is a relationship between ARTIST--->ARTIST_AUX where i checked > "To Dep PK" since no ARTIST_AUX rows can exists without corresponding > ARTIST. > > I have also a addPrefetch(ARTIST_AUX) when i retrieve ARTISTs. > > In my "artist editor" I create ARTIST_AUX rows at need and when an > error occurs i do a rollback(). The strange thing is that when i > refetch ARTISTS_AUX with the relationship, instead of getting only > existing ARTISTS_AUX, i get also the ARTISTS_AUX created before the > rollback() with the *TRANSIENT* state and no ObjectContext associated. > > So my question is : is this normal to get *TRANSIENT* objects from a > relationship after a rollback ? > > Thanks Laurent Marchal. > --------------080709070403050600090305 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit Hi Andrus,

I post on the mailing list with a new mail adress, because my provider sucks....
I will try to detail more what i do, so you can reproduce this in your test case. Maybe i'ts because you don't have prefetching or "to dep PK".

There is a relationship between MasterJob--->MasterJobAux where i checked "To Dep PK" since no ARTIST_AUX rows can exists without corresponding MasterJob.

When i fetch a MasterJob i have added a prefetch for MasterJobAux :

query.addPrefetch(MasterJob.RELATED_MASTER_JOB_AUX_PROPERTY);
Code I use to get/create/delete MasterJobAux
		protected MasterJobAux createAux(ILookupFieldCodes fieldCode, Short seqNo, String value) {
			MasterJobAux aux = MasterJob.this.getObjectContext().newObject(MasterJobAux.class);
			aux.setScheduleId(MasterJob.this.getScheduleId());
			aux.setJobName(MasterJob.this.getJobName());
			
			aux.setJaFieldCode((int) fieldCode.getID());
			aux.setJaSequenceNumber(seqNo);
			aux.setJavalue(value);
			aux.setRelatedMasterJob(MasterJob.this);

			return aux;
		}

		protected List<MasterJobAux> fetchAuxList() throws OpconException {
			return MasterJob.this.getRelatedMasterJobAux();
		}

		protected void deleteAux(MasterJobAux toDelete) throws OpconException {
			MasterJob.this.removeFromRelatedMasterJobAux(toDelete);
			MasterJob.this.getObjectContext().deleteObject(toDelete);
		}
Cayenne XML :
	<obj-entity name="MasterJob" className="com.sma.core.api.master.MasterJob" dbEntityName="JMASTER" superClassName="com.sma.core.api.DataAccessObject">
		<obj-attribute name="accessCodeId" type="java.lang.Short" db-attribute-path="ACCESSCDID"/>
		<obj-attribute name="altenateMachine1Id" type="java.lang.Short" db-attribute-path="ALTMACH1ID"/>
		<obj-attribute name="altenateMachine2Id" type="java.lang.Short" db-attribute-path="ALTMACH2ID"/>
		<obj-attribute name="altenateMachine3Id" type="java.lang.Short" db-attribute-path="ALTMACH3ID"/>
		<obj-attribute name="deptartmentId" type="java.lang.Short" db-attribute-path="DEPTID"/>
		<obj-attribute name="estimatedRuntime" type="java.lang.Integer" db-attribute-path="ESTRUNTIME"/>
		<obj-attribute name="jobGroupId" type="java.lang.Short" db-attribute-path="JOBGROUPID"/>
		<obj-attribute name="jobName" type="java.lang.String" db-attribute-path="JOBNAME"/>
		<obj-attribute name="jobTypeId" type="java.lang.Short" db-attribute-path="JOBTYPE"/>
		<obj-attribute name="machineGroupId" type="java.lang.Short" db-attribute-path="MACHGRPID"/>
		<obj-attribute name="primaryMachineId" type="java.lang.Short" db-attribute-path="PRIMMACHID"/>
		<obj-attribute name="scheduleId" type="java.lang.Integer" db-attribute-path="SKDID"/>
		<obj-attribute name="shortName" type="java.lang.String" db-attribute-path="SHORTNAME"/>
	</obj-entity>
	<obj-entity name="MasterJobAux" className="com.sma.core.api.auxs.MasterJobAux" dbEntityName="JMASTER_AUX" superClassName="com.sma.core.api.DataAccessObject">
		<obj-attribute name="jaFieldCode" type="java.lang.Integer" db-attribute-path="JAFC"/>
		<obj-attribute name="jaSequenceNumber" type="java.lang.Short" db-attribute-path="JASEQNO"/>
		<obj-attribute name="javalue" type="java.lang.String" db-attribute-path="JAVALUE"/>
		<obj-attribute name="jobName" type="java.lang.String" db-attribute-path="JOBNAME"/>
		<obj-attribute name="scheduleId" type="java.lang.Integer" db-attribute-path="SKDID"/>
	</obj-entity>


	<db-relationship name="toMasterJobAux" source="JMASTER" target="JMASTER_AUX" toDependentPK="true" toMany="true">
		<db-attribute-pair source="SKDID" target="SKDID"/>
		<db-attribute-pair source="JOBNAME" target="JOBNAME"/>
	</db-relationship>

	<obj-relationship name="relatedMasterJobAux" source="MasterJob" target="MasterJobAux" db-relationship-path="toMasterJobAux"/>


To reproduce the problem :
1) Fetch MasterJobAux  using the relationships
	MasterJob.getRelatedMasterJobAux();

2) delete/create some MasterJobAux
	MasterJob.removeFromRelatedMasterJobAux(toDelete);
	MasterJob.getObjectContext().deleteObject(toDelete);
3) Rollback

4) re-Fetch MasterJobAux  using the relationships
	MasterJob.getRelatedMasterJobAux();

I get TRANSIENT objects, you can look a the SQL log attached where there is some others details.


Thanks.

Laurent marchal.

Hi,

Sorry, you posted this earlier and looks like nobody replied yet.

So my question is : is this normal to get TRANSIENT objects from a relationship after a rollback ?

No, it is not normal. I just created a test case to reproduce it and things seem to be working ok:

PaintingInfo info = ctxt.newObject(PaintingInfo.class); info.setTextReview("XXX"); p1.setToPaintingInfo(info);

assertSame(info, p1.getToPaintingInfo()); ctxt.rollbackChanges(); assertNull(p1.getToPaintingInfo());

Does it look like the scenario that you have, or am I missing something?

Thanks, Andrus

On Sep 15, 2008, at 12:22 PM, Laurent Marchal wrote:

Hello again !

I have a strange thing happening in Cayenne 3.0M4 : I have two tables ARTIST and ARTIST_AUX where extended artist's properties are stored.

There is a relationship between ARTIST--->ARTIST_AUX where i checked "To Dep PK" since no ARTIST_AUX rows can exists without corresponding ARTIST.

I have also a addPrefetch(ARTIST_AUX) when i retrieve ARTISTs.

In my "artist editor" I create ARTIST_AUX rows at need and when an error occurs i do a rollback(). The strange thing is that when i refetch ARTISTS_AUX with the relationship, instead of getting only existing ARTISTS_AUX, i get also the ARTISTS_AUX created before the rollback() with the TRANSIENT state and no ObjectContext associated.

So my question is : is this normal to get TRANSIENT objects from a relationship after a rollback ?

--------------080709070403050600090305-- --------------080604070503060107030704 Content-Type: text/plain; name="SQL_trace_log.txt" Content-Transfer-Encoding: 8bit Content-Disposition: inline; filename="SQL_trace_log.txt" ### DISPLAY A MASTERJOB ### --- will run 2 queries. --- transaction started. SELECT t0.SHORTNAME, t0.ALTMACH3ID, t0.ESTRUNTIME, t0.SKDID, t0.ALTMACH2ID, t0.PRIMMACHID, t0.JOBTYPE, t0.MACHGRPID, t0.DEPTID, t0.JOBGROUPID, t0.ALTMACH1ID, t0.JOBNAME, t0.ACCESSCDID FROM dbo.JMASTER t0 WHERE (t0.SKDID = ?) AND (t0.JOBNAME = ?) [bind: 1->SKDID:5, 2->JOBNAME:'Backup de la base'] === returned 1 row. - took 3 ms. SELECT t0.SKDID, t0.JOBNAME, t0.JAVALUE, t0.JAFC, t0.JASEQNO FROM dbo.JMASTER_AUX t0 JOIN dbo.JMASTER t1 ON (t0.SKDID = t1.SKDID AND t0.JOBNAME = t1.JOBNAME) WHERE (t1.SKDID = ?) AND (t1.JOBNAME = ?) [bind: 1->SKDID:5, 2->JOBNAME:'Backup de la base'] === returned 12 rows. - took 3 ms. +++ transaction committed. ### SAVE A MASTER JOB ON A READ ONLY DB TO FORCE ERROR ### --- will run 1 query. --- transaction started. INSERT INTO dbo.JMASTER_AUX (JAFC, JASEQNO, JAVALUE, JOBNAME, SKDID) VALUES (?, ?, ?, ?, ?) [batch bind: 1->JAFC:3006, 2->JASEQNO:1, 3->JAVALUE:'AUX1', 4->JOBNAME:'Backup de la base', 5->SKDID:5] [batch bind: 1->JAFC:3007, 2->JASEQNO:1, 3->JAVALUE:'AUX2', 4->JOBNAME:'Backup de la base', 5->SKDID:5] *** error. !STACK 0 java.sql.BatchUpdateException: Échec de la mise à jour de la base de données "OPCONXPS4_PROD" car celle-ci est en lecture seule. at net.sourceforge.jtds.jdbc.JtdsStatement.executeBatch(JtdsStatement.java:944) at org.apache.cayenne.access.jdbc.BatchAction.runAsBatch(BatchAction.java:133) at org.apache.cayenne.access.jdbc.BatchAction.performAction(BatchAction.java:80) ### RESAVE THE MASTER JOB ### ERROR Transient OBJECT : {; transient; [relatedMasterJob=>{}; javalue=>AUX1; jaFieldCode=>3006; jaSequenceNumber=>1; scheduleId=>5; jobName=>Backup de la base]} ERROR Transient OBJECT : {; transient; [relatedMasterJob=>{}; javalue=>AUX2; jaFieldCode=>3007; jaSequenceNumber=>1; scheduleId=>5; jobName=>Backup de la base]} --- will run 1 query. --- transaction started. INSERT INTO dbo.JMASTER_AUX (JAFC, JASEQNO, JAVALUE, JOBNAME, SKDID) VALUES (?, ?, ?, ?, ?) [batch bind: 1->JAFC:3006, 2->JASEQNO:1, 3->JAVALUE:'AUX1', 4->JOBNAME:'Backup de la base', 5->SKDID:5] [batch bind: 1->JAFC:3007, 2->JASEQNO:1, 3->JAVALUE:'AUX2', 4->JOBNAME:'Backup de la base', 5->SKDID:5] *** error. !STACK 0 java.sql.BatchUpdateException: Échec de la mise à jour de la base de données "OPCONXPS4_PROD" car celle-ci est en lecture seule. at net.sourceforge.jtds.jdbc.JtdsStatement.executeBatch(JtdsStatement.java:944) at org.apache.cayenne.access.jdbc.BatchAction.runAsBatch(BatchAction.java:133) at org.apache.cayenne.access.jdbc.BatchAction.performAction(BatchAction.java:80) --------------080604070503060107030704--