DataNucleus JDO基础入门

开发应用程序通常是一项复杂的任务,涉及许多组件。 开发所有这些组件可能非常耗时。 Java 数据对象 API (JDO) 旨在减少花费的一些时间,提供一个 API 以允许 Java 开发人员将面向对象的数据持久化到任何数据库中,并提供一种使用与开发人员相同的 Java 语法的查询语言。

DataNucleus JDO 提供了此 JDO 标准的实现,允许您(用户)将面向对象的数据持久保存到该标准的 RDBMS 数据存储中,而且还保存到范围广泛的其他数据存储中。 其中包括流行的map存储,例如 Cassandra 和 HBase、Neo4j 图形存储、Excel 或 OpenDocument 格式的电子表格、JSON 格式的 Amazon 和 Google Storage 选项、流行的 MongoDB 类 JSON 文档存储,以及无处不在的 LDAP 等等。

DataNucleus 并不是所有问题的最佳解决方案。 例如,如果您想要批量保存大量数据,那么其他更接近数据存储 API 的解决方案会更合适。 您想要定制发送到数据存储的精确查询以利用某些特定于数据存储的功能是另一种情况,您可能会发现手工制作的解决方案更合适。 也就是说,DataNucleus JDO 的功能范围涵盖了广泛的用例,使用 DataNucleus 的门槛非常低。 您无需精通所选数据存储的所有功能即可使用它。 它使您免于进行大多数更常规的处理,同时仍然让您高度控制其行为,我们希望您能从其功能中受益。

使用原则

在开始使用 JDO 进行 Java 持久化时,需要牢记一些关键点。

  • 你的类应该就是你的类。 DataNucleus 对您几乎没有任何影响。 如果您尚未提供默认构造函数,则 DataNucleus 增强器提供添加默认构造函数的功能。

  • 您的 JDO 持久类需要字节码增强以在持久过程中使用,但这可以是一个自动的编译后步骤。

  • 要持久化类的对象,您首先需要定义哪些类是可持久化的,以及它们是如何持久化的。 从 JDO 映射指南开始

  • JDO 的使用需要 PersistenceManagerFactory 来访问数据存储。

  • 持久化本身由 PersistenceManager 控制,每个要持久化的对象都有不同的生命周期状态,您需要了解这些状态。

  • 您可以通过对象的身份或使用查询来检索对象。 通过 JDO,您可以使用 JDOQL SQL 查询语言。

  • 对于您使用的任何数据存储,您都需要 javax.jdo 以及 datanucleus-api-jdo、datanucleus-core 和 datanucleus-XXX jar。

理解JARs

DataNucleus 具有模块化架构,您将需要在应用程序中使用多个 JAR,如下所示

  • javax.jdo.jar :这是 JDO API。 这基本上是接口、注释和辅助类的集合。

  • datanucleus-api-jdo.jar :这是 DataNucleus 对 JDO API 的实现。 它实现了 javax.jdo.jar 中定义的接口。

  • datanucleus-core.jar :它提供了基本的 DataNucleus 持久化机制,所有 DataNucleus 插件都需要它。

  • datanucleus-{datastore}.jar({datastore} 是 ‘rdbms’、’mongodb’、’cassandra’ 等):这为 JAR 所针对的特定类型的数据存储提供了持久性。

  • datanucleus-jdo-query.jar :它提供了一个注释处理器,JDO 类型查询机制使用它来生成运行时使用的 Q 类。

可以使用各种附加 JAR,为附加(非标准)类型或特性(例如第三方缓存产品)提供支持。

DataNucleus jar 使用插件机制,因此它们每个都有一个文件 plugin.xml,用于定义每个 jar 的功能。 尝试“合并”DataNucleus jars(不合并plugin.xml 和MANIFEST.MF)可能会导致问题,建议人们不要这样做,或者如果他们真的想使用类似one-jar 的东西。

JDO教程

基本介绍

根据相关项目的开发过程,应用程序可以通过多种途径启用 JDO。 例如,该项目可以使用 Eclipse 作为开发类的 IDE。 在这种情况下,项目通常会使用 DataNucleus Eclipse 插件。 或者,项目可以使用 Ant、Maven 或其他一些构建工具。 在这种情况下,本教程应用作在应用程序中使用 DataNucleus 的指导方法。 JDO 过程非常简单。

  • 第0步:下载 DataNucleus AccessPlatform

  • 第 1 步:使用元数据定义其持久性定义。

  • 第 2 步:定义“持久性单元”

  • 第 3 步:编译您的类,并对它们进行检测(使用 DataNucleus 增强器)。

  • 第 4 步:编写代码以在 DAO 层中保留对象。

  • 第 5 步:运行您的应用程序。

我们将通过 2 个可选步骤更进一步,展示如何控制生成的模式,以及如何为类生成模式。

  • 第 6 步:控制架构

  • 第 7 步:生成要持久化您的类的数据库表

本教程将指导您完成此操作。 您可以从 SourceForge(名为“datanucleus-samples-jdo-tutorial-*”的文件之一)获取本教程中引用的代码。

第0步

您可以通过多种方式下载 DataNucleus,但最简单的方法是下载适合您的数据存储的分发 zip。 您可以从 SourceForge DataNucleus 下载页面执行此操作。 当你打开压缩包时,你会在 lib 目录中找到 DataNucleus jars,在 deps 目录中找到依赖 jars。

第1步,获取您的模型类并标记哪些是持久的

对于我们的教程,假设我们有以下代表待售产品商店的类。

public class Inventory
{
    String name = null;
    Set<Product> products = new HashSet<>();

    public Inventory(String name)
    {
        this.name = name;
    }

    public Set<Product> getProducts() {return products;}
}
public class Product
{
    long id;
    String name = null;
    String description = null;
    double price = 0.0;

    public Product(String name, String desc, double price)
    {
        this.name = name;
        this.description = desc;
        this.price = price;
    }
}
public class Book extends Product
{
    String author=null;
    String isbn=null;
    String publisher=null;

    public Book(String name, String desc, double price, String author, String isbn, String publisher)
    {
        super(name,desc,price);
        this.author = author;
        this.isbn = isbn;
        this.publisher = publisher;
    }
}

所以我们有一个关系(库存有一组产品)和继承(产品书)。 现在我们需要能够持久化所有这些类型的对象,因此我们需要为它们定义持久性。 在决定如何持久化一个类型的对象时,你可以定义很多东西,但基本部分是

  • 将该类标记为 PersistenceCapable,以便它对持久性机制可见

  • 确定哪些字段表示对象的身份(如果没有字段满足此要求,则使用 datastore-identity)。

所以这就是我们现在要做的。 请注意,我们可以使用 XML 元数据、注释或通过 JDO API 来定义持久性。 在本教程中,我们将使用注释。

@PersistenceCapable
public class Inventory
{
    @PrimaryKey
    String name = null;

    ...
}
@PersistenceCapable
public class Product
{
    @PrimaryKey
    @Persistent(valueStrategy=IdGeneratorStrategy.INCREMENT)
    long id;

    ...
}
@PersistenceCapable
public class Book extends Product
{
    ...
}

请注意,我们用@PersistenceCapable 标记每个可以持久化的类,用@PrimaryKey 标记它们的主键字段。 此外,我们为 Product 字段 id 定义了一个 valueStrategy,以便自动生成其值。 在本教程中,我们使用应用程序标识,这意味着这些类的所有对象都将具有由主键字段定义的标识。 在设计系统持久性时,您可以在数据存储标识应用程序标识中阅读更多内容。

第2步,定义持久化单元

编写您自己的要持久化的类是起点,但您现在需要定义这些类的哪些对象实际上是持久化的。 您可以通过 CLASSPATH 根目录下的文件 META-INF/persistence.xml 执行此操作。 像这样

<?xml version="1.0" encoding="UTF-8" ?>
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
        http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd" version="2.1">

    <!-- JDO tutorial "unit" -->
    <persistence-unit name="Tutorial">
        <class>org.datanucleus.samples.jdo.tutorial.Inventory</class>
        <class>org.datanucleus.samples.jdo.tutorial.Product</class>
        <class>org.datanucleus.samples.jdo.tutorial.Book</class>
        <exclude-unlisted-classes/>
        <properties>
            <!-- Properties for runtime configuration will be added here later, see below -->
        </properties>
    </persistence-unit>
</persistence>

请注意,您同样可以使用属性文件来定义 JDO 的持久性,但在本教程中,为了方便起见,我们使用了 persistence.xml。

第3步,增强你的类

DataNucleus JDO 依赖于您想要持久实现 Persistable 的类。 您可以手动编写类来执行此操作,但这会很费力。 或者,您可以使用后处理步骤进行编译,以“增强”已编译的类,添加必要的额外方法以使它们具有持久性。 有几种方法可以做到这一点,最显着的是在编译后或运行时。 我们在本教程中使用编译后步骤。 DataNucleus JDO 提供了自己的字节码增强器,用于检测/增强您的类(在 datanucleus-core.jar 中),这包含在 DataNucleus AccessPlatform zip 文件先决条件中。

要了解如何调用增强器,您需要可视化各种源文件和 jdo 文件的存储位置

src/main/java/org/datanucleus/samples/jdo/tutorial/Book.java
src/main/java/org/datanucleus/samples/jdo/tutorial/Inventory.java
src/main/java/org/datanucleus/samples/jdo/tutorial/Product.java
src/main/resources/META-INF/persistence.xml

target/classes/org/datanucleus/samples/jdo/tutorial/Book.class
target/classes/org/datanucleus/samples/jdo/tutorial/Inventory.class
target/classes/org/datanucleus/samples/jdo/tutorial/Product.class

[when using Ant]
lib/javax.jdo.jar
lib/datanucleus-core.jar
lib/datanucleus-api-jdo.jar

首先要做的是编译域/模型类。 您可以按照您希望的任何方式执行此操作,但可下载的 JAR 提供了一个 Ant 任务和一个 Maven 项目来为您执行此操作。

Using Ant :
ant compile

Using Maven :
mvn compile

要使用 DataNucleus Enhancer 增强类,您需要从项目的根目录调用类似这样的命令。

# Using Ant :
ant enhance

# Using Maven : (this is usually done automatically after the "compile" goal)
mvn datanucleus:enhance

# Manually on Linux/Unix :
java -cp target/classes:lib/datanucleus-core.jar:lib/datanucleus-api-jdo.jar:lib/javax.jdo.jar
     org.datanucleus.enhancer.DataNucleusEnhancer -pu Tutorial

# Manually on Windows :
java -cp target\classes;lib\datanucleus-core.jar;lib\datanucleus-api-jdo.jar;lib\javax.jdo.jar
     org.datanucleus.enhancer.DataNucleusEnhancer -pu Tutorial

# [Command shown on many lines to aid reading - should be on single line]

此命令增强了具有 @PersistenceCapable 注释的 .class 文件。 如果您不小心省略了这一步,在运行应用程序并尝试持久化对象时,您将抛出 ClassNotPersistenceCapableException。 增强器指南中更详细地记录了增强器的使用。 此步骤的输出是一组表示 PersistenceCapable 类的类文件。

第4步,编写代码来持久化你的类的对象

编写您自己的要持久化的类是起点,但您现在需要定义这些类的哪些对象实际上是持久化的,以及何时被持久化。 与 JDO 持久性框架的交互是通过 PersistenceManager 执行的。 这提供了用于持久化对象、移除对象、查询持久化对象等的方法。本节给出了应用程序中遇到的典型场景的示例。

第一步是获取对 PersistenceManager 的访问权限,您可以按如下方式进行

PersistenceManagerFactory pmf = JDOHelper.getPersistenceManagerFactory("Tutorial");
PersistenceManager pm = pmf.getPersistenceManager();

现在应用程序有一个 PersistenceManager 它可以持久化对象。 这是按如下方式执行的

Transaction tx=pm.currentTransaction();
try
{
    tx.begin();
    Inventory inv = new Inventory("My Inventory");
    Product product = new Product("Sony Discman", "A standard discman from Sony", 49.99);
    inv.getProducts().add(product);
    pm.makePersistent(inv);
    tx.commit();
}
finally
{
    if (tx.isActive())
    {
        tx.rollback();
    }
    pm.close();
}

请注意以下事项

我们已经持久化了Inventory,但既然它引用了Product,那么它也被持久化了。

最后一步很重要,整理与数据存储的任何连接,并关闭 PersistenceManager

如果你想从持久存储中检索一个对象,像这样的东西将提供你所需要的。 这使用“查询”,并检索价格低于 150.00 的所有 Product 对象,按升序对它们进行排序。

Transaction tx = pm.currentTransaction();
try
{
    tx.begin();

    Query q = pm.newQuery("SELECT FROM " + Product.class.getName() + " WHERE price < 150.00 ORDER BY price ASC");
    List<Product> products = q.executeList();
    Iterator<Product> iter = products.iterator();
    while (iter.hasNext())
    {
        Product p = iter.next();

        ... (use the retrieved objects)
    }

    tx.commit();
}
finally
{
    if (tx.isActive())
    {
        tx.rollback();
    }

    pm.close();
}

如果你想从持久性中删除一个对象,你会执行类似的操作

Transaction tx = pm.currentTransaction();
try
{
    tx.begin();

    ... (retrieval of objects etc)

    pm.deletePersistent(product);

    tx.commit();
}
finally
{
    if (tx.isActive())
    {
        tx.rollback();
    }

    pm.close();
}

显然,您可以对对象执行大范围的操作。 我们不能希望在这里展示所有这些。 任何好的 JDO 书籍都会提供许多示例。

第5步,运行你的应用

要运行启用 JDO 的应用程序,需要在 Java CLASSPATH 中提供一些可用的东西,这些是

  • 用于 PersistenceManagerFactory 创建的任何 persistence.xml 文件

  • 持久化类的任何 JDO XML 元数据文件(本例中未使用)

  • 访问数据存储所需的任何数据存储驱动程序类(例如,用于 RDBMS 的 JDBC 驱动程序、用于 Cassandra 的 Datastax 驱动程序等)

  • javax.jdo.jar(定义 JDO API 接口)

  • datanucleus-core.jar、datanucleus-api-jdo.jar 和 datanucleus-{datastore}.jar(对于您正在使用的数据存储,例如使用 RDBMS 时的 datanucleus-rdbms.jar)

在我们的例子中,我们需要使用定义数据存储的持久性属性(我们之前展示的文件的属性部分)更新persistence.xml。

首先是 RDBMS(在本例中为 H2)

<properties>
    <property name="javax.jdo.option.ConnectionURL" value="jdbc:h2:mem:nucleus1"/>
    <property name="javax.jdo.option.ConnectionUserName" value="sa"/>
    <property name="javax.jdo.option.ConnectionPassword" value=""/>
    <property name="datanucleus.schema.autoCreateAll" value="true"/>
</properties>

如果我们想坚持使用 Cassandra 那么这将是

<properties>
    <property name="javax.jdo.option.ConnectionURL" value="cassandra:"/>
    <property name="javax.jdo.mapping.Schema" value="schema1"/>
    <property name="datanucleus.schema.autoCreateAll" value="true"/>
</properties>

或者对于 MongoDB 那么这将是

<properties>
    <property name="javax.jdo.option.ConnectionURL" value="mongodb:/nucleus1"/>
    <property name="datanucleus.schema.autoCreateAll" value="true"/>
</properties>

等等。 如果您查看可下载示例项目的persistence.xml,它会根据需要列出各种不同的数据存储以取消注释

您可以通过指定日志配置属性来访问 DataNucleus 日志文件,并且来自 DataNucleus 的任何消息都将以正常方式输出。 DataNucleus 日志是一种非常强大的查找问题的方法,因为它可以列出实际发送到数据存储的所有 SQL 以及持久性过程的许多其他部分。

有关可用于配置持久性的许多其他属性,请参阅 JDO 持久性指南

# Using Ant (you need the included "persistence.xml" to specify your database)
ant run

# Using Maven:
mvn exec:java

# Manually on Linux/Unix :
java -cp lib/javax.jdo.jar:lib/datanucleus-core.jar:lib/datanucleus-{datastore}.jar:
         lib/datanucleus-api-jdo.jar:lib/{jdbc-driver}.jar:target/classes/:.
             org.datanucleus.samples.jdo.tutorial.Main

# Manually on Windows :
java -cp lib\javax.jdo.jar;lib\datanucleus-core.jar;lib\datanucleus-{datastore}.jar;
         lib\datanucleus-api-jdo.jar;lib\{jdbc-driver}.jar;target\classes\;.
             org.datanucleus.samples.jdo.tutorial.Main

Output :

DataNucleus Tutorial
=============
Persisting products
Product and Book have been persisted

Retrieving Extent for Products
>  Product : Sony Discman [A standard discman from Sony]
>  Book : JRR Tolkien - Lord of the Rings by Tolkien

Executing Query for Products with price below 150.00
>  Book : JRR Tolkien - Lord of the Rings by Tolkien

Deleting all products from persistence
Deleted 2 products

End of Tutorial

第6步,控制schema

我们还没有考虑控制为这些类生成的模式。 现在让我们通过为模式定义 XML 元数据来更加关注这部分。 现在我们将定义一个 ORM XML 元数据文件来将类映射到模式。 使用 JDO,您有多种选择,即此 XML 元数据文件在文件结构中的放置位置,以及它们是引用单个类还是包中的多个类。

首先对于 RDBMS(在本例中为 H2),我们定义了一个包含两个类的 ORM 映射的文件 package-h2.orm。

<?xml version="1.0"?>
<!DOCTYPE orm SYSTEM "file:/javax/jdo/orm.dtd">
<orm>
    <package name="org.datanucleus.samples.jdo.tutorial">
        <class name="Inventory" table="INVENTORIES">
            <field name="name">
                <column name="INVENTORY_NAME" length="100"/>
            </field>
            <field name="products" table="INVENTORY_PRODUCTS">
                <join/>
            </field>
        </class>

        <class name="Product" table="PRODUCTS">
            <inheritance strategy="new-table"/>
            <field name="id">
                <column name="PRODUCT_ID"/>
            </field>
            <field name="name">
                <column name="PRODUCT_NAME" length="100"/>
            </field>
        </class>

        <class name="Book" table="BOOKS">
            <inheritance strategy="new-table"/>
            <field name="author">
                <column length="40"/>
            </field>
            <field name="isbn">
                <column length="20" jdbc-type="CHAR"/>
            </field>
            <field name="publisher">
                <column length="40"/>
            </field>
        </class>
    </package>
</orm>

如果我们一直坚持使用 Cassandra,那么我们将定义一个包含两个类的 ORM 映射的文件 package-cassandra.orm。

<?xml version="1.0"?>
<!DOCTYPE orm SYSTEM "file:/javax/jdo/orm.dtd">
<orm>
    <package name="org.datanucleus.samples.jdo.tutorial">
        <class name="Inventory" table="Inventories">
            <field name="name">
                <column name="Name" length="100"/>
            </field>
            <field name="products"/>
        </class>

        <class name="Product" table="Products">
            <inheritance strategy="complete-table"/>
            <field name="id">
                <column name="Id"/>
            </field>
            <field name="name">
                <column name="Name"/>
            </field>
            <field name="description">
                <column name="Description"/>
            </field>
            <field name="price">
                <column name="Price"/>
            </field>
        </class>

        <class name="Book" table="Books">
            <inheritance strategy="complete-table"/>
            <field name="Product.id">
                <column name="Id"/>
            </field>
            <field name="author">
                <column name="Author"/>
            </field>
            <field name="isbn">
                <column name="ISBN"/>
            </field>
            <field name="publisher">
                <column name="Publisher"/>
            </field>
        </class>
    </package>
</orm>

同样,可下载的示例包含许多不同数据存储的 package-{datastore}.orm 文件

生成域类所需的任何架构

此步骤是可选的,具体取决于您是否有现有的数据库架构。 如果您还没有,此时您可以使用 SchemaTool 生成将保存这些域对象的表。 DataNucleus SchemaTool 是一个命令行实用程序(它可以从 Maven/Ant 以类似于调用 Enhancer 的方式调用)。

首先要做的是向persistence.xml 添加一个额外的属性来指定使用哪个数据库映射(以便它可以定位ORM XML 元数据文件)。

所以对于 H2,属性部分变为

<properties>
    <property name="javax.jdo.option.ConnectionURL" value="jdbc:h2:mem:nucleus1"/>
    <property name="javax.jdo.option.ConnectionUserName" value="sa"/>
    <property name="javax.jdo.option.ConnectionPassword" value=""/>
    <property name="javax.jdo.option.Mapping" value="h2"/>
    <property name="datanucleus.schema.autoCreateAll" value="true"/>
</properties>

同样对于 Cassandra 来说,它会是

<properties>
    <property name="javax.jdo.option.ConnectionURL" value="cassandra:"/>
    <property name="javax.jdo.mapping.Schema" value="schema1"/>
    <property name="datanucleus.schema.autoCreateAll" value="true"/>
    <property name="javax.jdo.option.Mapping" value="cassandra"/>
</properties>

等等。

现在我们需要运行 DataNucleus SchemaTool。 对于我们上面的例子,你会做这样的事情

# Using Ant :
ant createschema

# Using Maven :
mvn datanucleus:schema-create

# Manually on Linux/Unix :
java -cp target/classes:lib/datanucleus-core.jar:lib/datanucleus-{datastore}.jar:lib/datanucleus-javax.jdo.jar:lib/javax.jdo.jar:lib/{datastore_driver.jar}
     org.datanucleus.store.schema.SchemaTool -create -pu Tutorial

# Manually on Windows :
java -cp target\classes;lib\datanucleus-core.jar;lib\datanucleus-{datastore}.jar;lib\datanucleus-api-jdo.jar;lib\javax.jdo.jar;lib\{datastore_driver.jar}
     org.datanucleus.store.schema.SchemaTool -create -pu Tutorial

# [Command shown on many lines to aid reading. Should be on single line]

这将为 JDO 元数据文件中定义的类生成所需的表、索引和外键。 在这种情况下生成的模式(用于 RDBMS)将如下所示:

DataNucleus JDO基础入门

5 1 投票
文章评分

本文为从大数据到人工智能博主「xiaozhch5」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://lrting.top/backend/2768/

(0)
上一篇 2021-12-14 01:22
下一篇 2021-12-16 01:38

相关推荐

订阅评论
提醒
guest
0 评论
内联反馈
查看所有评论
0
希望看到您的想法,请您发表评论x