在db4o本地数据库中存储包含Calender对象的对象,无法检索对象字段 [英] Storing an object containing a Calender object in a db4o local database, cannot retrieve object fields

查看:93
本文介绍了在db4o本地数据库中存储包含Calender对象的对象,无法检索对象字段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have been storing an object which contains a GregorianCalendar object in a db4o database, which works just fine. However, on retrieving the object (after closing and re-opening the database), I cannot seem to access some of the information inside (namely get(GregorianCalendar.MONTH) ). I have included test code below, and am wondering how to fix this problem.

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确实支持 java.util.Calendar 对象,但不支持现成的。要添加对 Calendar 的支持,请将以下两行之一添加到数据库配置中:

Db4o does support java.util.Calendar objects, but not out-of-the-box. To add support for Calendar, add one of these two lines to your database configuration:

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

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

之所以必要,是因为日历具有 transient 字段,或者默认情况下未在Java中存储或序列化的字段( JLS§8.3.1.3)。您可以在日历 源代码(如果需要)。这些字段通常依赖于对象中的某些其他字段,并在其他字段的值更改时进行计算。从上面的 JLS部分:

The reason this is necessary is that Calendar has transient fields, or fields that don't get stored or serialized by default in Java (JLS §8.3.1.3). You can find these fields in the Calendar source code if you want. These fields are usually dependent on some other field in the object and get calculated when the value of the other field changes. From the JLS section above:


变量可以标记为 transient 表示它们

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

For example, let's say I have a class that represents a sale:

public class Sale {
    private double cost, taxRate;
    private transient double taxesPaid;

    // etc...
}

I' ve在这里将 taxesPaid 变量声明为临时变量,因为我可以从 cost taxRate找出它。如果成本为2.00美元,税率为7%,则所支付的税金为0.14美元。在数据库中,这种信息通常被认为是多余的,并且整本书都写着如何从数据库中删除这种依赖关系。在Java中,可以通过将其指定为 transient 来指定根本不存储该字段。

I've declared the taxesPaid variable here as transient because I can figure it out from cost and taxRate. If the cost is $2.00 and the tax rate is 7%, then the taxes paid would be $0.14. In databases, this kind of information is usually considered redundant, and there are entire books written on how to remove this kind of dependency from a database. In Java, you can specify that the field not be stored at all by specifying it as transient.

Db4o荣誉Java对瞬态字段的定义,也不会存储它们。实际上,大多数持久性框架和数据库都不会存储瞬态字段。因此,当db4o从数据库中重新创建 Calendar 对象时,它仅恢复其非瞬态字段,这意味着所有瞬态字段均为 null (因此您的 NullPointerException )。要解决此问题,您可以告诉db4o之一:

Db4o honors Java's definition of transient fields, and it won't store them either. In fact, most persistence frameworks and databases won't store transient fields. So when db4o recreates the Calendar object from the database, it only restores its non-transient fields, which means all the transient fields are null (hence your NullPointerException). To fix this, you tell db4o to either:


  • 调用 Calendar 的构造函数,日历构造函数将自动初始化/计算瞬态字段,或者

  • 存储日历的瞬态字段,它将像对待非瞬态字段一样对待它们。

  • Call Calendar's constructor, and the Calendar constructor will initialize/calculate the transient fields automatically or
  • Store Calendar's transient fields, which will treat the fields as if they aren't transient.

我们曾经看到人们建议在代码中同时使用这两行,而且我还看到 GregorianCalendar.class 代替了 Calendar.class

For the record, I've seen people recommend using both lines in their code, and I've also seen GregorianCalendar.class in place of Calendar.class. One or the other should work fine though.

抱歉,迟到了。我只是认为确保阅读此书的任何人都知道这是存储日历的正确方法(它允许对<$ c $进行索引,查询等)非常重要。 c>日历没有对象实例化的字段会减慢查询速度。

Sorry for weighing in late. I just thought it was important to make sure anyone reading this knows this is the proper way to store the Calendar (it allows indexing, querying, etc. on the Calendar fields without object instantiation slowing down the queries).

这篇关于在db4o本地数据库中存储包含Calender对象的对象,无法检索对象字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆