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 55ec62b  EMPIREDB-368 DBBeanFactoryCache
55ec62b is described below

commit 55ec62b7fd04fa6c61072013d25d26db11c70543
Author: Rainer Döbele <[email protected]>
AuthorDate: Thu Feb 3 23:29:34 2022 +0100

    EMPIREDB-368 DBBeanFactoryCache
---
 .../org/apache/empire/data/bean/BeanResult.java    |  5 +-
 .../main/java/org/apache/empire/db/DBRowSet.java   | 49 ++++---------
 .../main/java/org/apache/empire/db/DBUtils.java    | 70 ++++++++++--------
 .../apache/empire/db/list/DBBeanFactoryCache.java  | 83 ++++++++++++++++++++++
 4 files changed, 143 insertions(+), 64 deletions(-)

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 addb372..46d2743 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
@@ -89,11 +89,14 @@ public class BeanResult<T> extends ArrayList<T>
      * 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
-     */
+     * 
+     * Need to implement a BeanRowsetMap for this. @see DBRowSet
+     * 
     public BeanResult(Class<T> beanType)
     {
         this(beanType, DBRowSet.getRowsetforType(beanType, true));
     }
+     */
     
     /**
      * Returns the current command 
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 60407a1..53e3aca 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,7 +27,6 @@ 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;
@@ -45,9 +44,9 @@ 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.DBBeanFactoryCache;
 import org.apache.empire.db.list.DBBeanListFactory;
 import org.apache.empire.db.list.DBBeanListFactoryImpl;
 import org.apache.empire.dbms.DBMSFeature;
@@ -103,51 +102,43 @@ 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 
ConcurrentHashMap<Class<?>, DBRowSet>();
+    /*
+     * Do we need a BeanRowsetMap?
+     * 
+    private static final Map<Class<?>, DBRowSet> beanRowsetMap = new 
HashMap<Class<?>, DBRowSet>(); // Concurrent ?
    
-    /**
-     * 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, 
boolean checkExists)
     {
-        DBRowSet rowset = beanTypeMap.get(beanType); 
+        DBRowSet rowset = beanRowsetMap.get(beanType); 
         if (rowset==null && checkExists)
             throw new UnknownBeanTypeException(beanType);
         return rowset;
     }
 
-    /**
-     * sets the DBRowSet instance assigned to a particular Java bean type
-     * @param beanType the Java bean type
-     */
     public static synchronized void setRowsetForType(Class<?> beanType, 
DBRowSet rowset)
     {
         if (rowset!=null)
         {   // Check previous
-            DBRowSet prev = beanTypeMap.get(beanType);
+            DBRowSet prev = beanRowsetMap.get(beanType);
             if (prev!=null && prev!=rowset)
                 log.warn("The Java bean type '{}' has already been assigned to 
a different DBRowSet {}. Assiging now to {}", beanType.getName(), 
prev.getName(), rowset.getName());
             // Assign now
-            beanTypeMap.put(beanType, rowset);
+            beanRowsetMap.put(beanType, rowset);
         }
         else
-            beanTypeMap.remove(beanType);
+            beanRowsetMap.remove(beanType);
     }
-    
+     */
     
     // Members
     protected final DBDatabase         db;     /* transient ? */
     protected String                   comment          = null;
     protected DBColumn                 timestampColumn  = null;
     protected Map<DBColumn, DBColumn>  columnReferences = null;
+    protected List<DBColumn>           columns          = new 
ArrayList<DBColumn>();
 
+    // associated Entity Bean Class (optional)
     protected Class<?>                 beanType         = null;
-    protected DBBeanListFactory<?>     beanFactory      = null;
-
-    // The column List
-    protected List<DBColumn>           columns          = new 
ArrayList<DBColumn>();
 
     /**
      * Internally used for parameter checking
@@ -315,15 +306,6 @@ public abstract class DBRowSet extends DBExpr implements 
Entity
     {
         return beanType;
     }
- 
-    /**
-     * returns the bean factory for this rowset
-     * @return the bean factory
-     */
-    public DBBeanListFactory<?> getBeanFactory()
-    {
-        return beanFactory;
-    }
     
     /**
      * sets the bean type for this rowset
@@ -340,14 +322,13 @@ public abstract class DBRowSet extends DBExpr implements 
Entity
      */
     public <T> void setBeanType(Class<T> beanType, DBBeanListFactory<T> 
factory)
     {
+        // set
+        this.beanType = beanType;
         // create default factory if not provided
         if (factory==null)
             factory = new DBBeanListFactoryImpl<T>(beanType, getKeyColumns(), 
getColumns());
-        // set
-        this.beanType = beanType;
-        this.beanFactory = factory;
         // set to global map
-        setRowsetForType(beanType, this);
+        DBBeanFactoryCache.setFactoryForType(beanType, factory);
     }
 
     /**
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 067b756..2b074d1 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
@@ -17,12 +17,14 @@ 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.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.expr.compare.DBCompareExpr;
 import org.apache.empire.db.list.Bean;
+import org.apache.empire.db.list.DBBeanFactoryCache;
 import org.apache.empire.db.list.DBBeanListFactory;
 import org.apache.empire.db.list.DBBeanListFactoryImpl;
 import org.apache.empire.db.list.DBRecordListFactory;
@@ -928,12 +930,36 @@ public class DBUtils implements DBContextAware
      * @param rowset the rowset for which to return the factory 
      * @return the bean factory
      */
-    protected <T> DBBeanListFactory<T> getRowsetBeanListFactory(Class<T> 
beanType, DBRowSet rowset) 
+    protected synchronized <T> DBBeanListFactory<T> 
getRowsetBeanListFactory(Class<T> beanType, DBRowSet rowset) 
     {
-        @SuppressWarnings("unchecked")
-        DBBeanListFactory<T> factory = 
(DBBeanListFactory<T>)rowset.getBeanFactory();
+        DBBeanListFactory<T> factory = 
DBBeanFactoryCache.getFactoryForType(beanType, false);
         if (factory==null)
-            factory =createDefaultBeanListFactory(beanType, 
rowset.getKeyColumns(), rowset.getColumns());
+        {   // Create default factory
+            log.info("No factory found for bean type '{}' and rowset {}. 
Creating default", beanType.getName(), rowset.getName());
+            factory= createDefaultBeanListFactory(beanType, 
rowset.getKeyColumns(), rowset.getColumns());
+            DBBeanFactoryCache.setFactoryForType(beanType, factory);
+        }
+        return factory;
+    }
+
+    /**
+     * gets or creates DBBeanListFactory for the given rowset
+     * @param beanType the beanType for which to create the list head 
+     * @param rowset the rowset for which to return the factory 
+     * @return the bean factory
+     */
+    protected synchronized <T> DBBeanListFactory<T> 
getCommandBeanListFactory(Class<T> beanType, DBCommand cmd) 
+    {
+        DBBeanListFactory<T> factory = 
DBBeanFactoryCache.getFactoryForType(beanType, false);
+        if (factory==null) 
+        {   // Check command: Must have select!
+            if (!cmd.hasSelectExpr())
+                throw new CommandWithoutSelectException(cmd);
+            // Create default factory
+            log.info("No factory found for bean type '{}'. Creating default", 
beanType.getName());
+            factory= createDefaultBeanListFactory(beanType, null, 
cmd.getSelectExpressions());
+            DBBeanFactoryCache.setFactoryForType(beanType, factory);
+        }
         return factory;
     }
     
@@ -1045,11 +1071,7 @@ public class DBUtils implements DBContextAware
      */
     public <T> List<T> queryBeanList(DBCommand cmd, Class<T> beanType, Object 
parent)
     {
-        DBRowSet rowset = DBRowSet.getRowsetforType(beanType, false);
-        if (rowset!=null)
-            return queryBeanList(cmd, getRowsetBeanListFactory(beanType, 
rowset), parent);
-        else
-            return queryBeanList(cmd, createDefaultBeanListFactory(beanType, 
null, cmd.getSelectExpressions()), parent);
+        return queryBeanList(cmd, getCommandBeanListFactory(beanType, cmd), 
parent);
     }
     
     /**
@@ -1091,11 +1113,7 @@ public class DBUtils implements DBContextAware
      */
     public <T> T queryBean(DBCommand cmd, Class<T> beanType)
     {
-        DBRowSet rowset = DBRowSet.getRowsetforType(beanType, false);
-        if (rowset!=null)
-            return queryBean(cmd, getRowsetBeanListFactory(beanType, rowset));
-        else
-            return queryBean(cmd, createDefaultBeanListFactory(beanType, null, 
cmd.getSelectExpressions()));
+        return queryBean(cmd, getCommandBeanListFactory(beanType, cmd));
     }
     
     /**
@@ -1125,8 +1143,15 @@ public class DBUtils implements DBContextAware
      */
     public final <T> T queryBean(Class<T> beanType, DBCompareExpr 
whereConstraints)
     {
-        DBRowSet rowset = DBRowSet.getRowsetforType(beanType, true);
-        return queryBean(beanType, rowset, whereConstraints);
+        DBObject.checkParamNull("whereConstraints", whereConstraints);
+        // must have a factory
+        DBBeanListFactory<T> factory = 
DBBeanFactoryCache.getFactoryForType(beanType, true);
+        // add constraints
+        DBDatabase db = whereConstraints.getDatabase();
+        DBCommand cmd = db.createCommand();
+        cmd.where(whereConstraints);
+        // query now
+        return queryBean(cmd, factory);
     }
     
     /**
@@ -1146,17 +1171,4 @@ public class DBUtils implements DBContextAware
         // use factory of rowset
         return queryBean(cmd, getRowsetBeanListFactory(beanType, rowset));
     }
-    
-    /**
-     * Queries a single bean based on primary key values
-     * @param beanType the beanType 
-     * @param key the primary key
-     * @return the entity bean
-     */
-    public final <T> T queryBean(Class<T> beanType, Object[] key)
-    {
-        DBRowSet rowset = DBRowSet.getRowsetforType(beanType, true);
-        return queryBean(beanType, rowset, key);
-    }
-    
 }
diff --git 
a/empire-db/src/main/java/org/apache/empire/db/list/DBBeanFactoryCache.java 
b/empire-db/src/main/java/org/apache/empire/db/list/DBBeanFactoryCache.java
new file mode 100644
index 0000000..525ff9f
--- /dev/null
+++ b/empire-db/src/main/java/org/apache/empire/db/list/DBBeanFactoryCache.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.empire.db.list;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.empire.db.exceptions.UnknownBeanTypeException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * DBBeanFactoryCache
+ * @author rainer
+ */
+public final class DBBeanFactoryCache
+{
+    protected static final Logger log = 
LoggerFactory.getLogger(DBBeanFactoryCache.class);
+    
+    private static Map<Class<?>, DBBeanListFactory<?>> beanFactoryMap; 
+    
+    static {
+        // set default
+        beanFactoryMap = new HashMap<Class<?>, DBBeanListFactory<?>>(); /* 
Concurrent ? */
+    }
+
+    /**
+     * Allows to provide a different implementation of the bean factory map 
+     * @param map the map to use
+     */
+    public static void setMapImplementation(Map<Class<?>, 
DBBeanListFactory<?>> map)
+    {
+        beanFactoryMap = map;
+    }
+   
+    /**
+     * 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 <T> DBBeanListFactory<T> 
getFactoryForType(Class<T> beanType, boolean checkExists)
+    {
+        @SuppressWarnings("unchecked")
+        DBBeanListFactory<T> factory = 
(DBBeanListFactory<T>)beanFactoryMap.get(beanType); 
+        if (factory==null && checkExists)
+            throw new UnknownBeanTypeException(beanType);
+        return factory;
+    }
+
+    /**
+     * sets the DBRowSet instance assigned to a particular Java bean type
+     * @param beanType the Java bean type
+     */
+    public static synchronized <T> void setFactoryForType(Class<?> beanType, 
DBBeanListFactory<T> factory)
+    {
+        if (factory!=null)
+        {   // Check previous
+            DBBeanListFactory<?> prev = beanFactoryMap.get(beanType);
+            if (prev!=null && prev!=factory)
+                log.warn("The Java bean type '{}' has already been assigned to 
a different BeanListFactory!", beanType.getName());
+            // Assign now
+            beanFactoryMap.put(beanType, factory);
+        }
+        else
+            beanFactoryMap.remove(beanType);
+    }
+}

Reply via email to