繁体   English   中英

在JDBC中使用isWrapperFor和unwrap函数的正确方法是什么?

[英]What is the correct way to use of isWrapperFor and unwrap functions in JDBC?

我想知道验证isWrapperFor和在JDBC中解包函数的正确方法。 这里使用HIRAConnection和标准的Connection类。

HIRAConnection hiraCon1 = (HIRAConnection) ds.getConnection();
Connection conn = ds.getConnection();
if (hiraCon1 instanceof Wrapper) {
    // try to use java 6 unwrapping
    try {
        Wrapper w = conn;
        if (hiraCon1.isWrapperFor(Connection.class)) {
            hiraCon1 = conn.unwrap(HIRAConnection.class); 
            hiraCon1= hiraCon1.unwrap(HIRAConnection.class);
            hiraCon1= ds.unwrap(HIRAConnection.class);//returns SQLException   
        }
        if (hiraCon1.isWrapperFor(HIRAConnection.class)) {
            hiraCon1 = conn.unwrap(HIRAConnection.class);
            hiraCon1 = hiraCon1.unwrap(HIRAConnection.class);    
        }
        if (conn.isWrapperFor(com.hira.HIRAConnection.class)) {          
            hiraCon1 = conn.unwrap(com.hira.HIRAConnection.class);
        } 
        if (conn.isWrapperFor(Connection.class)) {          
            hiraCon1 = conn.unwrap(com.hira.HIRAConnection.class);
        } 
    } catch (Throwable t) {
        System.out.println("Failed to unwrap connection using java 6 facilities");
    }
}

在其javadoc中记录了使用java.sql.Wrapper的正确方法。

对于isWrapperFor(Class<?> iface)

如果此方法实现了接口参数,或者直接或间接地对该对象进行了包装,则返回true。 否则返回false。 如果这实现了接口,则返回true,否则返回true,否则返回包装对象上递归调用isWrapperFor的结果。 如果这没有实现接口并且不是包装器,则返回false。 unwrap相比,此方法应作为一种低成本操作来实现,以便调用者可以使用此方法来避免可能失败的昂贵的unwrap调用。 如果此方法返回true,则使用相同参数调用unwrap应该会成功。

参数
iface定义接口的类。
返回值
如果这实现了接口或直接或间接包装了这样做的对象,则为true。

对于unwrap(Class<T> iface)

返回一个实现给定接口的对象,以允许访问非标准方法或代理未公开的标准方法。 如果接收方实现了接口,那么结果就是接收方或该接收方的代理。 如果接收方是包装器,并且包装对象实现接口,则结果是包装对象或包装对象的代理。 否则,返回调用的结果unwrap的包装对象或该结果的代理递归。 如果接收方不是包装器,并且未实现该接口,则将引发SQLException

类型参数
T此Class对象建模的类的类型
参数
iface定义结果必须实现的接口的类。
返回值
实现接口的对象。 可能是实际实现对象的代理。
抛出
SQLException如果未找到实现该接口的对象

换句话说,您可以先使用wrapperFor检查包装程序是否可以解包到接口,然后可以使用unwrap真正解包到该接口。 请注意,该规范仅提及支持对接口进行拆包,因此实际上可能无法对具体类进行拆包。

是否起作用,取决于所使用的驱动程序(并非所有驱动程序都支持解包,或者可能没有对解包有用的东西),如果您使用的是连接池库,则很可能不允许您解包。 -例如-基础连接,因为这样做可以使您规避或打破连接池的某些限制和要求。

因此,使用包装的正确方法是:

Connection conn = ds.getConnection();
if (conn.isWrapperFor(HiraConnection.class)) {
    HIRAConnection hiraCon1 = conn.unwrap(HiraConnection.class);
    // use hiraCon1...
)

但是,如果HiraConnection是一个具体的类而不是一个接口,则可能不起作用。 而且展开通常也会导致代码变脆。 除非绝对必要,否则通常最好避免依赖于特定于驱动程序的接口。

有关您问题中代码的一些说明:

  • 如果您知道HIRAConnection hiraCon1 = (HIRAConnection) ds.getConnection(); 有效,那么您根本不需要拆包。
  • 检查hiraCon1 instanceof Wrapper是没有用的检查,因为如果HIRAConnection实现java.sql.Connection ,那么它将始终实现java.sql.Wrapper (否则,运行代码将为java.sql.Wrapper产生ClassNotFoundException ,这意味着您可以运行它在Java 5或更低版本上)。
  • 检查hiraCon1.isWrapperFor(Connection.class) ,然后将conn展开为HIRAConnection是不安全的,没有任何意义。 如果要将conn HIRAConnectionHIRAConnection ,则需要使用conn.isWrapperFor(HiraConnection.class)
  • hiraCon1= ds.unwrap(HIRAConnection.class);hiraCon1= ds.unwrap(HIRAConnection.class); 引发SQLExceptionjavax.sql.DataSource实现不太可能将自己视为连接的包装。
  • 检查hiraCon1.isWrapperFor(HIRAConnection.class)有点奇怪:您已经知道hiraCon1 HIRAConnection
  • 如前所述,在检查hiraCon1之后hiraCon1 conn没有意义。
  • 检查conn.isWrapperFor(Connection.class)有点奇怪:您已经知道conn 一个Connection
  • 检查conn.isWrapperFor(Connection.class)然后使用conn.unwrap(com.hira.HIRAConnection.class)是不安全的,因为您仅检查了conn是否解包到Connection而不是HIRAConnection

除了下面的@MarkRotteveel指出的以外,它们不是真正供应用程序使用的。 JDBC驱动程序作者(例如Apache DBCP)更多地使用它们。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM