You are viewing a plain text version of this content. The canonical link for it is here.
Posted to ojb-dev@db.apache.org by ar...@apache.org on 2004/06/25 20:08:06 UTC
cvs commit: db-ojb build.properties release-notes.txt
arminw 2004/06/25 11:08:06
Modified: src/test/org/apache/ojb/broker/metadata
PersistentFieldPerfTest.java
src/test/org/apache/ojb OJB.properties
. build.properties release-notes.txt
Added: src/java/org/apache/ojb/broker/metadata/fieldaccess
PersistentFieldDirectAccessImplNew.java
PersistentFieldPrivilegedImplNew.java
Log:
- add new rewritten PersistentField implementations
- write notice to release-notes
- prepare for 1.0
Revision Changes Path
1.1 db-ojb/src/java/org/apache/ojb/broker/metadata/fieldaccess/PersistentFieldDirectAccessImplNew.java
Index: PersistentFieldDirectAccessImplNew.java
===================================================================
package org.apache.ojb.broker.metadata.fieldaccess;
/* Copyright 2003-2004 The Apache Software Foundation
*
* Licensed 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.
*/
import java.lang.reflect.Field;
import java.util.List;
import org.apache.ojb.broker.core.proxy.ProxyHelper;
import org.apache.ojb.broker.metadata.MetadataException;
import org.apache.ojb.broker.util.ClassHelper;
/**
* This {@link PersistentField} implementation
* is the high-speed version of the access strategies.
* <br/>
* It does not cooperate with an AccessController,
* but accesses the fields directly. This implementation persistent
* attributes don't need getters and setters
* and don't have to be declared public or protected. Only the the
* metadata field names have to match the class fields.
*
* @author <a href="mailto:armin@codeAuLait.de">Armin Waibel</a>
* @version $Id: PersistentFieldDirectAccessImplNew.java,v 1.1 2004/06/25 18:08:05 arminw Exp $
*/
public class PersistentFieldDirectAccessImplNew extends PersistentFieldBase
{
private static final long serialVersionUID = -5458024240998909205L;
private static int NESTED_UNKOWM = 0;
private static int NESTED_TRUE = 1;
private static int NESTED_FALSE = 2;
private transient List fieldsList;
private transient Field field;
private transient int isNestedField;
public PersistentFieldDirectAccessImplNew()
{
}
public PersistentFieldDirectAccessImplNew(Class type, String fieldname)
{
super(type, fieldname);
}
public Class getType()
{
return getField().getType();
}
public Class getDeclaringClass()
{
return getField().getDeclaringClass();
}
/**
* Returns the underlying field object.
* If parameter <tt>setAccessible</tt> is true the
* field access checking was suppressed.
*/
protected Field getField()
{
if (field == null)
{
/*
first we build a graph of fields for nested fields support,
but for best performance on non-nested fields we also keep
the latest field separate and build a 'isNested' flag.
*/
fieldsList = getFieldGraph(makeAccessible());
field = (Field) fieldsList.get(fieldsList.size() - 1);
isNestedField = fieldsList.size() > 1 ? NESTED_TRUE : NESTED_FALSE;
}
return field;
}
private List getFieldsList()
{
// make sure class is init
if (field == null) getField();
return fieldsList;
}
protected boolean isNestedField()
{
// make sure class is init
if(isNestedField == NESTED_UNKOWM)
{
getField();
}
return isNestedField == NESTED_TRUE;
}
/**
* do not override this method, have a look at {@link #setValueFor(java.lang.reflect.Field, java.lang.Object, java.lang.Object)}
*/
public void set(Object target, Object value) throws MetadataException
{
Object current = target;
if (isNestedField())
{
List fields = getFieldsList();
int size = fields.size() - 1;
Field field;
for (int i = 0; i < size; i++)
{
field = (Field) fields.get(i);
Object attribute = null;
try
{
// System.out.println("" + (field != null ? field.getName() : null)
// + "/" + (field != null ? field.getType() : null)
// + " " + (current != null ? current.getClass() : null));
//attribute = field.get(current);
attribute = getValueFrom(field, current);
}
catch (Exception e)
{
throw new MetadataException("Can't read field '" + field.getName() + "' of type " + field.getType().getName(), e);
}
if (attribute != null || value != null)
{
if (attribute == null)
{
try
{
attribute = ClassHelper.newInstance(field.getType());
}
catch (Exception e)
{
throw new MetadataException("Can't create nested object of type '"
+ field.getType() + "' for field '"
+ field.getName() + "'", e);
}
}
try
{
//field.set(current, attribute);
setValueFor(field, current, attribute);
}
//catch (IllegalAccessException e)
catch (Exception e)
{
throw new MetadataException("Can't set nested object of type '"
+ field.getType() + "' for field '"
+ field.getName() + "'", e);
}
}
else
{
return;
}
current = attribute;
}
}
if(current != null) setValueFor(getField(), current, value);
}
/**
* do not override this method, have a look at {@link #getValueFrom(java.lang.reflect.Field, java.lang.Object)}
*/
public Object get(Object target) throws MetadataException
{
Object result = target;
if (isNestedField())
{
List fields = getFieldsList();
for (int i = 0; i < fields.size(); i++)
{
result = getValueFrom((Field) fields.get(i), result);
if (result == null) break;
}
}
else
{
result = result != null ? getValueFrom(getField(), result) : null;
}
return result;
}
protected Object getValueFrom(Field field, Object target)
{
try
{
return field.get(ProxyHelper.getRealObject(target));
}
catch (IllegalAccessException e)
{
throw new MetadataException(
"IllegalAccess error getting field:" +
(field != null ? field.getName() : null) + " in object:"
+ target != null ? target.getClass().getName() : null, e);
}
}
protected void setValueFor(Field field, Object target, final Object value)
{
try
{
/**
* MBAIRD
* we need to be able to set values to null. We can only set something to null if
* the type is not a primitive (assignable from Object).
*/
// thanks to Tomasz Wysocki for this trick
if ((value != null) || !field.getType().isPrimitive())
{
// System.err.println("## t: " + target + " v: " + value);
field.set(ProxyHelper.getRealObject(target), value);
}
}
catch (NullPointerException ignored)
{
getLog().info("Target object '" + (target != null ? target.getClass().getName() : null)
+ "' for field '" + (field != null ? field.getName() : null)
+ "' of type '" + (field != null ? field.getType().getName() : null)
+ "' seems to be null. Can't write into null.", ignored);
}
catch (Exception e)
{
getLog().error("while set field: " + buildMessageString(target, value, field));
throw new MetadataException("IllegalAccess error setting field:" +
(field != null ? field.getName() : null) + " in object:" + target.getClass().getName(), e);
}
}
/**
* This implementation returns always 'true'.
* @see AbstractPersistentField#makeAccessible()
*/
protected boolean makeAccessible()
{
return true;
}
/**
* Always returns 'false'.
* @see PersistentField#usesAccessorsAndMutators
*/
public boolean usesAccessorsAndMutators()
{
return false;
}
}
1.1 db-ojb/src/java/org/apache/ojb/broker/metadata/fieldaccess/PersistentFieldPrivilegedImplNew.java
Index: PersistentFieldPrivilegedImplNew.java
===================================================================
package org.apache.ojb.broker.metadata.fieldaccess;
/* Copyright 2003-2004 The Apache Software Foundation
*
* Licensed 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.
*/
import java.io.Serializable;
import java.lang.reflect.Field;
import java.security.AccessController;
import java.security.PrivilegedAction;
/**
* A {@link PersistentField} implementation using
* reflection to access but does cooperate with
* AccessController and do not suppress the java
* language access check.
*
* @author <a href="mailto:thma@apache.org">Thomas Mahler<a>
* @author <a href="mailto:armin@codeAuLait.de">Armin Waibel</a>
* @version $Id: PersistentFieldPrivilegedImplNew.java,v 1.1 2004/06/25 18:08:05 arminw Exp $
* @see PersistentFieldDirectAccessImpl
*/
public class PersistentFieldPrivilegedImplNew extends PersistentFieldDirectAccessImplNew
{
private static final long serialVersionUID = -6110158693763128846L;
private SetAccessibleAction setAccessibleAction = new SetAccessibleAction();
private UnsetAccessibleAction unsetAccessibleAction = new UnsetAccessibleAction();
private static final int ACCESSIBLE_STATE_UNKOWN = 0;
private static final int ACCESSIBLE_STATE_FALSE = 1;
private static final int ACCESSIBLE_STATE_SET_TRUE = 2;
public PersistentFieldPrivilegedImplNew()
{
}
public PersistentFieldPrivilegedImplNew(Class type, String fieldname)
{
super(type, fieldname);
}
protected Object getValueFrom(Field field, Object target)
{
int accessibleState = ACCESSIBLE_STATE_UNKOWN;
Object result = null;
if (!field.isAccessible()) accessibleState = ACCESSIBLE_STATE_FALSE;
if (accessibleState == ACCESSIBLE_STATE_FALSE)
{
accessibleState = ACCESSIBLE_STATE_SET_TRUE;
setAccessibleAction.current = field;
AccessController.doPrivileged(setAccessibleAction);
}
try
{
result = super.getValueFrom(field, target);
}
finally
{
if (accessibleState == ACCESSIBLE_STATE_SET_TRUE)
{
unsetAccessibleAction.current = field;
AccessController.doPrivileged(unsetAccessibleAction);
}
}
return result;
}
protected void setValueFor(Field field, Object target, Object value)
{
int accessibleState = ACCESSIBLE_STATE_UNKOWN;
if (!field.isAccessible()) accessibleState = ACCESSIBLE_STATE_FALSE;
if (accessibleState == ACCESSIBLE_STATE_FALSE)
{
accessibleState = ACCESSIBLE_STATE_SET_TRUE;
setAccessibleAction.current = field;
AccessController.doPrivileged(setAccessibleAction);
}
try
{
super.setValueFor(field, target, value);
}
finally
{
if (accessibleState == ACCESSIBLE_STATE_SET_TRUE)
{
unsetAccessibleAction.current = field;
AccessController.doPrivileged(unsetAccessibleAction);
}
}
}
/**
* This implementation returns always 'false'.
*
* @see AbstractPersistentField#makeAccessible()
*/
public boolean makeAccessible()
{
return false;
}
/**
* Always returns 'false'.
*
* @see PersistentField#usesAccessorsAndMutators
*/
public boolean usesAccessorsAndMutators()
{
return false;
}
//************************************************************
// inner class
//************************************************************
private class SetAccessibleAction implements PrivilegedAction, Serializable
{
static final long serialVersionUID = 8152025069698028050L;
Field current;
public Object run()
{
current.setAccessible(true);
return null;
}
}
private class UnsetAccessibleAction implements PrivilegedAction, Serializable
{
static final long serialVersionUID = -2284913657454430305L;
Field current;
public Object run()
{
current.setAccessible(false);
return null;
}
}
}
1.2 +8 -9 db-ojb/src/test/org/apache/ojb/broker/metadata/PersistentFieldPerfTest.java
Index: PersistentFieldPerfTest.java
===================================================================
RCS file: /home/cvs/db-ojb/src/test/org/apache/ojb/broker/metadata/PersistentFieldPerfTest.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- PersistentFieldPerfTest.java 25 Jun 2004 13:26:49 -0000 1.1
+++ PersistentFieldPerfTest.java 25 Jun 2004 18:08:05 -0000 1.2
@@ -6,7 +6,10 @@
import org.apache.ojb.broker.metadata.fieldaccess.PersistentField;
import org.apache.ojb.broker.metadata.fieldaccess.PersistentFieldAutoProxyImpl;
import org.apache.ojb.broker.metadata.fieldaccess.PersistentFieldDirectAccessImpl;
+import org.apache.ojb.broker.metadata.fieldaccess.PersistentFieldDirectAccessImplNew;
import org.apache.ojb.broker.metadata.fieldaccess.PersistentFieldIntrospectorImpl;
+import org.apache.ojb.broker.metadata.fieldaccess.PersistentFieldPrivilegedImpl;
+import org.apache.ojb.broker.metadata.fieldaccess.PersistentFieldPrivilegedImplNew;
import org.apache.ojb.broker.util.ClassHelper;
import org.apache.ojb.junit.OJBTestCase;
@@ -40,7 +43,7 @@
Class testClass = NestedFieldsTest.NestedMain.class;
String fieldName = "name";
String fieldNameNested = "nestedDetail::nestedDetailDetail::realDetailName";
- int numberOfOperations = 0;
+ int numberOfOperations = 30000;
int repeat = 5;
public static void main(String[] args)
@@ -49,17 +52,15 @@
junit.textui.TestRunner.main(arr);
}
-// Class[] persistentFieldClasses = new Class[] {
-// PersistentFieldDirectAccessImpl_2.class
-// , PersistentFieldDirectAccessImpl.class
-// , PersistentFieldIntrospectorImpl.class
-// , PersistentFieldAutoProxyImpl.class};
-
Class[] persistentFieldClasses = new Class[]{
PersistentFieldDirectAccessImpl.class
+ , PersistentFieldDirectAccessImplNew.class
, PersistentFieldIntrospectorImpl.class
+ , PersistentFieldPrivilegedImpl.class
+ , PersistentFieldPrivilegedImplNew.class
, PersistentFieldAutoProxyImpl.class};
+
private PersistentField newInstance(Class pfClass, Class testClass, String fieldName) throws Exception
{
Class[] types = new Class[]{Class.class, String.class};
@@ -69,7 +70,6 @@
public void testFieldPerformance() throws Exception
{
- numberOfOperations = 300000;
System.out.println();
System.out.println("=========================================");
System.out.println("Field performance, set/get " + numberOfOperations + " times a field");
@@ -92,7 +92,6 @@
public void testNestedFieldPerformance() throws Exception
{
- numberOfOperations = 300000;
System.out.println();
System.out.println("=========================================");
System.out.println("Nested Field performance, set/get " + numberOfOperations + " times a nested field");
1.71 +6 -1 db-ojb/src/test/org/apache/ojb/OJB.properties
Index: OJB.properties
===================================================================
RCS file: /home/cvs/db-ojb/src/test/org/apache/ojb/OJB.properties,v
retrieving revision 1.70
retrieving revision 1.71
diff -u -r1.70 -r1.71
--- OJB.properties 3 Jun 2004 23:46:08 -0000 1.70
+++ OJB.properties 25 Jun 2004 18:08:05 -0000 1.71
@@ -399,6 +399,11 @@
#PersistentFieldClass=org.apache.ojb.broker.metadata.fieldaccess.PersistentFieldIntrospectorImpl
#PersistentFieldClass=org.apache.ojb.broker.metadata.fieldaccess.PersistentFieldDynaBeanAccessImpl
#PersistentFieldClass=org.apache.ojb.broker.metadata.fieldaccess.PersistentFieldAutoProxyImpl
+# Here you can try the new upcoming PersistentField implementations. These classes will replace the
+# old ones on next release. They pass the test-suite, but should be tested by community too.
+# The new implementations are about 50 times faster in handling nested fields.
+#PersistentFieldClass=org.apache.ojb.broker.metadata.fieldaccess.PersistentFieldDirectAccessImplNew
+#PersistentFieldClass=org.apache.ojb.broker.metadata.fieldaccess.PersistentFieldPrivilegedImplNew
#
#
#----------------------------------------------------------------------------------------
1.64 +3 -3 db-ojb/build.properties
Index: build.properties
===================================================================
RCS file: /home/cvs/db-ojb/build.properties,v
retrieving revision 1.63
retrieving revision 1.64
diff -u -r1.63 -r1.64
--- build.properties 22 Jun 2004 20:46:48 -0000 1.63
+++ build.properties 25 Jun 2004 18:08:05 -0000 1.64
@@ -168,9 +168,9 @@
project-name=db-ojb
major=1
minor=0
-build=rc7
+build=0
version=${major}.${minor}.${build}
-versiondate=2004-06-13
+versiondate=2004-06-25
ojb-filename-prefix=${project-name}-${version}
#
1.53 +60 -2 db-ojb/release-notes.txt
Index: release-notes.txt
===================================================================
RCS file: /home/cvs/db-ojb/release-notes.txt,v
retrieving revision 1.52
retrieving revision 1.53
diff -u -r1.52 -r1.53
--- release-notes.txt 25 Jun 2004 13:11:35 -0000 1.52
+++ release-notes.txt 25 Jun 2004 18:08:05 -0000 1.53
@@ -8,8 +8,28 @@
relational databases. OJB provides ODMG and JDO interfaces.
---------------------------------------------------------------------
-Release 1.0 ??
+Release 1.0
---------------------------------------------------------------------
+NEW FEATURES:
+--
+
+NOTES:
+- We introduce new PersistentField implementations in OJB.properties file called
+PersistentFieldXXXXImplNew. PersistentField implementations responsible for read/write
+to object attributes. The new versions has much better performance in read/write nested
+fields (up to 50 times faster than the old implementions) and will replace the old
+classes on next version. Because PersistentField is an important kernel class we
+wait for community response before change. Feel free to try the new upcoming versions.
+
+
+CHANGES:
+--
+
+BUG FIXES:
+Please refer to our Bug tracking site (http://issues.apache.org/scarab/servlet/scarab/)
+under http://issues.apache.org/scarab/servlet/scarab/issues/id/OJBxxx
+to see details for a bug with id OJBxxx.
+
KNOWN ISSUES:
- The default ojb escape character '\' does not work for database using the same default as well and
@@ -20,6 +40,44 @@
crit.addLike("firstname", "h%|%");
This issue is fixed for MySql and PostgreSql so far.
+
+- odmg-api: If a user exchange already existing objects in 1:n references without changing the size
+of the collection, the main object will not become dirty and the FK values of the exchanged objects
+will not be updated.
+E.g. two objects obj_1 anf obj_2 with 1:n reference to ref objects, each with one
+existing/persistent reference object, obj_1{ref_1} and obj_2{ref_2}.
+Lock objects and exchange the references in collection obj_1{ref_2}
+and obj_2{ref_1} and commit --> FK values of ref_1 and ref_2 will not be updated.
+
+- odmg-api: Creation of m:n relation only works when objects created step by step (or use PB-api
+as workaround), persist a whole object graph seems not to work proper.
+
+- ReportQueries should not be used with columns referencing Classes with extents:
+
+ ReportQueryByCriteria q = QueryFactory.newReportQuery(ProductGroup.class, crit);
+ q.setAttributes(new String[] { "groupName", "sum(allArticlesInGroup.stock)", "sum(allArticlesInGroup.price)" });
+ q.addGroupBy("groupName");
+
+ ProductGroup.allArticlesInGroup points to class Article having multiple extents.
+
+ As a workaround the query can be 'reversed' :
+
+ ReportQueryByCriteria q = QueryFactory.newReportQuery(Article.class, crit);
+ q.setAttributes(new String[] { "productGroup.groupName", "sum(stock)", "sum(price)" });
+ q.addGroupBy("productGroup.groupName");
+
+ Due to the fact the Article has extents multiple selects will be executed,
+ so the same ProductGroup may show up more than once.
+
+ Please see the testcases QueryTest#testReportQueryGroupByExtents1 and
+ QueryTest#testReportQueryGroupByExtents2.
+
+- A count on ReportQueries containing groupBy does not deliver a correct result.
+
+- Batch handling doesn't work proper with optimistic locking. This will be fixed
+before long after 1.0
+
+
---------------------------------------------------------------------
Release 1.0 rc7
---------------------------------------------------------------------
To unsubscribe, e-mail: ojb-dev-unsubscribe@db.apache.org
For additional commands, e-mail: ojb-dev-help@db.apache.org