文档

Java™ 教程
隐藏目录
使用自定义类型映射
路径: JDBC 数据库访问
课程: JDBC 基础知识

使用自定义类型映射

注意:MySQL当前不支持用户定义类型。MySQL和Java DB当前不支持结构化类型或DISTINCT SQL数据类型。没有可用的JDBC教程示例来演示本节中描述的功能。

随着业务的繁荣,The Coffee Break的业主经常增加新店铺并对数据库进行更改。业主决定为结构化类型ADDRESS使用自定义映射。这使得业主可以对映射ADDRESS类型的Java类进行更改。该Java类将为ADDRESS的每个属性设置一个字段。类的名称和字段的名称可以是任何有效的Java标识符。

以下主题涵盖:

实现SQLData

自定义映射所需的第一步是创建一个实现SQLData接口的类。

结构化类型ADDRESS的SQL定义如下:

  CREATE TYPE ADDRESS
  (
    NUM INTEGER,
    STREET VARCHAR(40),
    CITY VARCHAR(40),
    STATE CHAR(2),
    ZIP CHAR(5)
  );

实现ADDRESS类型的自定义映射的类可能如下所示:

public class Address implements SQLData {
    public int num;
    public String street;
    public String city;
    public String state;
    public String zip;
    private String sql_type;
    
    public String getSQLTypeName() {
        return sql_type;
    }

    public void readSQL(SQLInput stream, String type)
        throws SQLException {
        sql_type = type;
        num = stream.readInt();
        street = stream.readString();
        city = stream.readString();
        state = stream.readString();
        zip = stream.readString();
    }

    public void writeSQL(SQLOutput stream)
        throws SQLException {
        stream.writeInt(num);
        stream.writeString(street);
        stream.writeString(city);
        stream.writeString(state);
        stream.writeString(zip);
    }
}

使用连接的类型映射

编写实现SQLData接口的类后,设置自定义映射的另一件事是在类型映射中添加条目。对于本示例,这意味着输入ADDRESS类型的完全限定SQL名称和类AddressClass对象。类型映射是java.util.Map接口的实例,与每个新建的连接关联在一起,因此您可以使用它。假设con是活动连接,以下代码片段向与con关联的类型映射中添加了UDTADDRESS的条目。

java.util.Map map = con.getTypeMap();
map.put("SchemaName.ADDRESS", Class.forName("Address"));
con.setTypeMap(map);

每当调用getObject方法检索ADDRESS类型的实例时,驱动程序将检查与连接关联的类型映射,并查看是否存在ADDRESS的条目。驱动程序将注意到Address类的Class对象,创建一个实例,并在后台执行许多其他操作,将ADDRESS映射到Address。您无需做任何事情,只需生成映射的类并在类型映射中进行条目输入,以让驱动程序知道存在自定义映射。驱动程序将完成所有其他操作。

对于存储具有自定义映射的结构化类型,情况类似。当调用setObject方法时,驱动程序将检查要设置的值是否是实现SQLData接口的类的实例。如果是(表示存在自定义映射),驱动程序将使用自定义映射将该值转换为其SQL对应项,然后将其返回到数据库。同样,驱动程序在后台执行自定义映射;您只需向setObject方法提供具有自定义映射的参数即可。稍后的本节中将给出一个示例。

看一下使用标准映射(Struct对象)和使用Java编程语言中的自定义映射(类)之间的区别。以下代码片段显示了对Struct对象的标准映射,当连接的类型映射中没有条目时,驱动程序使用此映射。

ResultSet rs = stmt.executeQuery(
    "SELECT LOCATION " +
    "WHERE STORE_NO = 100003");
rs.next();
Struct address = (Struct)rs.getObject("LOCATION");

变量address包含以下属性值:4344"First_Street""Verona""CA""94545"

以下代码片段显示了连接的类型映射中存在结构化类型ADDRESS时会发生的情况。请记住,列LOCATION存储了ADDRESS类型的值。

ResultSet rs = stmt.executeQuery(
    "SELECT LOCATION " +
    "WHERE STORE_NO = 100003");
rs.next();
Address store_3 = (Address)rs.getObject("LOCATION");

现在,变量store_3Address类的一个实例,每个属性值都是Address的字段的当前值。请注意,在将getObject方法检索到的对象转换为Address对象之前,必须记得进行转换。还要注意,store_3必须是一个Address对象。

将使用Struct对象与使用Address类的实例进行比较。假设商店搬到了附近镇的更好位置,因此您必须更新数据库。通过自定义映射,重置store_3的字段,如下代码片段所示:

ResultSet rs = stmt.executeQuery(
    "SELECT LOCATION " +
    "WHERE STORE_NO = 100003");
rs.next();
Address store_3 = (Address)rs.getObject("LOCATION");
store_3.num = 1800;
store_3.street = "Artsy_Alley";
store_3.city = "Arden";
store_3.state = "CA";
store_3.zip = "94546";
PreparedStatement pstmt = con.prepareStatement(
    "UPDATE STORES " +
    "SET LOCATION = ? " +
    "WHERE STORE_NO = 100003");
pstmt.setObject(1, store_3);
pstmt.executeUpdate();

LOCATION列中的值是ADDRESS类型的实例。驱动程序检查连接的类型映射,并看到有一个将ADDRESSAddress类链接起来的条目,并因此使用Address中指定的自定义映射。当代码调用setObject方法,并将变量store_3作为第二个参数时,驱动程序检查并看到store_3表示Address类的实例,该类实现了结构类型ADDRESSSQLData接口,并自动使用自定义映射。

如果没有为ADDRESS自定义映射,更新将如下所示:

PreparedStatement pstmt = con.prepareStatement(
    "UPDATE STORES " +
    "SET LOCATION.NUM = 1800, " +
    "LOCATION.STREET = 'Artsy_Alley', " + 
    "LOCATION.CITY = 'Arden', " +
    "LOCATION.STATE = 'CA', " +
    "LOCATION.ZIP = '94546' " +
    "WHERE STORE_NO = 100003");
pstmt.executeUpdate;

使用自定义类型映射

到目前为止,您只使用了与连接关联的类型映射进行自定义映射。通常,这是大多数程序员将使用的唯一类型映射。然而,也可以创建一个类型映射并将其传递给某些方法,以便驱动程序将使用该类型映射而不是与连接关联的类型映射。这允许同一个用户定义类型(UDT)有两个不同的映射。实际上,可以为同一个UDT拥有多个自定义映射,只要每个映射都使用实现SQLData接口的类和类型映射中的条目设置。如果在可以接受类型映射的方法中不传递类型映射,则驱动程序默认使用与连接关联的类型映射。

除了与连接关联的类型映射之外,几乎没有什么情况需要使用其他类型映射。如果多个程序员在一个JDBC应用程序上工作并将他们的组件放在一起,并且正在使用同一个连接,可能需要向方法提供类型映射。如果两个或更多程序员为相同的SQL UDT创建了自定义映射,则每个人都需要提供自己的类型映射,从而覆盖连接的类型映射。


上一页: 使用结构化对象
下一页: 使用数据链接对象