This is an automated email from the ASF dual-hosted git repository.

doebele pushed a commit to branch version3
in repository https://gitbox.apache.org/repos/asf/empire-db.git


The following commit(s) were added to refs/heads/version3 by this push:
     new 8163ec7  EMPIREDB-368 fix
8163ec7 is described below

commit 8163ec79fc865695d67345061d8cb2d974d7202c
Author: Rainer Döbele <[email protected]>
AuthorDate: Tue Feb 1 12:30:29 2022 +0100

    EMPIREDB-368 fix
---
 .../org/apache/empire/samples/db/SampleApp.java    |   7 +-
 .../apache/empire/samples/db/beans/Employee.java   |  38 +++---
 .../main/java/org/apache/empire/data/Record.java   |   9 ++
 .../org/apache/empire/data/bean/BeanResult.java    | 130 ++++++++++++++-------
 .../main/java/org/apache/empire/db/DBReader.java   |  15 ++-
 .../main/java/org/apache/empire/db/DBRowSet.java   |  13 ++-
 .../main/java/org/apache/empire/db/DBUtils.java    |  33 +++---
 7 files changed, 154 insertions(+), 91 deletions(-)

diff --git 
a/empire-db-examples/empire-db-example-basic/src/main/java/org/apache/empire/samples/db/SampleApp.java
 
b/empire-db-examples/empire-db-example-basic/src/main/java/org/apache/empire/samples/db/SampleApp.java
index 469ba31..31a89b1 100644
--- 
a/empire-db-examples/empire-db-example-basic/src/main/java/org/apache/empire/samples/db/SampleApp.java
+++ 
b/empire-db-examples/empire-db-example-basic/src/main/java/org/apache/empire/samples/db/SampleApp.java
@@ -715,6 +715,7 @@ public class SampleApp
        {
            SampleDB.Employees EMP = db.EMPLOYEES;
            
+           /*
            DBCommand cmd = db.createCommand();
            cmd.where(EMP.GENDER.is(Gender.M));
            cmd.orderBy(EMP.LASTNAME.desc());
@@ -729,9 +730,10 @@ public class SampleApp
            Department department = 
context.getUtils().queryBean(Department.class, db.DEPARTMENTS.NAME.is("Sales"));
            Payment first = 
department.getEmployees().get(0).getPayments().get(0);
            log.info("First payment amount is {}", first.getAmount());
+           */
 
-           // Query all males
-           BeanResult<Employee> result = new 
BeanResult<Employee>(Employee.class, EMP);
+        // Query all males
+           BeanResult<Employee> result = new 
BeanResult<Employee>(Employee.class);
         result.getCommand().where(EMP.GENDER.is(Gender.M));
            result.fetch(context);
            
@@ -742,7 +744,6 @@ public class SampleApp
            result.fetch(context);
            
         log.info("Number of female employees is: "+result.size());
-        */
        }
        
        private static void queryDataList()
diff --git 
a/empire-db-examples/empire-db-example-basic/src/main/java/org/apache/empire/samples/db/beans/Employee.java
 
b/empire-db-examples/empire-db-example-basic/src/main/java/org/apache/empire/samples/db/beans/Employee.java
index 2df7e43..bf44085 100644
--- 
a/empire-db-examples/empire-db-example-basic/src/main/java/org/apache/empire/samples/db/beans/Employee.java
+++ 
b/empire-db-examples/empire-db-example-basic/src/main/java/org/apache/empire/samples/db/beans/Employee.java
@@ -27,7 +27,6 @@ import java.util.Locale;
 import org.apache.empire.commons.DateUtils;
 import org.apache.empire.db.DBCommand;
 import org.apache.empire.db.DBContext;
-import org.apache.empire.db.DBRecord;
 import org.apache.empire.db.list.Bean;
 import org.apache.empire.samples.db.SampleDB;
 
@@ -38,7 +37,6 @@ import org.apache.empire.samples.db.SampleDB;
  */
 public class Employee implements Bean<SampleDB>
 {
-    private int    rownum;      // rownum
     private long   id;          // "ID" 
     private String firstname;   // "FIRSTNAME"
     private String lastname;    // "LASTNAME"
@@ -52,9 +50,10 @@ public class Employee implements Bean<SampleDB>
     private Department department;
     private List<Payment> payments;
     
+    int rownum;
+    
     /**
-     * Creates a new Employee entity bean
-     * @param rownum
+     * Constructor using all fields from the table EMPLOYEES
      * @param id
      * @param firstname
      * @param lastname
@@ -65,10 +64,9 @@ public class Employee implements Bean<SampleDB>
      * @param salary
      * @param retired
      */
-    public Employee(int rownum, int id, String firstname, String lastname, 
Date dateOfBirth, int departmentId, String gender, String phoneNumber,
+    public Employee(int id, String firstname, String lastname, Date 
dateOfBirth, int departmentId, String gender, String phoneNumber,
                     BigDecimal salary, boolean retired, Timestamp timestamp)
     {
-        this.rownum = rownum;   
         this.id = id;
         this.firstname = firstname;
         this.lastname = lastname;
@@ -80,26 +78,18 @@ public class Employee implements Bean<SampleDB>
         this.retired = retired;
     }
 
+    /**
+     * Constructor using fields but without timestamp 
+     */
     public Employee(int id, String firstname, String lastname, Date 
dateOfBirth, int departmentId, String gender, String phoneNumber,
-                    BigDecimal salary, boolean retired, Timestamp timestamp)
-    {
-        this.rownum = -1;   
-        this.id = id;
-        this.firstname = firstname;
-        this.lastname = lastname;
-        this.dateOfBirth = dateOfBirth;
-        this.departmentId = departmentId;
-        this.gender = gender;
-        this.phoneNumber = phoneNumber;
-        this.salary = salary;
-        this.retired = retired;
-    }
-    
-    public Employee(int rownum)
+                    BigDecimal salary, boolean retired)
     {
-        this.rownum = rownum; 
+        this(id, firstname, lastname, dateOfBirth, departmentId, gender, 
phoneNumber, salary, retired, null);
     }
     
+    /**
+     * Standard Constructor 
+     */
     public Employee()
     {
         // Standard constructor 
@@ -230,10 +220,12 @@ public class Employee implements Bean<SampleDB>
     @Override
     public void onBeanLoaded(SampleDB db, DBContext context, int rownum, 
Object parent)
     {
+        this.rownum = rownum;
+        
         if (parent instanceof Department)
             department = ((Department)parent); 
         // don't!
-        else department = context.getUtils().queryBean(Department.class, 
db.DEPARTMENTS, DBRecord.key(this.departmentId));
+        // else department = context.getUtils().queryBean(Department.class, 
DBRecord.key(this.departmentId));
         
         DBCommand cmd = db.createCommand();
         cmd.where(db.PAYMENTS.EMPLOYEE_ID.is(this.id));
diff --git a/empire-db/src/main/java/org/apache/empire/data/Record.java 
b/empire-db/src/main/java/org/apache/empire/data/Record.java
index 196cdf1..a976318 100644
--- a/empire-db/src/main/java/org/apache/empire/data/Record.java
+++ b/empire-db/src/main/java/org/apache/empire/data/Record.java
@@ -34,6 +34,15 @@ import org.apache.empire.commons.Options;
  */
 public interface Record extends RecordData
 {
+    /**
+     * varArgs to Array
+     * @param parts
+     * @return
+     */
+    public static Object[] key(Object... parts)
+    {
+        return parts;
+    }
 
     /**
      * returns true if the record is valid.
diff --git 
a/empire-db/src/main/java/org/apache/empire/data/bean/BeanResult.java 
b/empire-db/src/main/java/org/apache/empire/data/bean/BeanResult.java
index 519187a..0b3d429 100644
--- a/empire-db/src/main/java/org/apache/empire/data/bean/BeanResult.java
+++ b/empire-db/src/main/java/org/apache/empire/data/bean/BeanResult.java
@@ -26,10 +26,11 @@ import org.apache.empire.db.DBColumn;
 import org.apache.empire.db.DBCommand;
 import org.apache.empire.db.DBContext;
 import org.apache.empire.db.DBDatabase;
+import org.apache.empire.db.DBObject;
 import org.apache.empire.db.DBReader;
 import org.apache.empire.db.DBRowSet;
+import org.apache.empire.db.exceptions.CommandWithoutSelectException;
 import org.apache.empire.exceptions.BeanIncompatibleException;
-import org.apache.empire.exceptions.InvalidArgumentException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -50,80 +51,78 @@ public class BeanResult<T> extends ArrayList<T>
     private static final Logger log = 
LoggerFactory.getLogger(BeanResult.class);
 
     private DBCommand cmd;
-    private Class<T> clazz;
+    private Class<T> beanType;
 
     /**
      * Create a bean result from a command object.
      * No checks will be performed here whether the command is compatible with 
the supplied class.
-     * @param clazz
+     * @param beanType
      * @param cmd
      */
-    public BeanResult(Class<T> clazz, DBCommand cmd)
+    public BeanResult(Class<T> beanType, DBCommand cmd)
     {
-        this.clazz = clazz;
+        DBObject.checkParamNull("beanType", beanType);
+        DBObject.checkParamNull("cmd", cmd);
+        this.beanType = beanType;
         this.cmd = cmd;
-        // Invalid Argument
-        if (cmd==null || cmd.hasSelectExpr())
-            throw new InvalidArgumentException("cmd", cmd);
     }
     
     /**
      * Creates a bean result for a Table, View or Query from the supplied 
columns.
      * At least one column must match the given getters / setters on the 
supplied class otherwise an BeanIncompatibleException will be thrown.
-     * @param clazz the of T
+     * @param beanType the of T
      * @param rowset the rowset 
      */
-    public BeanResult(Class<T> clazz, DBRowSet rowset)
+    public BeanResult(Class<T> beanType, DBRowSet rowset)
     {
-        this.clazz = clazz;
+        DBObject.checkParamNull("beanType", beanType);
+        DBObject.checkParamNull("rowset", rowset);
+        this.beanType = beanType;
         // Create the command
         DBDatabase db = rowset.getDatabase();
         cmd = db.createCommand();
-        // Select all accessible columns
-        int count = 0;
-        Method[] methods = clazz.getMethods();
-        for (DBColumn col : rowset.getColumns())
-        {   // obtain the bean property Name
-            String property = col.getBeanPropertyName();
-            if (!isPropertyAcessible(methods, property, col.getDataType())) {
-                // Property not found
-                log.debug("Unable to access the property {} on {}. Column will 
be ignored.", property, clazz.getName());
-                continue;
-            }
-            // Select
-            cmd.select(col);
-            count++;
-        }    
-        // Check
-        if (count==0)
-            throw new BeanIncompatibleException(clazz, rowset);
+        autoSelectColumns(rowset);
     }
-
-    protected boolean isPropertyAcessible(Method[] methods, String property, 
DataType dataType)
+    
+    /**
+     * Creates a bean result for a Table, View or Query from the supplied 
columns.
+     * A rowset must be registered for this beanType @see 
DBRowSet.getRowsetforType()
+     * At least one column must match the given getters / setters on the 
supplied class otherwise an BeanIncompatibleException will be thrown.
+     * @param beanType the of T
+     */
+    public BeanResult(Class<T> beanType)
     {
-        property = 
"et"+property.substring(0,1).toUpperCase()+property.substring(1);
-        for (int i=0; i<methods.length; i++)
-        {   // Find a matching getter or setter method
-            String name = methods[i].getName();
-            if (name.endsWith(property))
-                return true;
-        }
-        return false;
+        this(beanType, DBRowSet.getRowsetforType(beanType, true));
     }
     
+    /**
+     * Returns the current command 
+     * Used to add constraints, order, grouping etc.
+     * @return the command
+     */
     public DBCommand getCommand()
     {
         return cmd;
     }
     
+    /**
+     * Executes the query and fetches the result
+     * @param context
+     * @param maxItems the maximum number of items to query
+     * @return the number of items fetched by the query
+     */
     public int fetch(DBContext context, int maxItems)
     {
+        // Check command
+        if (!cmd.hasSelectExpr())
+            throw new CommandWithoutSelectException(cmd); 
+        // OK, fetch now
         clear();
         DBReader reader = new DBReader(context);
         try {
             // Open and Read
             reader.open(cmd);
-            reader.getBeanList(this, clazz, maxItems);
+            reader.getBeanList(this, beanType, maxItems);
             return size();
             
         } finally {
@@ -131,9 +130,60 @@ public class BeanResult<T> extends ArrayList<T>
         }
     }
 
+    /**
+     * Executes the query and fetches the result
+     * @param context
+     * @return the number of items fetched by the query
+     */
     public final int fetch(DBContext context)
     {
         return fetch(context, -1);
     }
     
+    /**
+     * Selects all columns for a given rowset
+     * @param rowset
+     */
+    protected void autoSelectColumns(DBRowSet rowset)
+    {
+        // Select all accessible columns
+        int count = 0;
+        Method[] methods = beanType.getMethods();
+        for (DBColumn col : rowset.getColumns())
+        {   // obtain the bean property Name
+            String property = col.getBeanPropertyName();
+            if (!isPropertyAcessible(methods, property, col.getDataType())) {
+                // Property not found
+                log.info("Unable to access the property {} on {}. Column will 
be ignored.", property, beanType.getName());
+                continue;
+            }
+            // Select
+            cmd.select(col);
+            count++;
+        }    
+        log.debug("{} columns have been selected for beanType {}", count, 
beanType.getName());
+        // Check
+        if (count==0)
+            throw new BeanIncompatibleException(beanType, rowset);
+    }
+
+    /**
+     * Checks if the property is accessible i.e. has a getter method on the 
beanType
+     * @param methods the beanType methods
+     * @param propety the property to check
+     * @param dataType the dataType
+     */
+    protected boolean isPropertyAcessible(Method[] methods, String property, 
DataType dataType)
+    {
+        String prefix = (dataType.isBoolean() ? "is" : "et");
+        String getter = 
prefix+property.substring(0,1).toUpperCase()+property.substring(1);
+        for (int i=0; i<methods.length; i++)
+        {   // Find a matching getter or setter method
+            String name = methods[i].getName();
+            if (name.endsWith(getter))
+                return true;
+        }
+        return false;
+    }
+    
 }
diff --git a/empire-db/src/main/java/org/apache/empire/db/DBReader.java 
b/empire-db/src/main/java/org/apache/empire/db/DBReader.java
index 4f6875e..7fa315f 100644
--- a/empire-db/src/main/java/org/apache/empire/db/DBReader.java
+++ b/empire-db/src/main/java/org/apache/empire/db/DBReader.java
@@ -39,6 +39,7 @@ import org.apache.empire.data.DataType;
 import org.apache.empire.db.exceptions.EmpireSQLException;
 import org.apache.empire.db.exceptions.QueryNoResultException;
 import org.apache.empire.db.expr.join.DBJoinExpr;
+import org.apache.empire.db.list.Bean;
 import org.apache.empire.exceptions.BeanInstantiationException;
 import org.apache.empire.exceptions.InvalidArgumentException;
 import org.apache.empire.exceptions.ObjectNotValidException;
@@ -686,20 +687,24 @@ public class DBReader extends DBRecordData implements 
Closeable
             
             // Create a list of beans
             while (moveNext() && maxCount != 0)
-            { // Create bean an init
+            {   // Create bean an init
+                T bean;
                 if (ctor!=null)
                 {   // Use Constructor
                     for (int i = 0; i < getFieldCount(); i++)
                         args[i] = ObjectUtils.convert(ctorParamTypes[i], 
getValue(i));
-                    T bean = (T)ctor.newInstance(args);
-                    c.add(bean);
+                    bean = (T)ctor.newInstance(args);
                 }
                 else
                 {   // Use Property Setters
-                    T bean = t.newInstance();
+                    bean = t.newInstance();
                     setBeanProperties(bean);
-                    c.add(bean);
                 }
+                // add
+                c.add(bean);
+                // post processing
+                if (bean instanceof Bean<?>)
+                    ((Bean<?>)bean).onBeanLoaded(getDatabase(), context, 
c.size(), null);
                 // Decrease count
                 if (maxCount > 0)
                     maxCount--;
diff --git a/empire-db/src/main/java/org/apache/empire/db/DBRowSet.java 
b/empire-db/src/main/java/org/apache/empire/db/DBRowSet.java
index cc562d9..fa54020 100644
--- a/empire-db/src/main/java/org/apache/empire/db/DBRowSet.java
+++ b/empire-db/src/main/java/org/apache/empire/db/DBRowSet.java
@@ -27,6 +27,7 @@ import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
 
 import org.apache.empire.commons.ObjectUtils;
 import org.apache.empire.commons.StringUtils;
@@ -44,6 +45,7 @@ import org.apache.empire.db.exceptions.QueryNoResultException;
 import org.apache.empire.db.exceptions.RecordNotFoundException;
 import org.apache.empire.db.exceptions.RecordUpdateFailedException;
 import org.apache.empire.db.exceptions.RecordUpdateInvalidException;
+import org.apache.empire.db.exceptions.UnknownBeanTypeException;
 import org.apache.empire.db.expr.column.DBCountExpr;
 import org.apache.empire.db.expr.compare.DBCompareExpr;
 import org.apache.empire.db.list.DBBeanListFactory;
@@ -101,16 +103,19 @@ public abstract class DBRowSet extends DBExpr implements 
Entity
     // Logger
     protected static final Logger                log         = 
LoggerFactory.getLogger(DBRowSet.class);
 
-    private static final Map<Class<?>, DBRowSet> beanTypeMap = new 
HashMap<Class<?>, DBRowSet>(); /* ConcurrentHashMap ? */
+    private static final Map<Class<?>, DBRowSet> beanTypeMap = new 
ConcurrentHashMap<Class<?>, DBRowSet>();
    
     /**
      * Returns the DBRowSet instance assigned to a particular Java bean type
      * @param beanType the Java bean type
      * @return return the DBRowSet assigned to this type 
      */
-    public static synchronized DBRowSet getRowsetforType(Class<?> beanType)
-    {   
-        return beanTypeMap.get(beanType);
+    public static synchronized DBRowSet getRowsetforType(Class<?> beanType, 
boolean checkExists)
+    {
+        DBRowSet rowset = beanTypeMap.get(beanType); 
+        if (rowset==null && checkExists)
+            throw new UnknownBeanTypeException(beanType);
+        return rowset;
     }
 
     /**
diff --git a/empire-db/src/main/java/org/apache/empire/db/DBUtils.java 
b/empire-db/src/main/java/org/apache/empire/db/DBUtils.java
index 709d1c5..7b39736 100644
--- a/empire-db/src/main/java/org/apache/empire/db/DBUtils.java
+++ b/empire-db/src/main/java/org/apache/empire/db/DBUtils.java
@@ -16,12 +16,11 @@ import org.apache.empire.data.list.DataListFactory;
 import org.apache.empire.data.list.DataListFactoryImpl;
 import org.apache.empire.data.list.DataListHead;
 import org.apache.empire.db.context.DBContextAware;
-import org.apache.empire.db.exceptions.ConstraintViolationException;
 import org.apache.empire.db.exceptions.CommandWithoutSelectException;
+import org.apache.empire.db.exceptions.ConstraintViolationException;
 import org.apache.empire.db.exceptions.QueryFailedException;
 import org.apache.empire.db.exceptions.QueryNoResultException;
 import org.apache.empire.db.exceptions.StatementFailedException;
-import org.apache.empire.db.exceptions.UnknownBeanTypeException;
 import org.apache.empire.db.expr.compare.DBCompareExpr;
 import org.apache.empire.db.list.Bean;
 import org.apache.empire.db.list.DBBeanListFactory;
@@ -727,11 +726,12 @@ public class DBUtils implements DBContextAware
             int rownum = 0;
             while (r.moveNext() && maxCount != 0)
             {   // Create bean an init
-                T entry = factory.newEntry(++rownum, r);
+                T entry = factory.newEntry(rownum, r);
                 if (entry==null)
                     continue;
                 // add entry
                 list.add(entry);
+                rownum++;
                 // Decrease count
                 if (maxCount > 0)
                     maxCount--;
@@ -865,12 +865,15 @@ public class DBUtils implements DBContextAware
             int rownum = 0;
             while (r.moveNext() && maxCount != 0)
             {   // Create bean an init
-                T entry = factory.newRecord(++rownum, r);
+                T entry = factory.newRecord(rownum, r);
                 if (entry==null)
                     continue;
-                // add entry
+                // check
                 if (entry.isValid())
+                {   // add entry
                     list.add(entry);
+                    rownum++;
+                }
                 else
                     log.warn("Record {} is not valid thus it will not be added 
to the RecordListQuery.", rownum);
                 // Decrease count
@@ -979,14 +982,16 @@ public class DBUtils implements DBContextAware
             int rownum = 0;
             while (r.moveNext() && maxCount != 0)
             {   // Create bean an init
-                T item = factory.newItem(++rownum, r);
+                T item = factory.newItem(rownum, r);
                 if (item==null)
                     continue;
+                // add entry
+                list.add(item);
                 // post processing
                 if (item instanceof Bean<?>)
                     ((Bean<?>)item).onBeanLoaded(r.getDatabase(), context, 
rownum, parent);
-                // add entry
-                list.add(item);
+                // next
+                rownum++;
                 // Decrease count
                 if (maxCount > 0)
                     maxCount--;
@@ -1055,7 +1060,7 @@ public class DBUtils implements DBContextAware
      */
     public <T> List<T> queryBeanList(DBCommand cmd, Class<T> beanType, Object 
parent)
     {
-        DBRowSet rowset = DBRowSet.getRowsetforType(beanType);
+        DBRowSet rowset = DBRowSet.getRowsetforType(beanType, false);
         if (rowset!=null)
             return queryBeanList(cmd, getRowsetBeanListFactory(beanType, 
rowset), parent);
         else
@@ -1115,7 +1120,7 @@ public class DBUtils implements DBContextAware
      */
     public <T> T queryBean(DBCommand cmd, Class<T> beanType)
     {
-        DBRowSet rowset = DBRowSet.getRowsetforType(beanType);
+        DBRowSet rowset = DBRowSet.getRowsetforType(beanType, false);
         if (rowset!=null)
             return queryBean(cmd, getRowsetBeanListFactory(beanType, rowset));
         else
@@ -1149,9 +1154,7 @@ public class DBUtils implements DBContextAware
      */
     public final <T> T queryBean(Class<T> beanType, DBCompareExpr 
whereConstraints)
     {
-        DBRowSet rowset = DBRowSet.getRowsetforType(beanType);
-        if (rowset==null)
-            throw new UnknownBeanTypeException(beanType);
+        DBRowSet rowset = DBRowSet.getRowsetforType(beanType, true);
         return queryBean(beanType, rowset, whereConstraints);
     }
     
@@ -1181,9 +1184,7 @@ public class DBUtils implements DBContextAware
      */
     public final <T> T queryBean(Class<T> beanType, Object[] key)
     {
-        DBRowSet rowset = DBRowSet.getRowsetforType(beanType);
-        if (rowset==null)
-            throw new UnknownBeanTypeException(beanType);
+        DBRowSet rowset = DBRowSet.getRowsetforType(beanType, true);
         return queryBean(beanType, rowset, key);
     }
     

Reply via email to