package com.dieselpoint.norm;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import javax.sql.DataSource;
import com.dieselpoint.norm.sqlmakers.SqlMaker;
import com.dieselpoint.norm.sqlmakers.StandardSqlMaker;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
/**
* Provides methods to access a database.
*/
public class Database {
private SqlMaker sqlMaker = new StandardSqlMaker();
private DataSource ds;
/**
* Set the maker object for the particular flavor of sql.
*/
public void setSqlMaker(SqlMaker sqlMaker) {
this.sqlMaker = sqlMaker;
}
public SqlMaker getSqlMaker() {
return sqlMaker;
}
/**
* Provides the DataSource used by this database. Override this method to change how the DataSource is created or
* configured.
*/
protected DataSource getDataSource() throws SQLException {
HikariConfig config = new HikariConfig();
config.setMaximumPoolSize(10);
String dataSourceClassName = System.getProperty("norm.dataSourceClassName");
if (dataSourceClassName != null) {
config.setDataSourceClassName(dataSourceClassName);
}
String driverClassName = System.getProperty("norm.driverClassName");
if (driverClassName != null) {
config.setDriverClassName(driverClassName);
}
String jdbcUrl = System.getProperty("norm.jdbcUrl");
if (jdbcUrl != null) {
config.setJdbcUrl(jdbcUrl);
}
addConfigProperty(config, "serverName", System.getProperty("norm.serverName"));
addConfigProperty(config, "databaseName", System.getProperty("norm.databaseName"));
addConfigProperty(config, "user", System.getProperty("norm.user"));
addConfigProperty(config, "password", System.getProperty("norm.password"));
return new HikariDataSource(config);
}
private void addConfigProperty(HikariConfig config, String name, String value) {
if (value != null) {
config.addDataSourceProperty(name, value);
}
}
/**
* Create a query using straight SQL. Overrides any other methods
* like .where(), .orderBy(), etc.
* @param sql The SQL string to use, may include ? parameters.
* @param args The parameter values to use in the query.
*/
public Query sql(String sql, Object... args) {
return new Query(this).sql(sql, args);
}
/**
* Create a query with the given where clause.
* @param where Example: "name=?"
* @param args The parameter values to use in the where, example: "Bob"
*/
public Query where(String where, Object... args) {
return new Query(this).where(where, args);
}
/**
* Create a query with the given "order by" clause.
*/
public Query orderBy(String orderBy) {
return new Query(this).orderBy(orderBy);
}
/**
* Returns a JDBC connection. Can be useful if you need to customize
* how transactions work, but you shouldn't normally need to call this method.
* You must close the connection after you're done with it.
*/
public Connection getConnection() {
try {
if (ds == null) {
ds = getDataSource();
}
return ds.getConnection();
} catch (Throwable t) {
throw new DbException(t);
}
}
/**
* Simple, primitive method for creating a table based on a pojo.
* Does not add indexes or implement complex data types. Probably
* not suitable for production use.
*/
public Query createTable(Class clazz) {
return new Query(this).createTable(clazz);
}
/**
* Insert a row into a table. The row pojo can
* have a @Table annotation to specify the table,
* or you can specify the table with the .table() method.
*/
public Query insert(Object row) {
return new Query(this).insert(row);
}
/**
* Delete a row in a table. This method looks for an @Id annotation
* to find the row to delete by primary key, and looks for a @Table
* annotation to figure out which table to hit.
*/
public Query delete(Object row) {
return new Query(this).delete(row);
}
/**
* Execute a "select" query and get some results. The system will create
* a new object of type "clazz" for each row in the result set and add
* it to a List. It will also try to extract the table name from a @Table
* annotation in the clazz.
*/
public <T> List<T> results(Class<T> clazz) {
return new Query(this).results(clazz);
}
/**
* Returns the first row in a query in a pojo. Will return it in a Map
* if a class that implements Map is specified.
*/
public <T> T first(Class<T> clazz) {
return new Query(this).first(clazz);
}
/**
* Update a row in a table. It will match an existing row based
* on the primary key.
*/
public Query update(Object row) {
return new Query(this).update(row);
}
/**
* Upsert a row in a table. It will insert, and if that fails, do an update
* with a match on a primary key.
*/
public Query upsert(Object row) {
return new Query(this).upsert(row);
}
/**
* Create a query and specify which table it operates on.
*/
public Query table(String table) {
return new Query(this).table(table);
}
/**
* Start a database transaction. Pass the transaction object
* to each query or command that should be part of the transaction
* using the .transaction() method. Then call
* transaction.commit() or .rollback() to complete the process.
* No need to close the transaction.
* @return a transaction object
*/
public Transaction startTransaction() {
Transaction trans = new Transaction();
trans.setConnection(getConnection());
return trans;
}
/**
* Create a query that uses this transaction object.
*/
public Query transaction(Transaction trans) {
return new Query(this).transaction(trans);
}
}