7.1 Nhóm kết nối

Hôm nay chúng ta sẽ học cách làm việc với cơ sở dữ liệu chuyên nghiệp hơn nữa. Và bây giờ chúng ta sẽ nói về thread pool, hay connection pool trong tiếng Anh.

Kết nối với cơ sở dữ liệu mất một thời gian. Đặc biệt nếu cơ sở dữ liệu ở xa. Nếu chúng ta tạo kết nối đến cơ sở dữ liệu cho từng yêu cầu, thì phản hồi của ứng dụng của chúng ta sẽ có tốc độ cực kỳ chậm. Chưa kể các tài nguyên nó sẽ tiêu thụ.

Như một giải pháp cho những vấn đề như vậy, người ta đã đề xuất lưu trữ các kết nối đến cơ sở trong một số tập hợp, được gọi là nhóm luồng.

Khi chúng tôi yêu cầu một kết nối mới, nhóm kết nối sẽ tạo ra nó và khi đóng, nó sẽ không đóng mà lưu nó vào nhóm kết nối. Và nếu chúng tôi yêu cầu kết nối lại từ nhóm kết nối, nó sẽ cung cấp cho chúng tôi một trong những kết nối cũ thay vì tạo một kết nối mới.

Trên thực tế, ứng dụng hoạt động thông qua một trình điều khiển đặc biệt, là trình bao bọc cho trình điều khiển JDBC thông thường và có chức năng bổ sung để làm việc với nhóm. Tình huống này có thể được biểu diễn như sau:

nhóm kết nối

Lập trình viên có thể đặt cài đặt cho nhóm kết nối theo cách thủ công: số lượng kết nối đang hoạt động, thời gian chờ, v.v.

Đối với những tình huống đặc biệt khắc nghiệt, bạn có thể viết nhóm kết nối của riêng mình: một lớp sẽ có danh sách các kết nối. Nó sẽ ghi đè chức năng đóng, chức năng này sẽ đưa kết nối trở lại danh sách và sẽ có nhiều tính năng khác như bộ hẹn giờ mở kết nối. Khi không có kết nối trong một thời gian dài, kết nối sẽ bị đóng.

7.2* Giao diện DataSource và ConnectionPoolDataSource

Nhóm luồng thường hoạt động song song với đối tượng DataSource. Đối tượng này có thể được coi là một sự trừu tượng của một cơ sở dữ liệu từ xa. Tên Nguồn dữ liệu rất có thể được dịch theo nghĩa đen là Nguồn dữ liệu. Đó là loại gợi ý.

Các đối tượng DataSource được sử dụng để có được kết nối vật lý tới cơ sở dữ liệu và là một giải pháp thay thế cho DriverManager. Không cần phải đăng ký trình điều khiển JDBC. Bạn chỉ cần thiết lập các thông số phù hợp để thiết lập kết nối vàthực thi phương thức getConnection().

Khi tạo một đối tượng kiểu DataSource cục bộ (trực tiếp trong ứng dụng), các tham số kết nối được thiết lập bởi các phương pháp thích hợp do nhà cung cấp trình điều khiển JDBC cung cấp. Các phương pháp này không được xác định bởi giao diện DataSource, vì các tham số để kết nối với DBMS từ các nhà cung cấp khác nhau có thể khác nhau cả về loại và số lượng (ví dụ: không phải tất cả DBMS đều yêu cầu loại trình điều khiển hoặc giao thức mạng được chỉ định).

Do đó, khi làm việc với Oracle DBMS, để sử dụng các phương thức set và get tương ứng, cần phải lấy một đối tượng thuộc loại OracleDataSource, là một thể hiện của lớp cùng tên thực hiện giao diện DataSource. Do đó, cách tạo các đối tượng kiểu DataSource này làm cho mã của bạn ít di động hơn và ít phụ thuộc vào việc triển khai trình điều khiển cụ thể.

Sau đây là một ví dụ mã minh họa việc sử dụng cục bộ các đối tượng kiểu DataSource.

import java.sql.*;
import javax.sql.*;
import oracle.jdbc.driver.*;
import oracle.jdbc.pool.*;

public class DataSource {
    public static void main(String[] args) {
    	try {
        	OracleDataSource ods = new OracleDataSource();

        	ods.setUser("root");
        	ods.setPassword("secret");
        	ods.setDriverType("thin");
        	ods.setDatabaseName("test");
        	ods.setServerName("localhost");
        	ods.setPortNumber(1521);

        	Connection connection = ods.getConnection();
        	System.out.println("Connection successful!!!");

    	} catch (SQLException se) {
        	se.printStackTrace();
    	}
    	System.out.println("Goodbye!");
	}
}

7.3* Giao diện JNDI

Toàn bộ khả năng của các đối tượng kiểu DataSource được thể hiện kết hợp với việc sử dụng giao diện JNDI. JNDI là một dịch vụ đặc biệt (giống như một thư mục) dành cho các ứng dụng máy chủ lớn cho phép một dịch vụ thiết lập kết nối với một dịch vụ khác.

Sử dụng dịch vụ tên và thư mục cho phép bạn lưu trữ các đối tượng thuộc loại DataSource do người quản trị hệ thống tạo trước đó với các tham số kết nối được xác định trước. Sau đây là một số tên thuộc tính (tham số) tiêu chuẩn do Sun phát triển:

Tên tài sản kiểu dữ liệu Java Mục đích
tên cơ sở dữ liệu Sợi dây Tên cơ sở dữ liệu
tên máy chủ Sợi dây Tên máy chủ
người dùng Sợi dây Tên người dùng / ID)
mật khẩu Sợi dây Mật khẩu người dùng
số cổng int Số cổng máy chủ DBMS

Sự kết hợp giữa các giao diện DataSource và JNDI đóng một vai trò quan trọng trong việc phát triển các ứng dụng doanh nghiệp nhiều tầng dựa trên công nghệ thành phần J2EE.

Nếu bạn sử dụng kết hợp các giao diện DataSource và JNDI trong mã ứng dụng của mình, thì bạn chỉ cần yêu cầu một đối tượng thuộc loại DataSource từ dịch vụ đặt tên và thư mục. Trong trường hợp này, các chi tiết của kết nối và mã chương trình phụ thuộc vào việc triển khai trình điều khiển cụ thể sẽ bị ẩn khỏi ứng dụng trong đối tượng được lưu trữ trong dịch vụ tên và thư mục.

Do đó, việc chia sẻ các đối tượng kiểu DataSource và JNDI bao gồm hai bước được thực hiện độc lập với nhau:

  1. Bạn phải lưu trữ đối tượng được đặt tên thuộc loại DataSource trong dịch vụ đặt tên và thư mục bằng cách sử dụng Context.bind()tệp javax.naming.
  2. Yêu cầu một đối tượng kiểu DataSource từ dịch vụ đặt tên và thư mục trong ứng dụng bằng cách sử dụng tệp Context.lookup(). Sau đó, bạn có thể sử dụng phương thức của nó DataSource.getConnection()để nhận kết nối đến cơ sở dữ liệu.

Sau đây là một ví dụ về việc sử dụng giao diện JNDI và một đối tượng kiểu OracleDataSource cùng nhau.

// Create a key JNDI object
Hashtable env = new Hashtable();
env.put (Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.fscontext.RefFSContextFactory");
env.put (Context.PROVIDER_URL, "file:JNDI");
Context ctx = new InitialContext(env);

// Get the DataSource object by its name
DataSource ods = (DataSource) ctx.lookup("myDatabase");

// Get the Connection from the DataSource object
Connection connection = ods.getConnection();
System.out.println("Connection successful!!!");

Chúng tôi sẽ không phân tích công việc của JNDI. Điều này nằm ngoài phạm vi của khóa học này. Tôi chỉ muốn bạn biết rằng phương pháp này rất phổ biến trong các ứng dụng lớn. Đừng để bị lạc nếu bạn thấy mã như thế này trong tương lai.

Nó không quan trọng nó hoạt động như thế nào. Bạn chỉ cần biết rằng với dịch vụ JNDI, bạn có thể lấy đối tượng proxy của bất kỳ dịch vụ nào đã đăng ký trong thư mục dịch vụ. Đây là cách bạn lấy đối tượng DataSource và sử dụng nó để làm việc với cơ sở dữ liệu.

7.4 Các ví dụ về nhóm kết nối

Hãy quay lại nơi chúng ta đã bắt đầu - nhóm kết nối.

Các lập trình viên Java trong các chương trình của họ thường sử dụng các thư viện chứa các triển khai khác nhau của nhóm kết nối. Trong số đó có ba phổ biến nhất:

  • Apache Commons DBCP
  • C3PO
  • Hikari CP

Dự án Apache là dự án đầu tiên tạo ra một nhóm kết nối tốt, nó cũng được sử dụng bên trong máy chủ web Tomcat. Một ví dụ về làm việc với nó:

public class DBCPDataSource {

    private static BasicDataSource ds = new BasicDataSource();
    static {
    	ds.setUrl("jdbc:h2:mem:test");
    	ds.setUsername("user");
    	ds.setPassword("password");
    	ds.setMinIdle(5);
    	ds.setMaxIdle(10);
    	ds.setMaxOpenPreparedStatements(100);
    }

    public static Connection getConnection() throws SQLException {
    	return ds.getConnection();
    }

    private DBCPDataSource(){ }
}

Pool rất phổ biến thứ hai là C3PO . Tên lạ, tôi đồng ý. Cái tên C3PO liên quan đến robot c3po từ Chiến tranh giữa các vì sao. Và CP cũng là viết tắt của Connection Pool.

public class C3p0DataSource {

    private static ComboPooledDataSource cpds = new ComboPooledDataSource();
    static {
    	try {
        	cpds.setDriverClass("org.h2.Driver");
        	cpds.setJdbcUrl("jdbc:h2:mem:test");
        	cpds.setUser("user");
        	cpds.setPassword("password");
    	} catch (PropertyVetoException e) {
            // handle the exception
    	}
    }

    public static Connection getConnection() throws SQLException {
    	return cpds.getConnection();
    }

    private C3p0DataSource(){}
}

Tài liệu cho nó có thể được tìm thấy trên trang chính thức .

Và cuối cùng, Nhóm kết nối phổ biến nhất hiện nay là HikariCP :

public class HikariCPDataSource {

    private static HikariConfig config = new HikariConfig();
    private static HikariDataSource ds;

    static {
    	config.setJdbcUrl("jdbc:h2:mem:test");
    	config.setUsername("user");
    	config.setPassword("password");
    	config.addDataSourceProperty("cachePrepStmts", "true");
    	config.addDataSourceProperty("prepStmtCacheSize", "250");
    	config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048");
    	ds = new HikariDataSource(config);
    }

    public static Connection getConnection() throws SQLException {
    	return ds.getConnection();
    }

    private HikariCPDataSource(){}
}

Đây là trang GitHub chính thức của anh ấy .

một bài viết hay về cấu hình.