Loading and Saving Data using Model Persistence

The purpose of this page is to help you become familiar with how iDempiere loads, modifies and saves data programmatically. In this tutorial, I am using iDempiere's "Create PO from Requisition" process as an example. You can execute this process from iDempiere's main menu when logged in as the GardenWorld Admin user.

General Common Examples

Here are persistence examples of common tasks from Create PO from Requisition:

MTable.get() Example

There is a newer/better way to load models; however, this technique is not widely adopted yet. Therefore, you will not see it as often. The biggest benefit of this technique is that it respects IModelFactory. Said another way, using this method allows users to inject their own model and any call using this method will pick up the new/appropriate class. Example:

MTable table = MTable.get(Env.getCtx(), m_Some_AD_Table);
PO po = table.getPO(id, null);

More practical example:

MDistributionRunLine drl = (MDistributionRunLine) MTable.get(getCtx(), MDistributionRunLine.Table_ID).getPO(record.getM_DistributionRunLine_ID(), get_TrxName());

To find more examples, right-click => References on MTable.getPO(...) method.

Every generated model has the X_... class. In it, it has getter methods that return an object instead of an ID. These methods give you an example of how to craft the statement. Here is an example:

public org.compiere.model.I_AD_Table getAD_Table() throws RuntimeException
{
return (org.compiere.model.I_AD_Table)MTable.get(getCtx(), org.compiere.model.I_AD_Table.Table_Name).getPO(getAD_Table_ID(), get_TrxName()); 
}

DB Example

Another important concept not demonstrated in the above process is using the DB class convenience methods. These methods help you use persistence best practices and simplify code at the same time. The MOrder class is full of examples:

One common question is "what does the Ex suffix at the end of DB.java methods mean?". Generally speaking, when you have two methods that are the same except where one ends in an Ex, the use the method with the Ex. These methods give you additional options for exception handling.

Transaction Management and Timeouts

When executing long-running processes, it is important to commit as often as it possible and appropriate. Try to avoid long-running, uncommitted processes.

Note the default timeout in iDempiere is 2 hours. Based on experience, the timeout is between commits. Said another way, if you are committing your transaction every could of minutes, your transaction can last for many hours

Here is an example of how you modify the transaction timeout:

Trx trx = Trx.get(get_TrxName(), false);
trx.setTimeout(60 * 60 * 5); //about 5 hour