View Javadoc

1   /*
2    * Copyright 2006 - 2012 Christina Bohk and Roland Ewald
3    *  
4    * Licensed under the Apache License, Version 2.0 (the "License"); 
5    * you may not use this file except in compliance with the License. 
6    * You may obtain a copy of the License at 
7    *  
8    *  http://www.apache.org/licenses/LICENSE-2.0
9    *  
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
13   * See the License for the specific language governing permissions and 
14   * limitations under the License. 
15   */
16  package p3j.database;
17  
18  import java.sql.Connection;
19  import java.sql.DriverManager;
20  import java.sql.ResultSet;
21  import java.sql.SQLException;
22  import java.util.Properties;
23  import java.util.logging.Level;
24  
25  import org.hibernate.cfg.Configuration;
26  import org.jamesii.SimSystem;
27  import org.jamesii.core.data.DBConnectionData;
28  
29  import p3j.database.hibernate.P3MDatabase;
30  import p3j.gui.P3J;
31  import p3j.gui.misc.P3JConfigFile;
32  import p3j.misc.Misc;
33  import p3j.misc.gui.GUI;
34  
35  /**
36   * A factory for the database layer. Not implemented properly yet.
37   * 
38   * Created on January 11, 2007
39   * 
40   * @author Christina Bohk
41   * @author Roland Ewald
42   * 
43   */
44  public final class DatabaseFactory {
45  
46    /**
47     * The name of the index that is manually created for the 'matrices' table in
48     * case a MySQL database is used.
49     */
50    private static final String MYSQL_MATRIX_INDEX_NAME = "hash_index";
51  
52    /**
53     * This class should not be instantiated.
54     */
55    private DatabaseFactory() {
56    }
57  
58    /** Implementing singleton pattern. */
59    private static IP3MDatabase sqlDatabase;
60  
61    /** Connection data to be used. */
62    private static DBConnectionData dbConnData = Misc.DEFAULT_DB_CONN;
63  
64    /**
65     * Get database interface.
66     * 
67     * @return database interface
68     */
69    public static IP3MDatabase getDatabaseSingleton() {
70      if (sqlDatabase == null) {
71        sqlDatabase = createDatabase(P3J.getInstance().getConfigFile());
72      }
73      return sqlDatabase;
74    }
75  
76    /**
77     * Creates a new Database object.
78     * 
79     * @param configFile
80     *          the config file
81     * @return the newly created database interface object
82     */
83    public static IP3MDatabase createDatabase(P3JConfigFile configFile) {
84      P3MDatabase database = new P3MDatabase();
85      database.init(dbConnData, configFile);
86      try {
87        database.open();
88        attemptDBSpecificOptimizations(database.getConfig(), dbConnData);
89      } catch (Exception ex) {
90        SimSystem.report(ex);
91      }
92      return database;
93    }
94  
95    /**
96     * Attempt some db-specific optimizations that cannot be easily covered by
97     * (the used version of) hibernate. Establishes a JDBC connection with the
98     * driver that is also used by hibernate and executes some raw SQL statements,
99     * e.g. to create multi-column indices.
100    * 
101    * @param config
102    *          the hibernate configuration
103    * @param connData
104    *          the connection data
105    */
106   private static void attemptDBSpecificOptimizations(Configuration config,
107       DBConnectionData connData) {
108     if (config.getProperty(Misc.PREF_HIBERNATE_DIALECT_PROPERTY).equals(
109         Misc.HIBERNATE_DIALECTS.get(DatabaseType.MYSQL))) {
110       createMatrixIndex(connData);
111     }
112   }
113 
114   /**
115    * Creates an index on the matrix table of a MySQL database schema (unless it
116    * already exists). The index is defined on the id (pk) and the hash code, to
117    * make retrieving matrices with certain hash codes faster.
118    * 
119    * @param connData
120    *          the database connection data
121    */
122   private static void createMatrixIndex(DBConnectionData connData) {
123 
124     Properties connectionProps = new Properties();
125     connectionProps.put("user", connData.getUser());
126     connectionProps.put("password", connData.getPassword());
127 
128     try (Connection conn = DriverManager.getConnection(dbConnData.getURL(),
129         connectionProps)) {
130       ResultSet rs = conn.createStatement().executeQuery(
131           "SHOW INDEX FROM matrices WHERE KEY_NAME = '"
132               + MYSQL_MATRIX_INDEX_NAME + "'");
133       if (!rs.first()) {
134         SimSystem.report(Level.INFO, "Attempting to create index '"
135             + MYSQL_MATRIX_INDEX_NAME + "'");
136         conn.createStatement()
137             .executeUpdate(
138                 "CREATE INDEX " + MYSQL_MATRIX_INDEX_NAME
139                     + " ON matrices(ID,hash)");
140         SimSystem.report(Level.INFO, "Index creation successful.");
141       }
142     } catch (SQLException e) {
143       SimSystem.report(e);
144     }
145   }
146 
147   /**
148    * Creates a new Database object, given a certain hibernate configuration
149    * file.
150    * 
151    * @param hibernateConfigFile
152    *          the hibernate config file
153    * 
154    * @return the database
155    */
156   public static IP3MDatabase createDatabase(String hibernateConfigFile) {
157     P3MDatabase.setHibernateConfigFile(hibernateConfigFile);
158     return createDatabase(P3J.getInstance().getConfigFile());
159   }
160 
161   /**
162    * Gets the DB connection data.
163    * 
164    * @return the DB connection data
165    */
166   public static DBConnectionData getDbConnData() {
167     return dbConnData;
168   }
169 
170   /**
171    * Sets the DB connection data.
172    * 
173    * @param dbConnData
174    *          the new DB connection data
175    */
176   public static void setDbConnData(DBConnectionData dbConnData) {
177     try {
178       reset();
179     } catch (Exception ex) {
180       GUI.printErrorMessage("Error closing database connection", ex);
181     }
182     DatabaseFactory.dbConnData = dbConnData;
183   }
184 
185   /**
186    * Reset.
187    */
188   public static void reset() {
189     if (sqlDatabase != null) {
190       sqlDatabase.close();
191     }
192     sqlDatabase = null;
193   }
194 
195 }