udt java_Java DB中的Java用户定义类型(UDT)

udt java

Java DB是基于Java编程语言和SQL的关系数据库管理系统。 这是Apache软件基金会的开源Derby项目的Oracle版本。 Java SE 7 SDK中包含Java DB。

用户定义类型(UDT)是Java类,其实例(对象)存储在数据库表列中。 UDT定义为列数据类型,UDT实例存储为列值。 可以在Java DB数据库中创建并使用UDT。

以下是该帖子的内容:

  1. 用户定义类型(UDT)
  2. 创建和使用UDT
  3. 设计UDT –考虑更新UDT对现有数据的影响
  4. 范例程式码
  5. 注释与参考

1.用户定义类型(UDT)

UDT在数据库中定义数据类型。 UDT是具有公共访问修饰符的Java类。 此类实现java.io.Serializable接口。 该类必须在引用该类的数据库应用程序(或工具)的类路径上可见。

UDT类用于定义表或视图列的数据类型-用户定义的数据类型。 UDT数据是UDT类的实例(Java对象)。 并存储为列数据。 UDT也可以在存储过程和函数(在Java DB中,它们是基于Java的)中称为数据类型。

  • UDT可以具有子类型。 并且可以将子类型数据填充为主类型,即,可以将UDT类的子类实例填充为UDT值。 例如:(a)Java类Type1和在数据库中定义为dbtype1的UDT,以及(b)Java类Subtype1Type1的子类,并且(c) dbtype1表列也可以用的实例填充Subtype1 (除了Type1的实例之外)。
  • 无法对UDT进行索引,排序或比较; 并且不能与在SQL表达式中分组或聚合的运算符一起使用(例如=,LIKE,DISTINCT,GROUP…)。

2.创建和使用UDT

  • 2.1。 创建UDT
  • 2.2。使用UDT

2.1。创建一个UDT

创建一个Java类并在数据库中定义UDT。创建一个Java类,例如TestType1.java (请参见代码: 4.1 TestType1.java ),以用作数据库中的UDT。 编译源代码。

SQL CREATE TYPE语句在数据库中创建UDT。 语法为:

CREATE TYPE udtTypeName
EXTERNAL NAME javaClassName
LANGUAGE JAVA

该命令以默认或指定的架构创建UDT,其中:

  • udtTypeName是数据库中UDT的名称标识符。
  • javaClassName是Java类的标准名称。

例如,使用ij工具在Java DB数据库中创建UDT( ij是Java DB附带的命令行工具。ij是用于在Java DB数据库上运行交互式查询的JDBC工具。):

ij> CONNECT 'jdbc:derby:testDB';
ij> CREATE TYPE type1 EXTERNAL NAME 'TestType1' LANGUAGE JAVA;

在上面的示例中, testDB是现有数据库。 在testDB数据库中创建了名称为type1的UDT。

注意

Java类文件必须位于要从ij工具引用的类路径中。

2.1.1。验证,删除和更新UDT

可以使用以下SQL命令验证创建的UDT:

ij> SELECT alias, javaclassname FROM SYS.SYSALIASES WHERE aliastype='A';

要从数据库中删除UDT,请使用DROP TYPE SQL命令。 以下是一个示例:

ij> DROP TYPE udtTypeName RESTRICT;

在上面的示例中, udtTypeName是数据库中定义的UDT名称。

如果数据库对象正在使用(或引用)UDT,则不能删除UDT。 例如,(a)如果表列的类型为UDT,除非删除相应的表列,否则不能删除该UDT,或者(b)如果数据库函数引用的是UDT的类(实例),则不能删除UDT。除非已修改函数,否则不要引用该UDT类。

要使用更新后的Java代码更新UDT,请(重新)编译UDT类。 这会影响UDT类型的对象。 这也可能会影响存储在UDT对象中的数据,具体取决于在应用程序中定义和使用UDT的方式。 请参阅主题: 3.设计UDT –考虑更新UDT对现有数据的影响

2.2。使用UDT

使用UDT创建数据库对象并处理UDT数据(插入,更新,删除和查询)。 UDT数据可以与SQL交互使用,也可以在Java程序中与JDBC API一起在数据库中使用。

2.2.1。 互动式SQL

下面介绍创建UDT类型的数据库表列,插入数据和查询插入的数据。

  • (i)使用UDT作为列类型创建数据库表。

    例如:

    CREATE TABLE test_table1 (
    	id INT,
    	type1col type1, // column with UDT
    )
  • (ii)将数据插入表中。

    使用定制的数据库函数将数据插入到用UDT定义的表列中。有关创建定制函数以将UDT数据插入到表列中的详细信息,请参阅4.2。 Example_Fn1 –函数

    示例函数Example_Fn1具有签名Example_Fn1(字符串输入),并返回TestType1的实例(其中TestType1是表示UDT的Java类)。

    ij> INSERT INTO test_table1(id, type1col) VALUES(1, Example_Fn1("udt value 1"));

    上面SQL命令在表中插入一行,其中带有TestType1 Java对象的UDT列值。 函数Example_Fn1使用String输入参数调用TestType1类的构造函数来构建对象; 并且该对象存储在表列中。

  • (iii)查询插入的数据。

    可以使用自定义函数从UDT列获取数据。 在以下示例中,UDT类TestType1的重写的Object类的toString()方法返回存储的实例的字符串值。

    ij> SELECT * FROM test_table1;
    ID         | TYPE1COL
    -------------------------
    1          | udt value 1
2.2.2。 使用JDBC API

java.sql包中定义的PreparedStatementResultSet接口分别用于插入和获取数据库UDT数据。

  • PreparedStatementsetObject()方法用于将UDT数据作为对象存储在UDT表列中。 方法setObject(int parameterIndex,Object obj)使用给定的对象设置指定参数的值。
  • ResultSet的getObject()方法用于从UDT表列中检索存储的UDT数据。 方法getObject(int columnIndex)获取此ResultSet对象的当前行中指定列的值。 返回的数据是一个对象。

以下Java代码段显示了用法:

// insert data into a table
int idValue = 2;
TestType1 obj = new TestType1("udt value 2");
PreparedStatement ps = conn.prepareStatement("INSERT INTO test_table1 VALUES (?, ?)";
ps.setInt(1, idValue); // where 1 is the parameter index
ps.setObject(2, obj); // UDT data
ps.executeUpdate();
...
// retrieve data from a table
PreparedStatement ps = conn.prepareStatement("SELECT * FROM test_table1");
ResultSet rs = ps.executeQuery();
while (rs.next()) {
int idValue = rs.getInt(1);
    TestType1 testType1 = (TestType1) rs.getObject(2); 
// where 2 is the column index in ResultSet object
    ...
}

注意

  1. 在上面的代码中, conn是数据库Connection对象。
  2. UDT Java类文件必须位于类路径中,才能从JDBC代码进行引用。
  3. 设计UDT –考虑更新UDT对现有数据的影响

UDT用于存储数据。 该UDT(和数据)可能会在应用程序的整个生命周期中发生变化(即演变)。 设计UDT时必须考虑到这一点。

另外,请注意,UDT类始终实现Serializable接口。 必须考虑数据序列化和各种版本的UDT数据对象的影响。 在简单的情况下,仅编译更改的UDT类代码就足够了。

有两种设计和使用UDT的方法。

  • UDT类实现了可序列化,并且随着UDT数据的发展,应用程序(带有UDT)使用数据转换应用程序。
  • UDT类实现Externalizable (而不是Serializable ),并在UDT类中使用数据转换功能。 一个带有UDT类代码的示例如下所示。

关于可外部化

UDT类必须实现Serializable接口。 和java.io.Externalizable扩展Serializable

实现此接口后,只有可外部化实例的类的身份(而不是状态)才写入序列化流中。 该类负责保存和恢复其实例的内容(状态)。

必须实现两种方法:

  • readExternal(ObjectInput in):对象实现readExternal()方法以恢复其内容。
  • writeExternal(ObjectOutput out):对象实现writeExternal()方法以保存其内容。

3.1 UDT类实现Serializable

UDT类实现了Serializable,并且随着UDT数据的发展,应用程序(使用UDT)使用数据转换应用程序-以下是概述步骤:

  • UDT实现Serializable
  • 创建并使用带有初始版本的UDT。
  • 在使用下一个版本更新UDT之前,请保存(存储)先前版本的数据。
  • 创建下一个版本的UDT(更新较早的版本)。
  • 将初始版本数据转换为当前更新的版本数据。

请注意,在这种情况下,所有以前的版本数据一次都转换为当前(新)版本。

3.2 UDT类实现可外部化

UDT类实现Externalizable (而不是Serializable )并在其中使用数据转换功能-以下是概述步骤:

  • UDT实现Externalizable
  • 创建并使用带有初始版本的UDT。
  • 在使用下一个版本更新UDT之前,无需执行任何操作。
  • 使用内置的数据转换功能,创建下一个版本的UDT(更新较早的版本)。

在这种情况下,每当查询或更新数据时,以前的版本数据就会转换为当前(新)版本。 版本信息包含在UDT类中。

以下是有关UDT类的详细信息和代码的示例。

  1. 创建具有版本1的UDT类: Testtype2.java (请参见以下代码: 4.3Testtype2.java(版本1)
  2. 编译
  3. 在数据库中创建UDT: type2
  4. 创建带有UDT列的表: test_table3
  5. 将数据插入UDT列
  6. 查询UDT数据
  7. 使用版本2更新UDT类: Testtype2.java (请参见代码: 4.3 Testtype2.java(版本2)
  8. 编译
  9. 将数据(版本2)插入UDT列
  10. 查询UDT数据–版本1和版本2数据

注意

本主题中的示例未显示用于插入和查询UDT数据SQL命令和函数的详细信息或代码。 这些可能类似于本文前面显示的示例。

4.示例代码

  • 4.1。 TestType1.java
  • 4.2。 Example_Fn1 –函数
  • 4.3.Testtype2.java(版本1)
  • 4.4.Testtype2.java(版本2)

4.1.TestType1.java

public class TestType1
        implements java.io.Serializable {
    private String value = "DEFAULT";
    public TestType1() {
    }
    public TestType1(String s) {
        value = s;
    }
    @Override
    public String toString() {
        return value;
    }
} // class

4.2.Example_Fn1 –功能

这是将数据插入UDT列的功能,如2.2中的示例所示 使用UDT

  • (i)使用具有函数功能的公共静态方法创建Java类。
  • (ii)使用CREATE FUNCTION命令在数据库中创建函数。

以下是该函数和CREATE FUNCTION命令的Java类。 使用ij工具以交互方式编译Java类并运行CREATE FUNCTION命令。

public class FunctionClass {
    public static TestType1 FnMethod1(String s) {
        return new TestType1(s);
    }
}
CREATE FUNCTION Example_Fn1(VARCHAR(25))
RETURNS type1
LANGUAGE JAVA
PARAMETER STYLE JAVA
NO SQL
EXTERNAL NAME 'FunctionClass.FnMethod1';

注意

ij使用SQL命令SHOW FUNCTIONS和DROP FUNCTION来验证创建的函数并将其从数据库中删除。

4.3.Testtype2.java(版本1)

import java.io.*;
public class Testtype2
        implements Externalizable {
    private static final long serialVersionUID = 1L;
    private static final int FIRST_VERSION = 1; // initial version id
    private String value = "DEFAULT";
    public Testtype2() {
    }
    public Testtype2(String s) {
        value = s;
    }
    @Override
    public void writeExternal(ObjectOutput out)
            throws IOException {
        // first write the version id
out.writeInt(FIRST_VERSION);
        // next write the state
out.writeObject(value);
    }
    @Override
    public void readExternal(ObjectInput in)
            throws IOException, ClassNotFoundException {
        // read the version id
int version = in.readInt();
        if (version < FIRST_VERSION) {	
            throw new IOException("Corrupt data stream (no such version).");
        }
        if (version > FIRST_VERSION) {
            throw new IOException("Can't deserialize from the future versions.");
        }
        // read object (state)
        value = (String) in.readObject() + "_V" + version;
    } // readExternal()
    @Override
    public String toString() {
        return value;
    }
} // version 1 class

4.4.Testtype2.java(版本2)

import java.io.*;
public class Testtype2
        implements Externalizable {
    private static final long serialVersionUID = 1L;
    private static final int FIRST_VERSION = 1; // initial version id
    private static final int NEW_VERSION = 2;
    private String value = "DEFAULT";
    private double newData;
    public Testtype2() {
    }
    public Testtype2(String s, double i) {
        value = s;
newData = i;
    }
    @Override
    public void writeExternal(ObjectOutput out)
            throws IOException {
        // first write the version id
out.writeInt(NEW_VERSION);
        // next write the state
out.writeObject(value);
out.writeDouble(newData);
    }
    @Override
    public void readExternal(ObjectInput in)
            throws IOException, ClassNotFoundException {
        if (version < FIRST_VERSION) {	
            throw new IOException("Corrupt data stream (no such version).");
        }
        if (version > NEW_VERSION) {
            throw new IOException("Can't deserialize from the future versions.");
        }
        // read object
        value = (String) in.readObject() + "_V" + version;
        // read new version's data
if (version == NEW_VERSION) {
newData = in.readDouble();
        }
        else { // if FIRST_VERSION
            // newData is its default value, 0
        }
    } // readExternal()
    @Override
    public String toString() {
        return value + ":" + newData;
    }
} // version 2 class

注意

  1. externalizablereadExternal()方法必须按与writeExternal()方法写入的相同顺序和相同类型读取值。
  2. 在上面的示例代码中, serialVersionUID变量是可选的。

5.注释和参考

  • Java Swing文本编辑器应用程序中的示例用法:GUI文本编辑器创建一个文本文档作为java.swing.text.PlainDocument类的实例。 使用内容创建的UDT Java类–例如PlainDocument实例,文档名称,创建日期等,并在应用程序中用于存储数据。
  • Oracle 10g数据库支持创建和使用基于Java的UDT。 这些被称为SQLJ类型。 表示UDT的Java类实现java.sql.SQLDataoracle.sql.ORAData接口,而不是java.io.Serializable 。 这些UDT是使用CREATE TYPE SQL语句创建的,并存储到服务器,并可以通过SQL访问。
  • 链接到Apache Derby>文档(10.8手册): http : //db.apache.org/derby/manuals/index.html

翻译自: https://www.javacodegeeks.com/2013/10/java-user-defined-types-udt-in-java-db.html

udt java

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值