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);
+ }
+}