Calendar 在db4o本地数据库中存储包含日历对象的对象时,无法检索对象字段

Calendar 在db4o本地数据库中存储包含日历对象的对象时,无法检索对象字段,calendar,store,db4o,Calendar,Store,Db4o,我一直在将一个包含GregorianCalendar对象的对象存储在一个db4o数据库中,该数据库工作正常。但是,在检索对象时(在关闭并重新打开数据库之后),我似乎无法访问其中的一些信息(即get(gregoriacalendar.MONTH))。我在下面包含了测试代码,我想知道如何解决这个问题 import static org.junit.Assert.assertEquals; import java.util.GregorianCalendar; import org.junit.T

我一直在将一个包含GregorianCalendar对象的对象存储在一个db4o数据库中,该数据库工作正常。但是,在检索对象时(在关闭并重新打开数据库之后),我似乎无法访问其中的一些信息(即get(gregoriacalendar.MONTH))。我在下面包含了测试代码,我想知道如何解决这个问题

import static org.junit.Assert.assertEquals;

import java.util.GregorianCalendar;

import org.junit.Test;

import com.db4o.Db4oEmbedded;
import com.db4o.ObjectContainer;
import com.db4o.config.EmbeddedConfiguration;

public class DateTest {

    public class RecordDate {

        private GregorianCalendar calendar;

        public RecordDate() {
            calendar = new GregorianCalendar();
        }

        public int getMonth() {
            return calendar.get(GregorianCalendar.MONTH);
        }
    }

    @Test
    public void testGetMonth() {
        EmbeddedConfiguration config = Db4oEmbedded.newConfiguration();
        config.common().objectClass(RecordDate.class).cascadeOnActivate(true);
        config.common().objectClass(RecordDate.class).cascadeOnUpdate(true);
        config.common().activationDepth(25);
        config.common().updateDepth(25);

        ObjectContainer database = Db4oEmbedded.openFile(config,
                "db/datetest.db");

        GregorianCalendar currentdate = new GregorianCalendar();
        RecordDate testdate = new RecordDate();
        assertEquals(currentdate.get(GregorianCalendar.MONTH),
                testdate.getMonth()); // this passes

        database.store(testdate);
        database.close();

        EmbeddedConfiguration config2 = Db4oEmbedded.newConfiguration();
        config2.common().objectClass(RecordDate.class).cascadeOnActivate(true);
        config2.common().objectClass(RecordDate.class).cascadeOnUpdate(true);
        config2.common().activationDepth(25);
        config2.common().updateDepth(25);
        database = Db4oEmbedded.openFile(config2, "db/datetest.db");

        testdate = (RecordDate) database.queryByExample(RecordDate.class)
                .next();
        assertEquals(currentdate.get(GregorianCalendar.MONTH),
                testdate.getMonth()); // this should pass, but doesn't
        database.close();
    }
}

db4o不支持存储日历实例。您应该存储日期实例

您也可以使用它来存储日历对象。但是,is不支持对该对象的任何查询。您可以尝试序列化,它只使用Java序列化来存储对象:

configuration.common().objectClass(Calendar.class).translate(new TSerializable());
configuration.common().objectClass(GregorianCalendar.class).translate(new TSerializable());
db4o基本上支持存储您自己的“数据”——对象,它可以由原语、字符串、数组、基本集合和对其他数据对象的引用组成。然而,db4o不支持存储复杂的框架对象,如日历、Swing对象和并发集合等


然而,db4o尝试存储任何对象,不管发生什么。但是,对于具有大量瞬态的复杂对象和对静态对象的引用,这可能会失败。

Db4o确实支持
java.util.Calendar
对象,但不是现成的。要添加对
日历的支持
,请在数据库配置中添加以下两行之一:

configuration.common().objectClass(Calendar.class).callConstructor(true);

configuration.common().objectClass(Calendar.class).storeTransientFields(true);
之所以需要这样做,是因为
Calendar
transient
字段,或者默认情况下在Java()中没有存储或序列化的字段。如果需要,您可以在
日历中找到这些字段。这些字段通常依赖于对象中的其他字段,并在其他字段的值更改时进行计算。从上面的JLS部分:

变量可以标记为
transient
,以指示它们不是对象持久状态的一部分

例如,假设我有一个代表销售的类:

公共类销售{
私人双重成本,税率;
私人临时性双重征税;
//等等。。。
}
我在这里将
taxesPaid
变量声明为暂时变量,因为我可以从
cost
taxRate
中计算出来。如果成本为2.00美元,税率为7%,则所缴税款为0.14美元。在数据库中,这类信息通常被认为是冗余的,并且有很多关于如何从数据库中删除这类依赖关系的书籍。在Java中,您可以通过将字段指定为
transient
来指定根本不存储该字段

Db4o尊重Java对瞬态字段的定义,并且也不会存储它们。事实上,大多数持久性框架和数据库不会存储临时字段。因此,当db4o从数据库中重新创建
Calendar
对象时,它只恢复其非临时字段,这意味着所有临时字段都是
null
(因此您的
NullPointerException
)。要解决此问题,请告诉db4o:

  • 调用
    Calendar
    的构造函数,然后
    Calendar
    构造函数将自动或自动初始化/计算瞬态字段
  • 存储
    Calendar
    的临时字段,这些字段将被视为非临时字段
作为记录,我看到有人建议在他们的代码中使用这两行,我也看到了
gregoriacalendar.class
代替
Calendar.class
。不过,其中一个应该很好


对不起,我来晚了。我只是认为确保阅读本文的任何人都知道这是存储
日历的正确方法非常重要(它允许在
日历
字段上进行索引、查询等,而无需对象实例化来减慢查询速度)。

那么,您在数据库中存储的月份是什么,您从中得到的对象上的月份是什么?这并不是它们不同,而是它抛出了一个NullPointerException
getMonth()
方法(即
calendar
字段是
null
),或者
get(Gregoriacalendar.month)
?还是
等于
方法?请帮助解决您的问题。get(gregoriacalendar.MONTH)抛出异常。calendar字段在检索时不是null,我已经检查过了。我检查过API,它说get()不应该抛出NullPointerException。get(gregorianalendar.MONTH)之后的堆栈跟踪是“at java.util.Calendar.get(未知源)”,谢谢。在我的例子中,我不再得到空点异常,但每次检索对象的日历属性时,我只得到当前日期,而不是我存储的日期。我的建议是将日期存储为字符串,因为db4o不支持存储复杂的对象,如日历、时间戳等。然而,db4o将尝试存储任何对象,但不能保证成功@当然,你可以这样做,但它大大降低了搜索能力。我更倾向于将其存储为
long
或您自己的自定义数据类型,而不是
String
,这样比较运算符更容易理解,谓词查询和SODA查询最终更容易编写和稍后读取。