簡體   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