You are viewing a plain text version of this content. The canonical link for it is here.
Posted to torque-user@db.apache.org by Mi...@bmwna.com on 2004/09/25 02:08:13 UTC

Torque BaseXXX in Transaction and the isNew() Method Check

Hi-

'm having a problem using Torque-generated classes within a transaction.

Let's say I have a table, Person, for which Person.java and BasePerson.java
are generated by Torque.  

When I attempt to save my person instance for the first time, Torque will do
an insert and then set the new attribtue to false on my Person instance.

    public void save(Connection con) throws TorqueException
    {
          if (!alreadyInSave)
        {
            alreadyInSave = true;


  
            // If this object has been modified, then save it to the
database.
            if (isModified())
            {
                if (isNew())
                {
                    PersonPeer.doInsert((Person) this, con);
                    setNew(false);
                }
                else
                {
                    PersonPeer.doUpdate((Person) this, con);
                }
            }

                      alreadyInSave = false;
        }
      }

Now, if I'm running in a transaction and the transaction rolls back due to
some application exception, once the user resolves the problem and attempts
to re-insert the Person instance, it will not be inserted.  Instead, because
isNew() now returns false, Torque will attempt to update the record.
However, this record does not exist in the database since the initial
transaction rolled back.

Has anyone come up with an elegant solution for this problem?

Thanks.

Michael


---------------------------------------------------------------------
To unsubscribe, e-mail: torque-user-unsubscribe@db.apache.org
For additional commands, e-mail: torque-user-help@db.apache.org


Re: Torque BaseXXX in Transaction and the isNew() Method Check

Posted by T E Schmitz <ma...@numerixtechnology.de>.
Hello Michael,

Michael.Kashambuzi@bmwna.com wrote:

> 'm having a problem using Torque-generated classes within a transaction.
> 
> Now, if I'm running in a transaction and the transaction rolls back due to
> some application exception, once the user resolves the problem and attempts
> to re-insert the Person instance, it will not be inserted.  Instead, because
> isNew() now returns false, Torque will attempt to update the record.
> However, this record does not exist in the database since the initial
> transaction rolled back.
> 
> Has anyone come up with an elegant solution for this problem?

I dealt with this problem in the following manner:

Between the Torque generated code and the UI I have a Business layer,
which. Operations on BusinessObjects are all transaction-based and in
some cases they are more complex than just one table insert update.
Therefore the need to be able to roll back the whole transaction exists.

The Business Layer is a set of interfaces, which is implemented by the
DB layer. For instance:

For a table PERSON, we have the Torque generated classes
Person/PersonPeer. For those, I have a wrapper each
TorquePerson/TorquePersonPeer. The latter act as a wrapper round the
Torque generated classes and implement the business layer interface.
(I refer to 'Person' as table object and 'TorquePerson' as business object.)

To solve the rollback problem, you need a shadow table object, which
contains the last committed state of the table object. In the above
example, TorquePerson contains the current and a committed version of
Person.

To create a shadow table object, you cannot use the generated copyInto()
methods as they only use the table object as a twemplate to create a new
similar table object.
Therefore I added the methods klone() and kloneInto() to the Velocity
template Object.vm. This creates a true copy (clone) of the table object.

After a successful commit the shadow table object is kloned from the
current table object using kloneInto(). I do this in a method called
confirm(). This is a method of my Confirmer interface, which all
BusinessObjects implement. This allows me to pass a List or Array of
Confirmers to Session.commit():

public static void commit (Connection connection,Confirmer[] confirmers)
{
     Transaction.commit (connection);
     loop: confirmers[i].confirm();
}

and in case of a rollback I do a reset() instead, which klones the
shadow table object over the current table object.

I hope my posting is not too garbled or more complex than what you were
looking for.


-- 


Regards/Gruß,

Tarlika Elisabeth Schmitz



---------------------------------------------------------------------
To unsubscribe, e-mail: torque-user-unsubscribe@db.apache.org
For additional commands, e-mail: torque-user-help@db.apache.org


Re: Torque BaseXXX in Transaction and the isNew() Method Check

Posted by Florian Fray <fl...@compuserve.de>.
Hmm, the attachment isn't there, so if you're interested i could send it
to you directly via, just send me a mail.

Florian Fray

----- Original Message ----- 
From: "Florian Fray" <fl...@compuserve.de>
To: "Apache Torque Users List" <to...@db.apache.org>
Sent: Saturday, September 25, 2004 11:06 AM
Subject: Re: Torque BaseXXX in Transaction and the isNew() Method Check


> I have had this problem some time ago, too.
> In my opinion, there is no simple solution. So I wrote some code
> to save those new-flags and manually rolled them back on an error.
> A solutian I've worked on is to change the Transaction-class by adding
> non-static methods for commit and rollback and two methods adding
> Jobs for post-commit and post-rollback processing. Finally there should
> be a save-method in the transaction, wich delegates to a save-method of
> a Base-Object and which adds a new-Flag-false-Job to the commit-job-chain.
> If commit is called, it should commit all changes and, if no exception is
> thrown,
> the commit-job-chain should be processed.
> I've made an implementation after reading your mail, cause my companies
code
> should not be contributed, as it contains too many specific changes. I'll
> append the code
> but it's not tested out now. It makes use of the fact that we are using
> BaseObjects which contain the save-Method (I think this is optional).
> Another way (my code doesn't exclude) is to add a save-Method which
> uses a Transaction-instance (this would be nice as the java.sql.Connection
> doesn't
> have to be used and won't appear in the app-code anymore).
>
> In the code you sent in, there is another error.
> The line "isAlreadyInSave = false" will never be executed if some
> exception is thrown. This could be easily fixed with a try ... finally
block
> in
> the template.
>
> Florian Fray


---------------------------------------------------------------------
To unsubscribe, e-mail: torque-user-unsubscribe@db.apache.org
For additional commands, e-mail: torque-user-help@db.apache.org


Re: Torque BaseXXX in Transaction and the isNew() Method Check

Posted by Florian Fray <fl...@compuserve.de>.
I have had this problem some time ago, too.
In my opinion, there is no simple solution. So I wrote some code
to save those new-flags and manually rolled them back on an error.
A solutian I've worked on is to change the Transaction-class by adding
non-static methods for commit and rollback and two methods adding
Jobs for post-commit and post-rollback processing. Finally there should
be a save-method in the transaction, wich delegates to a save-method of
a Base-Object and which adds a new-Flag-false-Job to the commit-job-chain.
If commit is called, it should commit all changes and, if no exception is
thrown,
the commit-job-chain should be processed.
I've made an implementation after reading your mail, cause my companies code
should not be contributed, as it contains too many specific changes. I'll
append the code
but it's not tested out now. It makes use of the fact that we are using
BaseObjects which contain the save-Method (I think this is optional).
Another way (my code doesn't exclude) is to add a save-Method which
uses a Transaction-instance (this would be nice as the java.sql.Connection
doesn't
have to be used and won't appear in the app-code anymore).

In the code you sent in, there is another error.
The line "isAlreadyInSave = false" will never be executed if some
exception is thrown. This could be easily fixed with a try ... finally block
in
the template.

Florian Fray

----- Original Message ----- 
From: <Mi...@bmwna.com>
To: <to...@db.apache.org>
Sent: Saturday, September 25, 2004 2:08 AM
Subject: Torque BaseXXX in Transaction and the isNew() Method Check


> Hi-
>
> 'm having a problem using Torque-generated classes within a transaction.
>
> Let's say I have a table, Person, for which Person.java and
BasePerson.java
> are generated by Torque.
>
> When I attempt to save my person instance for the first time, Torque will
do
> an insert and then set the new attribtue to false on my Person instance.
>
>     public void save(Connection con) throws TorqueException
>     {
>           if (!alreadyInSave)
>         {
>             alreadyInSave = true;
>
>
>
>             // If this object has been modified, then save it to the
> database.
>             if (isModified())
>             {
>                 if (isNew())
>                 {
>                     PersonPeer.doInsert((Person) this, con);
>                     setNew(false);
>                 }
>                 else
>                 {
>                     PersonPeer.doUpdate((Person) this, con);
>                 }
>             }
>
>                       alreadyInSave = false;
>         }
>       }
>
> Now, if I'm running in a transaction and the transaction rolls back due to
> some application exception, once the user resolves the problem and
attempts
> to re-insert the Person instance, it will not be inserted.  Instead,
because
> isNew() now returns false, Torque will attempt to update the record.
> However, this record does not exist in the database since the initial
> transaction rolled back.
>
> Has anyone come up with an elegant solution for this problem?
>
> Thanks.
>
> Michael
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: torque-user-unsubscribe@db.apache.org
> For additional commands, e-mail: torque-user-help@db.apache.org
>


Re: Torque BaseXXX in Transaction and the isNew() Method Check

Posted by T E Schmitz <ma...@numerixtechnology.de>.
Good morning Henning,

Henning P. Schmiedehausen wrote:
>>What exactly do you mean by "lastState" property?
>>Do you mean a shadow object that allows youto fall back to the last 
>>saved state?
> 
> 
> No, no, much easier. Basically.
> 
> <snip>
> so if you have to roll back a transaction, you can do
> myObject.setNew(myObject.isLastNew());
> 
> And restore the "new" state of the object before a transaction. If you
> want complete rollback, then you would need a shadow object, right. I
> consider this outside the scope of Torque. 

I agree. That is really application logic whether you want to return the 
last saved state or not. Come to think about it I am not so sure anymore 
whether it makes that much sense in my application even.

>>Correct me if I am wrong but I think there is another pitfall regarding 
>>the modified flag: in doUpdate(...) the modified flag is set to false 
>>unless an exception was thrown. But as there is no feedback whether the 
>>update was actually successful it is possible for the flag to be set 
>>without the update having been carried out. (The record might've been 
>>deleted in the meantime or modified such that the criteria didn't grab 
>>the record).

This really comes down to the lack of feedback from Village, which you 
explained to me before on the dev list. If you really need to know 
whether a record has been updated you have to implement this logic in 
the application because Torque, as it is now, cannot provide the 
information.

> Could be, yes. I've not ventured deep inside the Peer/Object logic,
> mainly because my stomach gets upset. ;-)

You must have a delicate stomach. I remember it got upset over BasePeer 
the other day. :-) (Take a look at the NullPointerException in BasePeer, 
TRQS228, and you might need a digestif.)

It takes a lot of concentration to modify the Object/Peer Velocity 
templates. The main problem is that the same Velocity code is repeated 
dozens of times to generate Java method and variable names. I don't know 
Velocity well enough to be able to judge whether, for instance, the use 
of macros could make the templates more readable.
I've made extensive changes and it took a lot of builds - not very fast 
with a growing number of tables :-(

-- 


Regards/Gruß,

Tarlika

---------------------------------------------------------------------
To unsubscribe, e-mail: torque-user-unsubscribe@db.apache.org
For additional commands, e-mail: torque-user-help@db.apache.org


Re: Torque BaseXXX in Transaction and the isNew() Method Check

Posted by "Henning P. Schmiedehausen" <hp...@intermeta.de>.
T E Schmitz <ma...@numerixtechnology.de> writes:

>Hallo Henning,

>Henning P. Schmiedehausen wrote:

>> Well, it might be a good idea to add a "lastState" property to the
>> generated peer classes...
>> 

>What exactly do you mean by "lastState" property?
>Do you mean a shadow object that allows youto fall back to the last 
>saved state?

No, no, much easier. Basically.

private boolean isNew = false;
private boolean lastNew = false;

public void setNew(boolean isNew)
{
	this.lastNew = this.isNew;
	this.isNew = isNew;
}

public boolean isNew()
{
	return isNew;
}

public boolean isLastNew()
{
	return lastNew;
}

so if you have to roll back a transaction, you can do

[...]
	myObject.setNew(myObject.isLastNew());
[...]

And restore the "new" state of the object before a transaction. If you
want complete rollback, then you would need a shadow object, right. I
consider this outside the scope of Torque. 

>Correct me if I am wrong but I think there is another pitfall regarding 
>the modified flag: in doUpdate(...) the modified flag is set to false 
>unless an exception was thrown. But as there is no feedback whether the 
>update was actually successful it is possible for the flag to be set 
>without the update having been carried out. (The record might've been 
>deleted in the meantime or modified such that the criteria didn't grab 
>the record).

Could be, yes. I've not ventured deep inside the Peer/Object logic,
mainly because my stomach gets upset. ;-)

	Regards
		Henning

-- 
Dipl.-Inf. (Univ.) Henning P. Schmiedehausen          INTERMETA GmbH
hps@intermeta.de        +49 9131 50 654 0   http://www.intermeta.de/

RedHat Certified Engineer -- Jakarta Turbine Development  -- hero for hire
   Linux, Java, perl, Solaris -- Consulting, Training, Development

"Fighting for one's political stand is an honorable action, but re-
 fusing to acknowledge that there might be weaknesses in one's
 position - in order to identify them so that they can be remedied -
 is a large enough problem with the Open Source movement that it
 deserves to be on this list of the top five problems."
                       -- Michelle Levesque, "Fundamental Issues with
                                    Open Source Software Development"

---------------------------------------------------------------------
To unsubscribe, e-mail: torque-user-unsubscribe@db.apache.org
For additional commands, e-mail: torque-user-help@db.apache.org


Re: Torque BaseXXX in Transaction and the isNew() Method Check

Posted by T E Schmitz <ma...@numerixtechnology.de>.
Hallo Henning,

Henning P. Schmiedehausen wrote:

> Well, it might be a good idea to add a "lastState" property to the
> generated peer classes...
> 

What exactly do you mean by "lastState" property?
Do you mean a shadow object that allows youto fall back to the last 
saved state?

Correct me if I am wrong but I think there is another pitfall regarding 
the modified flag: in doUpdate(...) the modified flag is set to false 
unless an exception was thrown. But as there is no feedback whether the 
update was actually successful it is possible for the flag to be set 
without the update having been carried out. (The record might've been 
deleted in the meantime or modified such that the criteria didn't grab 
the record).

-- 


Regards/Gruß,

Tarlika

---------------------------------------------------------------------
To unsubscribe, e-mail: torque-user-unsubscribe@db.apache.org
For additional commands, e-mail: torque-user-help@db.apache.org


Re: Torque BaseXXX in Transaction and the isNew() Method Check

Posted by "Henning P. Schmiedehausen" <hp...@intermeta.de>.
Michael.Kashambuzi@bmwna.com writes:

>Has anyone come up with an elegant solution for this problem?

If the rollback is not under Torque control but in your own code,
Torque does not know about this. So IMHO you must manually reset the
isNew flag.

Well, it might be a good idea to add a "lastState" property to the
generated peer classes...

	Regards
		Henning

-- 
Dipl.-Inf. (Univ.) Henning P. Schmiedehausen          INTERMETA GmbH
hps@intermeta.de        +49 9131 50 654 0   http://www.intermeta.de/

RedHat Certified Engineer -- Jakarta Turbine Development  -- hero for hire
   Linux, Java, perl, Solaris -- Consulting, Training, Development

"Fighting for one's political stand is an honorable action, but re-
 fusing to acknowledge that there might be weaknesses in one's
 position - in order to identify them so that they can be remedied -
 is a large enough problem with the Open Source movement that it
 deserves to be on this list of the top five problems."
                       -- Michelle Levesque, "Fundamental Issues with
                                    Open Source Software Development"

---------------------------------------------------------------------
To unsubscribe, e-mail: torque-user-unsubscribe@db.apache.org
For additional commands, e-mail: torque-user-help@db.apache.org