2016-09-23 56 views
4

我试图在将本地H2数据库集成到我的JavaFX应用程序(Java8)时避免静态和单例。其他五个类(包括控制器)需要访问数据库,所以我试图共享它们之间的一个H2连接。我已阅读Connection Pool避免不必要的重新连接,但如果它适用于此,则会感到困惑。桌面使用,单用户。跨类访问H2连接

以下ExtrasDB类包含3种方法,initializeDB,getDBValuesperformQuery。以前这些方法是static,我会从其他类使用ExtrasDB.getDBValues()调用它们,并相应地使用结果,但由于我的应用程序使用多线程我正在寻找更好的方法。我正在从我的应用中删除所有静态/单身使用的过程。

initializeDB方法创建连接并根据需要创建一个表,并且从主控制器的initialize方法只调用一次此方法。这导致连接conn被隔离到该实例,并且getDBValuesperformQuery上的其他类的调用不可访问,导致空结果集。如何使数据库连接可以访问所有必需的类,以便这些类可以使用上述方法自由访问数据库?

public class ExtrasDB { 

    final String JDBC_DRIVER = "org.h2.Driver"; 
    final String DB_URL = "jdbc:h2:~/mainDB"; 
    final String USER = "test"; 
    final String PASS = "test"; 
    Connection conn = null; 
    Statement statement = null; 
    String myStatement; 
    ResultSet rs; 
    DatabaseMetaData meta; 

    public void initializeDB() { 

     try { 
      Class.forName("org.h2.Driver"); 
      conn = DriverManager.getConnection(DB_URL, USER, PASS); 
      System.out.println("Connected to database successfully..."); 
      statement = conn.createStatement(); 
      meta = conn.getMetaData(); 
      rs = meta.getTables(null, null, "EXTRAS", new String[]{"TABLE"}); // <--- Checks for existence of table "EXTRAS" 

      if (!rs.next()) { 

       System.out.println("Table doesn't exist yet... Creating..."); 
       sql = "CREATE TABLE EXTRAS " + 
         "(column_1 VARCHAR(255), " + 
         " column_2 VARCHAR(255))"; 

       statement.executeUpdate(sql); 
      } 
     } catch (SQLException e) { 
      e.printStackTrace(); 
     } catch (ClassNotFoundException e) { 
      e.printStackTrace(); 
     } 
    } 


    public void getDBValues() throws SQLException { 
     rs = statement.executeQuery("SELECT * FROM EXTRAS"); 
     while (rs.next()) { 
      //..... do something 
     } 
    } 

    public void performQuery(String query) { 
     try { 
      statement.executeUpdate(query); 
     } catch (Exception ex) { 
      ex.printStackTrace(); 
     } 
    } 
} 
+0

'org.h2.test.jdbcx.TestConnectionPool'就是一个例子。 – trashgod

+0

'performQuery(...){executeUpdate(...);嗯......什么?查询数据库会导致更新?也许如果'ResultSet performQuery(){return this.conn.executeQuery(...); }'你实际上不需要共享连接并仍然可以得到结果吗? –

+0

@trashgod,我想花时间理解* [那个例子](https://github.com/pkouki/recsys2015/blob/master/h2/src/test/org/h2/test/jdbcx/TestConnectionPool.java) *,似乎'testKeepOpen()'方法演示了man.dispose()是如何关闭该池的,但是我很困惑:(1)我的类ExtrasDB是否应该是'public static ...'以及3种方法,“公共”还是“私人”?我问的原因是(2)我的其他课程可以使用'ExtrasDb。getDBValues()'(静态),但如果我在每个类中创建一个ExtrasDB对象,它将创建一个新的ConnectionPool。如何分享? – MM88

回答

0

你有两个选择,如果你不想要某种静态访问:

  1. 在开始你的计划创建服务工厂的实例(非静态)。 Service-Factory是一个pojo类,包含您想要跨其他类共享的所有依赖关系。这些依赖关系可以由服务工厂创建,也可以通过setter来设置。所有需要一些依赖项的类只需提供Factory实例。
  2. 你可以使用一些实现自动依赖注入的框架。有了这样的框架,你只需要注释你的构造函数或字段。有关依赖注入的更多信息,请参见this link;有关如何使用弹簧框架进行依赖注入的this tutorial

在我的JavaFX应用程序使用第一个选项。我有一个名为Root的类,并在javafx.application.Application :: start函数内创建它的一个实例。某些依赖项由Root类创建,而其他一些依赖项(例如控制器实例)则使用setter来设置。因为我通过FXML装载机装我的控制器,我不能使用构造所提供的根实例,而是每个控制器有一个初始化函数

public void initialize(Root root); 

如果您需要更多的帮助。随意评论这个答案。