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 68648bc EMPIREDB-362 small fix
68648bc is described below
commit 68648bc334cacb392d522558b1d0633595283f36
Author: Rainer Döbele <[email protected]>
AuthorDate: Wed Feb 9 10:29:16 2022 +0100
EMPIREDB-362 small fix
---
.../java/org/apache/empire/commons/ClassUtils.java | 73 ++++++++++++++++++++++
.../main/java/org/apache/empire/db/DBRecord.java | 7 ++-
.../java/org/apache/empire/db/DBRecordBase.java | 24 ++++---
.../java/org/apache/empire/db/DBRecordBean.java | 11 ++--
4 files changed, 100 insertions(+), 15 deletions(-)
diff --git a/empire-db/src/main/java/org/apache/empire/commons/ClassUtils.java
b/empire-db/src/main/java/org/apache/empire/commons/ClassUtils.java
index 4e7d2e3..7b8b618 100644
--- a/empire-db/src/main/java/org/apache/empire/commons/ClassUtils.java
+++ b/empire-db/src/main/java/org/apache/empire/commons/ClassUtils.java
@@ -23,6 +23,7 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
+import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
@@ -81,6 +82,78 @@ public final class ClassUtils
}
/**
+ * Makes a copy of an object if possible or returns null
+ * @param obj the object to copy
+ * @return either a copy of the object or null if copy is not supported
+ */
+ public static Object copy(Object obj)
+ {
+ if (obj==null)
+ return null;
+ // the class
+ Class<?> clazz = obj.getClass();
+ // simple check
+ if (clazz.isInterface() || clazz.isAnnotation())
+ return null; // not supported
+ if (clazz.isPrimitive() || clazz.isEnum())
+ return obj; // no need to copy
+ // try clonable
+ if (obj instanceof Cloneable)
+ { try {
+ return invokeSimpleMethod(java.lang.Object.class, obj,
"clone", true);
+ } catch (Exception e) {
+ log.error("Copy through Cloning failed for :
"+clazz.getName(), e);
+ }
+ }
+ // try serializable
+ if (obj instanceof Serializable)
+ { try
+ { ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ // Write the object
+ ObjectOutputStream oos = new ObjectOutputStream(baos);
+ oos.writeObject(obj);
+ // Read the object
+ ObjectInputStream oin = new ObjectInputStream(new
ByteArrayInputStream(baos.toByteArray()));
+ Object copy = oin.readObject();
+ // return result
+ return copy;
+ } catch (IOException | ClassNotFoundException e) {
+ log.error("Copy through Serialization failed for :
"+clazz.getName(), e);
+ }
+ }
+ // find standard constructor
+ int i=0;
+ final Constructor<?>[] ctors = clazz.getConstructors();
+ for (; i<ctors.length; i++)
+ if (ctors[i].getParameterCount()==0)
+ break;
+ if (i<ctors.length)
+ { try
+ { // Try standard constructor
+ Object copy = clazz.newInstance();
+ Field[] fields = copy.getClass().getDeclaredFields();
+ for (Field field : fields) {
+ // make acessible
+ boolean accessible = field.isAccessible();
+ if (!accessible)
+ field.setAccessible(true);
+ // copy
+ Object value = field.get(obj); // recurse ?
+ field.set(copy, value);
+ // restore
+ if (!accessible)
+ field.setAccessible(false);
+ }
+ return copy;
+ } catch (InstantiationException | IllegalAccessException e) {
+ log.error("Copy through Instantiation failed for :
"+clazz.getName(), e);
+ }
+ }
+ // not supported
+ return null;
+ }
+
+ /**
* Retrieve a field value using reflection
* @param clazz the class from which to obtain the field
* @param object the object instance from which to obtain the field
diff --git a/empire-db/src/main/java/org/apache/empire/db/DBRecord.java
b/empire-db/src/main/java/org/apache/empire/db/DBRecord.java
index 71749fc..3cd3c7c 100644
--- a/empire-db/src/main/java/org/apache/empire/db/DBRecord.java
+++ b/empire-db/src/main/java/org/apache/empire/db/DBRecord.java
@@ -21,6 +21,7 @@ package org.apache.empire.db;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
+import java.io.Serializable;
import java.sql.Connection;
import org.apache.empire.commons.ClassUtils;
@@ -49,7 +50,7 @@ import org.slf4j.LoggerFactory;
*
* The record is Serializable either if the provided DBContext is
serializable, or if the Context is provided on deserialization in a derived
class.
*/
-public class DBRecord extends DBRecordBase
+public class DBRecord extends DBRecordBase implements Serializable // really
Serializable?
{
private static final long serialVersionUID = 1L;
@@ -212,8 +213,8 @@ public class DBRecord extends DBRecordBase
/**
* Returns the record id for tables which have a single numeric primary key
- * This method is provided for convenience in additon to the the getKey()
method
- * @return the record id
+ * This method is provided for convenience in addition to the the getKey()
method
+ * @return the record id or 0 if the key is null
* @throws NoPrimaryKeyException if the table has no primary key
* @throws NotSupportedException if the primary key is not a single column
of if the column is not numeric
*/
diff --git a/empire-db/src/main/java/org/apache/empire/db/DBRecordBase.java
b/empire-db/src/main/java/org/apache/empire/db/DBRecordBase.java
index a453b37..7a68e1e 100644
--- a/empire-db/src/main/java/org/apache/empire/db/DBRecordBase.java
+++ b/empire-db/src/main/java/org/apache/empire/db/DBRecordBase.java
@@ -18,13 +18,13 @@
*/
package org.apache.empire.db;
-import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.util.Collection;
import java.util.List;
import org.apache.commons.beanutils.BeanUtilsBean;
import org.apache.commons.beanutils.PropertyUtilsBean;
+import org.apache.empire.commons.ClassUtils;
import org.apache.empire.commons.ObjectUtils;
import org.apache.empire.commons.Options;
import org.apache.empire.commons.StringUtils;
@@ -60,10 +60,8 @@ import org.w3c.dom.Element;
*
* Also, field value changes, can be handled using the onFieldChanged event.
*/
-public abstract class DBRecordBase extends DBRecordData implements Record,
Cloneable, Serializable
+public abstract class DBRecordBase extends DBRecordData implements Record,
Cloneable
{
- private static final long serialVersionUID = 1L;
-
private static final Logger log =
LoggerFactory.getLogger(DBRecordBase.class);
/**
@@ -90,9 +88,9 @@ public abstract class DBRecordBase extends DBRecordData
implements Record, Clone
throw new ObjectNotValidException(record);
// save state
this.state = record.state;
- this.modified = copy(record.modified);
- this.fields = copy(record.fields);
- this.rowsetData = record.rowsetData;
+ this.modified = copy(record.modified);
+ this.fields = copy(record.fields);
+ this.rowsetData = copy(record.rowsetData);
}
@Override
@@ -177,6 +175,18 @@ public abstract class DBRecordBase extends DBRecordData
implements Record, Clone
}
return copy;
}
+
+ protected Object copy(Object other)
+ {
+ if (other==null)
+ return null;
+ if (other instanceof Object[])
+ return copy((Object[])other);
+ Object copy = ClassUtils.copy(other);
+ if (copy!=null)
+ return copy;
+ return other;
+ }
}
/* Record state enum */
diff --git a/empire-db/src/main/java/org/apache/empire/db/DBRecordBean.java
b/empire-db/src/main/java/org/apache/empire/db/DBRecordBean.java
index 3992654..03a8ad2 100644
--- a/empire-db/src/main/java/org/apache/empire/db/DBRecordBean.java
+++ b/empire-db/src/main/java/org/apache/empire/db/DBRecordBean.java
@@ -18,6 +18,7 @@
*/
package org.apache.empire.db;
+import java.io.Serializable;
import java.sql.Connection;
import org.apache.empire.commons.StringUtils;
@@ -39,7 +40,7 @@ import org.slf4j.LoggerFactory;
* Thus it has a Default constructor and is essentially a dynamic bean
*
*/
-public class DBRecordBean extends DBRecordBase
+public class DBRecordBean extends DBRecordBase implements Serializable
{
private static final long serialVersionUID = 1L;
@@ -132,8 +133,8 @@ public class DBRecordBean extends DBRecordBase
/**
* Returns the record id for tables which have a single numeric primary key
- * This method is provided for convenience in additon to the the getKey()
method
- * @return the record id
+ * This method is provided for convenience in addition to the the getKey()
method
+ * @return the record id or 0 if the key is null
* @throws NoPrimaryKeyException if the table has no primary key
* @throws NotSupportedException if the primary key is not a single column
of if the column is not numeric
*/
@@ -257,7 +258,7 @@ public class DBRecordBean extends DBRecordBase
// check updatable
checkUpdateable();
// allow rollback
- if (isRollbackHandlingEnabled())
+ if (this.enableRollbackHandling &&
context.isRollbackHandlingEnabled())
context.appendRollbackHandler(createRollbackHandler());
// update
getRowSet().updateRecord(this);
@@ -283,7 +284,7 @@ public class DBRecordBean extends DBRecordBase
// check updatable
checkUpdateable();
// allow rollback
- if (isRollbackHandlingEnabled())
+ if (this.enableRollbackHandling && context.isRollbackHandlingEnabled())
context.appendRollbackHandler(createRollbackHandler());
// Delete only if record is not new
if (!isNew())