简体   繁体   English

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

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

I would like to know the correct way to validate isWrapperFor and unwrap functions in JDBC. 我想知道验证isWrapperFor和在JDBC中解包函数的正确方法。 Here HIRAConnection and the standard Connection classes are used. 这里使用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");
    }
}

The correct way to use java.sql.Wrapper is documented in its javadoc. 在其javadoc中记录了使用java.sql.Wrapper的正确方法。

For isWrapperFor(Class<?> iface) : 对于isWrapperFor(Class<?> iface)

Returns true if this either implements the interface argument or is directly or indirectly a wrapper for an object that does. 如果此方法实现了接口参数,或者直接或间接地对该对象进行了包装,则返回true。 Returns false otherwise. 否则返回false。 If this implements the interface then return true, else if this is a wrapper then return the result of recursively calling isWrapperFor on the wrapped object. 如果这实现了接口,则返回true,否则返回true,否则返回包装对象上递归调用isWrapperFor的结果。 If this does not implement the interface and is not a wrapper, return false. 如果这没有实现接口并且不是包装器,则返回false。 This method should be implemented as a low-cost operation compared to unwrap so that callers can use this method to avoid expensive unwrap calls that may fail. unwrap相比,此方法应作为一种低成本操作来实现,以便调用者可以使用此方法来避免可能失败的昂贵的unwrap调用。 If this method returns true then calling unwrap with the same argument should succeed. 如果此方法返回true,则使用相同参数调用unwrap应该会成功。

Parameters : 参数
iface - a Class defining an interface. iface定义接口的类。
Returns : 返回值
true if this implements the interface or directly or indirectly wraps an object that does. 如果这实现了接口或直接或间接包装了这样做的对象,则为true。

And for unwrap(Class<T> iface) : 对于unwrap(Class<T> iface)

Returns an object that implements the given interface to allow access to non-standard methods, or standard methods not exposed by the proxy. 返回一个实现给定接口的对象,以允许访问非标准方法或代理未公开的标准方法。 If the receiver implements the interface then the result is the receiver or a proxy for the receiver. 如果接收方实现了接口,那么结果就是接收方或该接收方的代理。 If the receiver is a wrapper and the wrapped object implements the interface then the result is the wrapped object or a proxy for the wrapped object. 如果接收方是包装器,并且包装对象实现接口,则结果是包装对象或包装对象的代理。 Otherwise return the the result of calling unwrap recursively on the wrapped object or a proxy for that result. 否则,返回调用的结果unwrap的包装对象或该结果的代理递归。 If the receiver is not a wrapper and does not implement the interface, then an SQLException is thrown. 如果接收方不是包装器,并且未实现该接口,则将引发SQLException

Type Parameters : 类型参数
T - the type of the class modeled by this Class object T此Class对象建模的类的类型
Parameters : 参数
iface - A Class defining an interface that the result must implement. iface定义结果必须实现的接口的类。
Returns : 返回值
an object that implements the interface. 实现接口的对象。 May be a proxy for the actual implementing object. 可能是实际实现对象的代理。
Throws : 抛出
SQLException - If no object found that implements the interface SQLException如果未找到实现该接口的对象

In other words, you can first check using wrapperFor if the wrapper can unwrap to the interface, and then you can use unwrap to really unwrap to that interface. 换句话说,您可以先使用wrapperFor检查包装程序是否可以解包到接口,然后可以使用unwrap真正解包到该接口。 Be aware that the specification only mentions support to unwrap to interface, so unwrapping to concrete classes may not actually be possible. 请注意,该规范仅提及支持对接口进行拆包,因此实际上可能无法对具体类进行拆包。

Whether this works, depends on the driver used (not all drivers support unwrapping or maybe they have nothing useful to unwrap), and if you are using a connection pool library, then it is entirely possible that it doesn't allow you to unwrap to - for example - the underlying connection, because doing that could allow you to circumvent or break certain limits and requirements of the connection pool. 是否起作用,取决于所使用的驱动程序(并非所有驱动程序都支持解包,或者可能没有对解包有用的东西),如果您使用的是连接池库,则很可能不允许您解包。 -例如-基础连接,因为这样做可以使您规避或打破连接池的某些限制和要求。

So the correct way to use wrapping would be: 因此,使用包装的正确方法是:

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

However if HiraConnection is a concrete class instead of an interface, this might not work. 但是,如果HiraConnection是一个具体的类而不是一个接口,则可能不起作用。 And unwrapping will usually also lead to brittle code. 而且展开通常也会导致代码变脆。 It is usually better to avoid relying on driver specific interface unless absolutely necessary. 除非绝对必要,否则通常最好避免依赖于特定于驱动程序的接口。

Some remarks on the code in your question: 有关您问题中代码的一些说明:

  • If you know HIRAConnection hiraCon1 = (HIRAConnection) ds.getConnection(); 如果您知道HIRAConnection hiraCon1 = (HIRAConnection) ds.getConnection(); works, then you don't need to unwrap at all. 有效,那么您根本不需要拆包。
  • Checking for hiraCon1 instanceof Wrapper is a useless check, because if HIRAConnection implements java.sql.Connection , then it will always implement java.sql.Wrapper (and otherwise running your code would yield a ClassNotFoundException for java.sql.Wrapper meaning you ran it on Java 5 or lower). 检查hiraCon1 instanceof Wrapper是没有用的检查,因为如果HIRAConnection实现java.sql.Connection ,那么它将始终实现java.sql.Wrapper (否则,运行代码将为java.sql.Wrapper产生ClassNotFoundException ,这意味着您可以运行它在Java 5或更低版本上)。
  • Checking hiraCon1.isWrapperFor(Connection.class) and then unwrapping conn to HIRAConnection is unsafe and makes no sense. 检查hiraCon1.isWrapperFor(Connection.class) ,然后将conn展开为HIRAConnection是不安全的,没有任何意义。 If you want to unwrap conn to HIRAConnection , then you need to use conn.isWrapperFor(HiraConnection.class) 如果要将conn HIRAConnectionHIRAConnection ,则需要使用conn.isWrapperFor(HiraConnection.class)
  • It is not unexpected that hiraCon1= ds.unwrap(HIRAConnection.class); hiraCon1= ds.unwrap(HIRAConnection.class);hiraCon1= ds.unwrap(HIRAConnection.class); throws an SQLException : it is unlikely that a javax.sql.DataSource implementation considers itself a wrapper for connections. 引发SQLExceptionjavax.sql.DataSource实现不太可能将自己视为连接的包装。
  • Checking hiraCon1.isWrapperFor(HIRAConnection.class) is a bit odd: you already know hiraCon1 is a HIRAConnection 检查hiraCon1.isWrapperFor(HIRAConnection.class)有点奇怪:您已经知道hiraCon1 HIRAConnection
  • As previously mentioned, unwrapping conn after checking hiraCon1 makes no sense. 如前所述,在检查hiraCon1之后hiraCon1 conn没有意义。
  • Checking conn.isWrapperFor(Connection.class) is a bit odd: you already know conn is a Connection 检查conn.isWrapperFor(Connection.class)有点奇怪:您已经知道conn 一个Connection
  • Checking conn.isWrapperFor(Connection.class) and then using conn.unwrap(com.hira.HIRAConnection.class) is unsafe, as you have only checked whether conn unwraps to Connection , not to HIRAConnection . 检查conn.isWrapperFor(Connection.class)然后使用conn.unwrap(com.hira.HIRAConnection.class)是不安全的,因为您仅检查了conn是否解包到Connection而不是HIRAConnection

They are not really for use by applications, except as noted by @MarkRotteveel below. 除了下面的@MarkRotteveel指出的以外,它们不是真正供应用程序使用的。 They are used more by JDBC driver authors, for example the Apache DBCP. JDBC驱动程序作者(例如Apache DBCP)更多地使用它们。

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

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