Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/idempiere/idempiere/llms.txt

Use this file to discover all available pages before exploring further.

Overview

The PO (Persistent Object) class is the abstract base class for all persistent objects in iDempiere. It provides the foundation for database operations, value management, and the model-view-controller pattern implementation. Package: org.compiere.model Source: org.adempiere.base/src/org/compiere/model/PO.java Key Features:
  • CRUD operations (Create, Read, Update, Delete)
  • Value getters and setters with type safety
  • Transaction management
  • Validation hooks (beforeSave, afterSave, beforeDelete, afterDelete)
  • Context and tenant management
  • UUID and multi-key support

Constructors

Create New Record

public PO(Properties ctx)
ctx
Properties
Context containing session and environment variables

Load by ID

public PO(Properties ctx, int ID, String trxName)
ctx
Properties
Context
ID
int
The unique ID of the record (0 for new record)
trxName
String
Transaction name (null for auto-commit)

Load by UUID

public PO(Properties ctx, String UUID, String trxName)
ctx
Properties
Context
UUID
String
The unique UUID of the record (empty string "" for new record)
trxName
String
Transaction name

Load from ResultSet

public PO(Properties ctx, ResultSet rs, String trxName)
ctx
Properties
Context
rs
ResultSet
ResultSet positioned at current row to load
trxName
String
Transaction name

Value Management

Get Value by Column Name

public final Object get_Value(String columnName)
columnName
String
required
Name of the column
return
Object
Current value of the column, or null if not set
Example:
MOrder order = new MOrder(ctx, 1000000, trxName);
String docNo = (String) order.get_Value("DocumentNo");
Integer bpID = (Integer) order.get_Value("C_BPartner_ID");

Get Typed Values

public int get_ValueAsInt(String columnName)
public String get_ValueAsString(String columnName)
public boolean get_ValueAsBoolean(String columnName)
columnName
String
required
Name of the column
return
int | String | boolean
Value converted to the specified type
Example:
MOrder order = new MOrder(ctx, 1000000, trxName);
int bpID = order.get_ValueAsInt("C_BPartner_ID");
String docNo = order.get_ValueAsString("DocumentNo");
boolean isSOTrx = order.get_ValueAsBoolean("IsSOTrx");

Get Old Value

public final Object get_ValueOld(String columnName)
public int get_ValueOldAsInt(String columnName)
columnName
String
required
Name of the column
return
Object | int
Previous value before modification

Set Value

public final boolean set_Value(String columnName, Object value)
columnName
String
required
Name of the column
value
Object
required
Value to set (must match column type)
return
boolean
true if value was set successfully, false if column is read-only or virtual
Example:
MOrder order = new MOrder(ctx, 0, trxName); // new record
order.set_Value("C_BPartner_ID", 1000001);
order.set_Value("DateOrdered", new Timestamp(System.currentTimeMillis()));
order.set_Value("IsSOTrx", true);

Set Value Without Checks

public final boolean set_ValueNoCheck(String columnName, Object value)
columnName
String
required
Name of the column
value
Object
required
Value to set
return
boolean
true if successful
Use this method carefully - it bypasses standard validation and updateable checks. Primarily used for system fields like Created, CreatedBy, etc.

Save Operations

Save

public boolean save()
return
boolean
true if save was successful, false otherwise
Saves the record to the database. For new records, performs INSERT. For existing records, performs UPDATE only if values changed. Example:
MOrder order = new MOrder(ctx, 0, trxName);
order.setC_BPartner_ID(1000001);
order.setC_DocType_ID(1000000);
order.setDateOrdered(new Timestamp(System.currentTimeMillis()));

if (order.save()) {
    log.info("Order saved: " + order.getDocumentNo());
} else {
    log.severe("Failed to save order: " + CLogger.retrieveErrorString(""));
}

Save with Exception

public void saveEx() throws AdempiereException
throws
AdempiereException
Thrown if save fails
Same as save() but throws exception on failure instead of returning false. Example:
try {
    MOrder order = new MOrder(ctx, 0, trxName);
    order.setC_BPartner_ID(1000001);
    order.setC_DocType_ID(1000000);
    order.saveEx();
    log.info("Order saved successfully");
} catch (AdempiereException e) {
    log.severe("Save failed: " + e.getMessage());
    throw e;
}

Save with Transaction

public boolean save(String trxName)
public void saveEx(String trxName) throws AdempiereException
trxName
String
required
Transaction name to use for this save operation
return
boolean
true if save was successful (save() version only)

Delete Operations

Delete

public boolean delete(boolean force)
force
boolean
required
If true, delete even if record is processed
return
boolean
true if delete was successful, false otherwise
Example:
MOrder order = new MOrder(ctx, 1000000, trxName);
if (order.delete(false)) {
    log.info("Order deleted successfully");
} else {
    log.severe("Failed to delete: " + CLogger.retrieveErrorString(""));
}

Delete with Exception

public void deleteEx(boolean force) throws AdempiereException
public void deleteEx(boolean force, String trxName) throws AdempiereException
force
boolean
required
If true, delete even if record is processed
trxName
String
Transaction name (optional)
throws
AdempiereException
Thrown if delete fails

Validation Hooks

Before Save

protected boolean beforeSave(boolean newRecord)
newRecord
boolean
true if this is a new record being inserted
return
boolean
true to continue save, false to abort
Override this method to perform validation and business logic before saving. Example:
@Override
protected boolean beforeSave(boolean newRecord) {
    // Validate business partner
    if (getC_BPartner_ID() <= 0) {
        log.saveError("FillMandatory", Msg.getElement(getCtx(), "C_BPartner_ID"));
        return false;
    }
    
    // Set default values for new records
    if (newRecord) {
        if (getDateOrdered() == null)
            setDateOrdered(new Timestamp(System.currentTimeMillis()));
    }
    
    return true;
}

After Save

protected boolean afterSave(boolean newRecord, boolean success)
newRecord
boolean
true if this was a new record insertion
success
boolean
true if save operation succeeded
return
boolean
true to commit, false to rollback
Example:
@Override
protected boolean afterSave(boolean newRecord, boolean success) {
    if (!success)
        return false;
        
    // Create order lines for new order
    if (newRecord) {
        createDefaultLines();
    }
    
    // Update totals
    if (!newRecord && (is_ValueChanged("GrandTotal") || is_ValueChanged("C_Currency_ID"))) {
        updateBPartnerBalance();
    }
    
    return true;
}

Before Delete

protected boolean beforeDelete()
return
boolean
true to continue delete, false to abort
Example:
@Override
protected boolean beforeDelete() {
    // Check if order has shipments
    String sql = "SELECT COUNT(*) FROM M_InOut WHERE C_Order_ID=?";
    int count = DB.getSQLValue(get_TrxName(), sql, getC_Order_ID());
    if (count > 0) {
        log.saveError("Error", "Cannot delete order with shipments");
        return false;
    }
    return true;
}

After Delete

protected boolean afterDelete(boolean success)
success
boolean
true if delete succeeded
return
boolean
true to commit, false to rollback

State Methods

Check if New

public boolean is_new()
return
boolean
true if this is a new record not yet saved to database

Check if Changed

public boolean is_Changed()
public boolean is_ValueChanged(String columnName)
columnName
String
Column name to check
return
boolean
true if any value changed, or if specified column changed
Example:
if (order.is_ValueChanged("C_BPartner_ID")) {
    // Business partner changed, update pricing
    order.setPriceList();
}

Identity Methods

Get ID

public int get_ID()
return
int
The record ID, or 0 for new records

Get UUID

public String get_UUID()
return
String
The record UUID

Get Table Information

public String get_TableName()
public int get_Table_ID()
return
String | int
Table name or table ID

Context Methods

Get Context

public Properties getCtx()
return
Properties
Current context

Get Transaction

public String get_TrxName()
public void set_TrxName(String trxName)
trxName
String
Transaction name to set
return
String
Current transaction name

Client/Org Methods

Get Client and Org

public final int getAD_Client_ID()
public final int getAD_Org_ID()
return
int
Client ID or Organization ID

Get Access Level

protected abstract int get_AccessLevel()
return
int
Access level constant (ACCESSLEVEL_SYSTEM, ACCESSLEVEL_CLIENT, ACCESSLEVEL_ORG, etc.)
Access levels:
  • ACCESSLEVEL_SYSTEM = 4 - System data
  • ACCESSLEVEL_CLIENT = 2 - Client data
  • ACCESSLEVEL_ORG = 1 - Organization data
  • ACCESSLEVEL_ALL = 7 - System shared data
  • ACCESSLEVEL_SYSTEMCLIENT = 6 - System/Client data
  • ACCESSLEVEL_CLIENTORG = 3 - Client/Org data

Query Timeout

Set Query Timeout

public void set_QueryTimeout(int seconds)
public int get_QueryTimeout()
seconds
int
Query timeout in seconds (default: 300)
return
int
Current query timeout in seconds

Complete Example

import java.sql.Timestamp;
import java.util.Properties;
import org.compiere.model.MOrder;
import org.compiere.util.Env;
import org.compiere.util.CLogger;

public class OrderExample {
    
    public static void createOrder(Properties ctx, String trxName) {
        // Create new sales order
        MOrder order = new MOrder(ctx, 0, trxName);
        
        // Set mandatory fields
        order.setC_BPartner_ID(1000001);
        order.setC_DocType_ID(1000000);
        order.setDateOrdered(new Timestamp(System.currentTimeMillis()));
        order.setDatePromised(new Timestamp(System.currentTimeMillis()));
        order.setM_Warehouse_ID(Env.getContextAsInt(ctx, "#M_Warehouse_ID"));
        order.setIsSOTrx(true);
        
        // Save with exception handling
        try {
            order.saveEx();
            CLogger.getCLogger(OrderExample.class).info(
                "Created order: " + order.getDocumentNo() + 
                " (ID=" + order.get_ID() + ")"
            );
        } catch (Exception e) {
            CLogger.getCLogger(OrderExample.class).severe(
                "Failed to create order: " + e.getMessage()
            );
            throw e;
        }
    }
    
    public static void updateOrder(Properties ctx, int orderId, String trxName) {
        // Load existing order
        MOrder order = new MOrder(ctx, orderId, trxName);
        
        if (order.get_ID() == 0) {
            throw new IllegalArgumentException("Order not found: " + orderId);
        }
        
        // Update description
        String oldDesc = order.getDescription();
        order.setDescription("Updated: " + new Timestamp(System.currentTimeMillis()));
        
        // Save only if changed
        if (order.is_Changed()) {
            if (order.save()) {
                CLogger.getCLogger(OrderExample.class).info(
                    "Updated order " + order.getDocumentNo() +
                    " - Old desc: " + oldDesc +
                    ", New desc: " + order.getDescription()
                );
            }
        }
    }
}

See Also