Skip to content

Commit

Permalink
Fixes MySQL implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
jswiesner committed Jan 18, 2018
1 parent 37bd341 commit 03d71e8
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 24 deletions.
4 changes: 2 additions & 2 deletions pom.xml
Expand Up @@ -4,7 +4,7 @@

<groupId>com.erudika</groupId>
<artifactId>para-dao-sql</artifactId>
<version>1.27.1-SNAPSHOT</version>
<version>1.28.1-SNAPSHOT</version>

<packaging>jar</packaging>
<name>Para SQL DAO</name>
Expand Down Expand Up @@ -69,7 +69,7 @@
<dependency>
<groupId>com.erudika</groupId>
<artifactId>para-core</artifactId>
<version>1.28.0</version>
<version>1.28.1</version>
<scope>provided</scope>
</dependency>

Expand Down
116 changes: 94 additions & 22 deletions src/main/java/com/erudika/para/persistence/SqlUtils.java
Expand Up @@ -32,6 +32,7 @@
import org.slf4j.LoggerFactory;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
Expand All @@ -52,8 +53,25 @@
public final class SqlUtils {

private static final Logger logger = LoggerFactory.getLogger(SqlUtils.class);
private static boolean useMySqlSyntax = false;

private static HikariDataSource hikariDataSource;
private static final String JSON_FIELD_NAME = "json";
private static final String SQL_SCHEMA = Utils.formatMessage(
"{0} NVARCHAR(64) PRIMARY KEY NOT NULL," +
"{1} NVARCHAR(64) NOT NULL," +
"{2} NVARCHAR(64) DEFAULT NULL," +
"{3} TIMESTAMP NOT NULL," +
"{4} TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP," +
"{5} LONGTEXT NOT NULL",
Config._ID,
Config._TYPE,
Config._CREATORID,
Config._TIMESTAMP,
Config._UPDATED,
JSON_FIELD_NAME
);

private SqlUtils() { }

/**
Expand All @@ -65,10 +83,40 @@ static Connection getConnection() throws SQLException {
return hikariDataSource.getConnection();
}

String sqlUrl = Config.getConfigParam("sql.url", null);
String sqlDriver = Config.getConfigParam("sql.driver", null);
String sqlUser = Config.getConfigParam("sql.user", "user");
String sqlPassword = Config.getConfigParam("sql.password", "secret");

if (StringUtils.isBlank(sqlUrl)) {
logger.error("Missing required configuration parameter \"para.sql.url\" for the SqlDAO");
}
if (Config.getConfigParam("sql.driver", null) == null) {
logger.error("Missing requiredconfiguration parameter \"para.sql.driver\" for the SqlDAO");
}

// verify the SQL driver can be loaded from the classpath
try {
Class.forName(sqlDriver);
useMySqlSyntax = sqlDriver.contains("mysql");
} catch (ClassNotFoundException e) {
throw new IllegalStateException("Error loading SQL driver \"{" + sqlDriver + "}\", class not found.");
}

// verify a connection can be made to the SQL server
try {
Connection conn = DriverManager.getConnection("jdbc:" + sqlUrl, sqlUser, sqlPassword);
conn.close();
} catch (SQLException e) {
throw new IllegalStateException("Failed to connect to SQL database: " + e.getMessage());
}

// connection and driver are valid, so establish a connection pool
HikariConfig hikariConfig = new HikariConfig();
hikariConfig.setJdbcUrl("jdbc:" + Config.getConfigParam("sql.url", null));
hikariConfig.setUsername(Config.getConfigParam("sql.user", "user"));
hikariConfig.setPassword(Config.getConfigParam("sql.password", "secret"));
hikariConfig.setJdbcUrl("jdbc:" + sqlUrl);
hikariConfig.setUsername(sqlUser);
hikariConfig.setPassword(sqlPassword);
hikariConfig.setDriverClassName(sqlDriver);
/*
hikariConfig.addDataSourceProperty("cachePrepStmts", Config.getConfigBoolean("sql.cachePrepStmts"), true);
hikariConfig.addDataSourceProperty("prepStmtCacheSize", Config.getConfigInt("sql.prepStmtCacheSize"), 500);
Expand Down Expand Up @@ -120,7 +168,7 @@ public static boolean existsTable(String appid) {
return name != null;
}
} catch (Exception e) {
logger.error("Failed to check if table exists for appid '{}'", appid, logSqlError(e));
logger.error("Failed to check if table exists for appid '{}'{}", appid, logSqlError(e));
}
return false;
}
Expand All @@ -137,14 +185,12 @@ public static boolean createTable(String appid) {
try (Connection connection = getConnection()) {
String tableName = getTableNameForAppid(appid);
Statement statement = connection.createStatement();
String sql = Utils.formatMessage("CREATE TABLE IF NOT EXISTS {0} ({1} NVARCHAR PRIMARY KEY,"
+ "{2} NVARCHAR,{3} NVARCHAR,{4} TIMESTAMP,{5} TIMESTAMP,json NVARCHAR(MAX))",
tableName, Config._ID, Config._TYPE, Config._CREATORID, Config._TIMESTAMP, Config._UPDATED);
String sql = Utils.formatMessage("CREATE TABLE IF NOT EXISTS {0} ({1})", tableName, SQL_SCHEMA);
statement.execute(sql);
logger.info("Created SQL database table named '{}'.", tableName);
return true;
} catch (Exception e) {
logger.error("Failed to create a new table for appid '{}' in the SQL database", appid, logSqlError(e));
logger.error("Failed to create a new table for appid '{}' in the SQL database{}", appid, logSqlError(e));
}
return false;
}
Expand All @@ -164,7 +210,7 @@ public static boolean deleteTable(String appid) {
s.execute("DROP TABLE IF EXISTS " + tableName);
logger.info("Deleted table named '{}' from the SQL database.", tableName);
} catch (Exception e) {
logger.error("Failed to delete the table for appid '{}' in the SQL database", appid, logSqlError(e));
logger.error("Failed to delete the table for appid '{}' in the SQL database{}", appid, logSqlError(e));
}
return true;
}
Expand Down Expand Up @@ -197,10 +243,10 @@ protected static <P extends ParaObject> Map<String, P> readRows(String appid, Li
}
try (Connection connection = getConnection()) {
Map<String, P> results = new LinkedHashMap<>();
String table = getTableNameForAppid(appid);
String tableName = getTableNameForAppid(appid);
PreparedStatement p = connection.prepareStatement(
Utils.formatMessage("SELECT json FROM {0} WHERE {1} IN ({2})",
table, Config._ID, StringUtils.repeat("?", ",", ids.size())));
tableName, Config._ID, StringUtils.repeat("?", ",", ids.size())));
for (int i = 0; i < ids.size(); i++) {
p.setString(i + 1, ids.get(i));
results.put(ids.get(i), null);
Expand All @@ -214,7 +260,7 @@ protected static <P extends ParaObject> Map<String, P> readRows(String appid, Li
}
return results;
} catch (Exception e) {
logger.error("Failed to read rows for appid '{}' in the SQL database.", appid, logSqlError(e));
logger.error("Failed to read rows for appid '{}' in the SQL database{}", appid, logSqlError(e));
}
return Collections.emptyMap();
}
Expand All @@ -231,7 +277,19 @@ protected static <P extends ParaObject> void createRows(String appid, List<P> ob
}
try (Connection connection = getConnection()) {
String tableName = getTableNameForAppid(appid);
PreparedStatement p = connection.prepareStatement("MERGE INTO " + tableName + " VALUES (?,?,?,?,?,?)");
String sql;
if (useMySqlSyntax) {
sql = Utils.formatMessage("INSERT INTO {0} VALUES (?,?,?,?,?,?) " +
"ON DUPLICATE KEY UPDATE {1}=?,{2}=?,{3}=?,{4}=?",
tableName,
Config._TYPE,
Config._CREATORID,
Config._UPDATED,
JSON_FIELD_NAME);
} else {
sql = "MERGE INTO " + tableName + " VALUES (?,?,?,?,?,?)";
}
PreparedStatement p = connection.prepareStatement(sql);

for (P object : objects) {
if (StringUtils.isBlank(object.getId())) {
Expand All @@ -246,18 +304,32 @@ protected static <P extends ParaObject> void createRows(String appid, List<P> ob
p.setString(2, object.getType());
p.setString(3, object.getCreatorid());
p.setTimestamp(4, new Timestamp(object.getTimestamp()));
if (object.getUpdated() == null) {
final Timestamp updateTimetamp = object.getUpdated() == null ? null : new Timestamp(object.getUpdated());
if (updateTimetamp == null) {
p.setNull(5, Types.TIMESTAMP);
} else {
p.setTimestamp(5, new Timestamp(object.getUpdated()));
p.setTimestamp(5, updateTimetamp);
}
final String objectJson = ParaObjectUtils.getJsonWriterNoIdent().
writeValueAsString(ParaObjectUtils.getAnnotatedFields(object, false));
p.setString(6, objectJson);

if (useMySqlSyntax) {
p.setString(7, object.getType());
p.setString(8, object.getCreatorid());
if (updateTimetamp == null) {
p.setNull(9, Types.TIMESTAMP);
} else {
p.setTimestamp(9, updateTimetamp);
}
p.setString(10, objectJson);
}
p.setString(6, ParaObjectUtils.getJsonWriterNoIdent().
writeValueAsString(ParaObjectUtils.getAnnotatedFields(object, false)));
p.addBatch();
}
logger.info("statement:" + p.toString());
p.executeBatch();
} catch (Exception e) {
logger.error("Failed to create rows for appid '{}' in the SQL database.", appid, logSqlError(e), e);
logger.error("Failed to create rows for appid '{}' in the SQL database{}", appid, logSqlError(e), e);
}
}

Expand Down Expand Up @@ -310,7 +382,7 @@ protected static <P extends ParaObject> void updateRows(String appid, List<P> ob
}
p.executeBatch();
} catch (Exception e) {
logger.error("Failed to update rows for appid '{}' in the SQL database.", appid, logSqlError(e));
logger.error("Failed to update rows for appid '{}' in the SQL database{}", appid, logSqlError(e));
}
}

Expand All @@ -334,7 +406,7 @@ protected static <P extends ParaObject> void deleteRows(String appid, List<P> ob
}
p.execute();
} catch (Exception e) {
logger.error("Failed to delete rows for appid '{}' in the SQL database.", appid, logSqlError(e));
logger.error("Failed to delete rows for appid '{}' in the SQL database{}", appid, logSqlError(e));
}
}

Expand Down Expand Up @@ -378,14 +450,14 @@ protected static <P extends ParaObject> List<P> scanRows(String appid, Pager pag
}
return results;
} catch (Exception e) {
logger.error("Failed to scan a page for appid '{}' from the SQL database.", appid, logSqlError(e));
logger.error("Failed to scan a page for appid '{}' from the SQL database{}", appid, logSqlError(e));
}
return Collections.emptyList();
}

private static String logSqlError(Exception e) {
if (e == null || !SQLException.class.isAssignableFrom(e.getClass())) {
return null;
return "";
}
SQLException sqlException = (SQLException) e;
return " (Error Code: " + sqlException.getErrorCode() + ", SQLState: " + sqlException.getSQLState() + ")";
Expand Down

0 comments on commit 03d71e8

Please sign in to comment.