2025年3月19日 星期三

how to connect to Java DB from Java application or Java EE container

 假設 Java DB 已建好 db_name 資料庫,帳密為 user/password。

以下展示 Java EE 後台組件如何善用資料來源定義,注入資料來源,定義執行SQL指令,回傳結果集合給前台。

  1.  
  2. // 定義資料來源
  3. @DataSourceDefinition(
  4. name = "java:global/jdbc/db_name",
  5. className = "org.apache.derby.jdbc.ClientDataSource",
  6. url = "jdbc:derby://localhost:1527/db_name",
  7. databaseName = "db_name",
  8. user = "user",
  9. password = "password")
  10.  
  11. @Named("bean")
  12. @javax.faces.view.ViewScoped
  13. public class Bean implements Serializable
  14. {
  15. // 定義每筆記錄的欄位屬性 f1, f2, f3
  16.  
  17. // 要求伺服器注入資料來源成為 dataSource 物件
  18. @Resource(lookup="java:global/jdbc/db_name")
  19. DataSource dataSource;
  20. // 回傳查詢結果集合
  21. public ResultSet query() throws SQLException
  22. {
  23. // check whether dataSource was injected by the server
  24. if (dataSource == null)
  25. {
  26. throw new SQLException("Unable to obtain DataSource");
  27. }
  28. // 透過注入的資料來源,從連線池取得連線
  29. Connection connection = dataSource.getConnection();
  30.  
  31. // check whether connection was successful
  32. if (connection == null)
  33. {
  34. throw new SQLException("Unable to connect to DataSource");
  35. }
  36. try
  37. {
  38. // 建立查詢指令
  39. PreparedStatement getRecords = connection.prepareStatement(
  40. "SELECT * FROM tbl");
  41. // 建立存放結果的快取列集合
  42. CachedRowSet rowSet =
  43. RowSetProvider.newFactory().createCachedRowSet();
  44. // 執行查詢指令,將結果填入列集合
  45. rowSet.populate(getRecords.executeQuery());
  46.  
  47. // 回傳列集合,供前台呈現
  48. return rowSet;
  49. }
  50. finally
  51. {
  52. connection.close(); // return this connection to pool
  53. }
  54. }
  55. // 新增一筆記錄,回傳去處網頁名稱
  56. public String insert() throws SQLException
  57. {
  58. // check whether dataSource was injected by the server
  59. if (dataSource == null)
  60. {
  61. throw new SQLException("Unable to obtain DataSource");
  62. }
  63. // 透過注入的資料來源,從連線池取得連線
  64. Connection connection = dataSource.getConnection();
  65. // check whether connection was successful
  66. if (connection == null)
  67. {
  68. throw new SQLException("Unable to connect to DataSource");
  69. }
  70. try
  71. {
  72. // 建立帶參數新增記錄指令
  73. PreparedStatement addEntry =
  74. connection.prepareStatement("INSERT INTO tbl " +
  75. "(f1,f2,f3) VALUES (?, ?, ?)");
  76.  
  77. // 指定欄位值
  78. addEntry.setString(1, getF1());
  79. addEntry.setString(2, getF2());
  80. addEntry.setString(3, getF3());
  81.  
  82. addEntry.executeUpdate(); // insert the entry
  83. return ""; // 回傳空字串,停在原頁
  84. }
  85. finally
  86. {
  87. connection.close(); // 不管發生例外或return,都會關閉連線,歸還給連線池
  88. }
  89. }
  90. }
    利用 Java EE 後台注入資料來源的好處包括
  1. 連線池管理,可供連線重複使用,減少頻繁開關連線的成本。
  2. 資源管理,伺服器可管理連線生命週期,確保連線正常關閉,返回連線池。
  3. 組態管理,伺服器設定資料庫連線組態細節,程式只要呼叫資料來源即可。

如果願意喪失上述好處,也可採用

A. 單機版如DriverManager操作資料庫作法,一切自己管理,如下。

  1.  
  2. import java.sql.Connection;
  3. import java.sql.DriverManager;
  4. import java.sql.ResultSet;
  5. import java.sql.SQLException;
  6. import java.sql.Statement;
  7.  
  8. public class JavaDBExample {
  9. private static final String DB_URL = "jdbc:derby:myDB;create=true";
  10. private static final String USER = "user";
  11. private static final String PASSWORD = "password";
  12.  
  13. public static void main(String[] args) {
  14. try (Connection conn = DriverManager.getConnection(DB_URL, USER, PASSWORD);
  15. Statement stmt = conn.createStatement()) {
  16.  
  17. // Create a table
  18. String createTableSQL = "CREATE TABLE addresses (" +
  19. "id INT PRIMARY KEY, " +
  20. "firstname VARCHAR(255), " +
  21. "lastname VARCHAR(255), " +
  22. "street VARCHAR(255), " +
  23. "city VARCHAR(255), " +
  24. "state VARCHAR(255), " +
  25. "zip VARCHAR(255))";
  26. stmt.execute(createTableSQL);
  27.  
  28. // Insert data
  29. String insertSQL =
  30. "INSERT INTO addresses VALUES " +
  31. "(1, 'John', 'Doe', '123 Main St', 'Anytown', 'CA', '12345')";
  32. stmt.execute(insertSQL);
  33.  
  34. // Query data
  35. String querySQL = "SELECT * FROM addresses";
  36. ResultSet rs = stmt.executeQuery(querySQL);
  37.  
  38. while (rs.next()) {
  39. System.out.println("ID: " + rs.getInt("id"));
  40. System.out.println("First Name: " + rs.getString("firstname"));
  41. System.out.println("Last Name: " + rs.getString("lastname"));
  42. System.out.println("Street: " + rs.getString("street"));
  43. System.out.println("City: " + rs.getString("city"));
  44. System.out.println("State: " + rs.getString("state"));
  45. System.out.println("ZIP: " + rs.getString("zip"));
  46. }
  47. } catch (SQLException e) {
  48. e.printStackTrace();
  49. }
  50. }
  51. }

或者,
B. 採用單機版Java Persistence API (JPA) 操作資料庫作法,如下。

  1. // Address.java 住址個體類別
  2.  
  3. import javax.persistence.Entity;
  4. import javax.persistence.Id;
  5. import javax.persistence.Table;
  6.  
  7. @Entity
  8. @Table(name = "addresses")
  9. public class Address {
  10. @Id
  11. private int id;
  12. private String firstname;
  13. private String lastname;
  14. String city;
  15. private String state;
  16. private String zip;
  17.  
  18. // Getters and setters
  19. }

由如下個體管理員建立查詢,取用資料庫:

  1. // JpaExample.java
  2.  
  3. import javax.persistence.EntityManager;
  4. import javax.persistence.EntityManagerFactory;
  5. import javax.persistence.Persistence;
  6. import javax.persistence.TypedQuery;
  7. import java.util.List;
  8.  
  9. public class JpaExample {
  10. private static final EntityManagerFactory ENTITY_MANAGER_FACTORY =
  11. Persistence.createEntityManagerFactory("myPersistenceUnit");
  12.  
  13. public static void main(String[] args) {
  14. EntityManager entityManager = ENTITY_MANAGER_FACTORY.createEntityManager();
  15.  
  16. try {
  17. // Create a query to fetch addresses
  18. TypedQuery<Address> query =
  19. entityManager.createQuery("SELECT a FROM Address a", Address.class);
  20. List<Address> addresses = query.getResultList();
  21.  
  22. // Process the result
  23. for (Address address : addresses) {
  24. System.out.println("ID: " + address.getId());
  25. System.out.println("First Name: " + address.getFirstname());
  26. System.out.println("Last Name: " + address.getLastname());
  27. System.out.println("Street: " + address.getStreet());
  28. System.out.println("City: " + address.getCity());
  29. System.out.println("State: " + address.getState());
  30. ();
  31. }
  32. } finally {
  33. entityManager.close();
  34. ENTITY_MANAGER_FACTORY.close();
  35. }
  36. }
  37. }

其中,建立個體管理員時,須要參考如下 META-INF/persistence.xml 持續組態檔,

內含 myPersistenceUnit 持續單元的定義:

  1. <persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence" version="2.2">
  2. <persistence-unit name="myPersistenceUnit">
  3. <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
  4. <class>com.example.Address</class>
  5. <properties>
  6. <property name="javax.persistence.jdbc.url" value="jdbc:derby:myDB;create=true"/>
  7. <property name="javax.persistence.jdbc.user" value="user"/>
  8. <property name="javax.persistence.jdbc.password" value="password"/>
  9. <property name="javax.persistence.jdbc.driver" value="org.apache.derby.jdbc.EmbeddedDriver"/>
  10. <property name="hibernate.dialect" value="org.hibernate.dialect.DerbyDialect"/>
  11. <property name="hibernate.hbm2ddl.auto" value="update"/>
  12. </properties>
  13. </persistence-unit>
  14. </persistence>

沒有留言: