2008-11-14 28 views
17

Tôi cần kiểm tra kết nối JDBC với cơ sở dữ liệu. Mã java để làm điều đó phải đơn giản như:Cách sử dụng trình điều khiển JDBC từ một vị trí tùy ý

DriverManager.getConnection("jdbc connection URL", "username", "password"); 

Trình quản lý trình điều khiển sẽ tra cứu trình điều khiển thích hợp cho URL kết nối đã cho. Tuy nhiên tôi cần để có thể tải trình điều khiển JDBC (jar) khi chạy. I. Tôi không có trình điều khiển JDBC trên classpath của ứng dụng java chạy đoạn mã trên.

Vì vậy, tôi có thể tải trình điều khiển sử dụng mã này, ví dụ:

URLClassLoader classLoader = new URLClassLoader(new URL[]{"jar URL"}, this.getClass().getClassLoader()); 
Driver driver = (Driver) Class.forName("jdbc driver class name", true, classLoader).newInstance(); 

Nhưng sau đó người quản lý tài xế vẫn không nhặt nó lên như tôi không thể nói nó mà classloader để sử dụng. Tôi đã thử thiết lập trình nạp lớp ngữ cảnh của luồng hiện tại và nó vẫn không hoạt động.

Bất kỳ ai có ý tưởng nào về cách tốt nhất để đạt được điều đó?

+0

Có lý do chính đáng khiến bạn không có tài xế trên đường dẫn lớp không? –

+0

Có. Ứng dụng có thể kết nối với nhiều cơ sở dữ liệu. Hơn nữa tôi không thể bó tất cả các trình điều khiển vì lý do cấp phép. Điều tôi muốn đạt được là một hộp thoại đơn giản để người dùng tải bình trong khi ứng dụng đang chạy. – SaM

+0

Ở đó tôi đã suy nghĩ như một nhà phát triển phía máy chủ một lần nữa ... :) –

Trả lời

17

Từ bài viết Pick your JDBC driver at runtime; Tôi sẽ đăng mã ở đây để tham khảo.

Ý tưởng là lừa người quản lý trình điều khiển nghĩ rằng trình điều khiển đã được tải từ trình nạp lớp hệ thống. Để thực hiện việc này, chúng tôi sử dụng lớp này:

public class DelegatingDriver implements Driver 
{ 
    private final Driver driver; 

    public DelegatingDriver(Driver driver) 
    { 
     if (driver == null) 
     { 
      throw new IllegalArgumentException("Driver must not be null."); 
     } 
     this.driver = driver; 
    } 

    public Connection connect(String url, Properties info) throws SQLException 
    { 
     return driver.connect(url, info); 
    } 

    public boolean acceptsURL(String url) throws SQLException 
    { 
     return driver.acceptsURL(url); 
    } 

    public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException 
    { 
     return driver.getPropertyInfo(url, info); 
    } 

    public int getMajorVersion() 
    { 
     return driver.getMajorVersion(); 
    } 

    public int getMinorVersion() 
    { 
     return driver.getMinorVersion(); 
    } 

    public boolean jdbcCompliant() 
    { 
     return driver.jdbcCompliant(); 
    } 
} 

Bằng cách này trình điều khiển bạn đăng ký là loại DelegatingDriver được tải bằng trình nạp lớp hệ thống. Bây giờ bạn chỉ cần tải trình điều khiển mà bạn thực sự muốn sử dụng bằng cách sử dụng bất kỳ trình nạp lớp nào bạn muốn. Ví dụ:

URLClassLoader classLoader = new URLClassLoader(new URL[]{"path to my jdbc driver jar"}, this.getClass().getClassLoader()); 
Driver driver = (Driver) Class.forName("org.postgresql.Driver", true, classLoader).newInstance(); 
DriverManager.registerDriver(new DelegatingDriver(driver)); // register using the Delegating Driver 

DriverManager.getDriver("jdbc:postgresql://host/db"); // checks that the driver is found 
5

Vấn đề là DriverManager thực hiện "các tác vụ sử dụng phiên bản trình nạp lớp của người gọi trực tiếp". Xem Hướng dẫn 6-3 của Secure Coding Guidelines for the Java Programming Language, version 2.0. Trình nạp lớp hệ thống là không có cách nào đặc biệt trong trường hợp này.

Chỉ để đá, tôi đã viết blog entry về chủ đề này trong khi quay lại. Giải pháp của tôi, mặc dù phức tạp hơn sau đó Nick Sayer's solution, là hoàn chỉnh hơn và thậm chí hoạt động từ mã không đáng tin cậy. Cũng xin lưu ý rằng URLClassLoader.newInstance được ưu tiên hơn new URLClassLoader.

Các vấn đề liên quan