package com.supaham.commons.jdbc.sql; import static com.google.common.base.Preconditions.checkNotNull; import com.jolbox.bonecp.BoneCP; import com.jolbox.bonecp.BoneCPConfig; import com.supaham.commons.database.JDBCAgent; import com.supaham.commons.jdbc.CDataSource; import org.jetbrains.annotations.Nullable; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import java.io.File; import java.sql.Connection; import java.sql.SQLException; import javax.annotation.Nonnull; import javax.sql.DataSource; /** * Represents a Spring JDBC implementation of {@link JDBCAgent} that uses {@link SQLConfig}. */ public class SpringJDBCAgent implements JDBCAgent { private final SQLConfig configuration; private final DataSource dataSource; /** * Creates a new {@link SpringJDBCAgent}. This method takes a {@link ClassLoader} as a parameter * which is used to look for the MySQL Driver class. This method is equivalent to calling {@code * SpringJDBCAgent.createAgent(MySQLConfig, null)}. * * @param config mysql configuration used to connect to the database * * @return a new instance of {@link SpringJDBCAgent} * * @throws ClassNotFoundException thrown if the mysql driver is not found. * @throws SQLException thrown if the {@code config} data fails to connect to a mysql database * @see #createAgent(SQLConfig, ClassLoader) */ public static SpringJDBCAgent createAgent(@Nonnull SQLConfig config) throws ClassNotFoundException, SQLException { return createAgent(config, Thread.currentThread().getContextClassLoader()); } /** * Creates a new {@link SpringJDBCAgent}. This method takes a {@link ClassLoader} as a parameter * which is used to look for the MySQL Driver class. * * @param config mysql configuration used to connect to the database * @param classLoader the {@link ClassLoader} that will load the the database Driver class * * @return a new instance of {@link SpringJDBCAgent} * * @throws ClassNotFoundException thrown if the mysql driver is not found. * @throws SQLException thrown if the {@code config} data fails to connect to a mysql database */ public static SpringJDBCAgent createAgent(@Nonnull SQLConfig config, @Nonnull ClassLoader classLoader) throws ClassNotFoundException, SQLException { return createAgent(config, classLoader, null); } /** * Creates a new {@link SpringJDBCAgent}. This method takes a {@link ClassLoader} as a parameter * which is used to look for the MySQL Driver class. * * @param config mysql configuration used to connect to the database * @param classLoader the {@link ClassLoader} that will load the the database Driver class * * @return a new instance of {@link SpringJDBCAgent} * * @throws ClassNotFoundException thrown if the mysql driver is not found. * @throws SQLException thrown if the {@code config} data fails to connect to a mysql database */ public static SpringJDBCAgent createAgent(@Nonnull SQLConfig config, @Nonnull BoneCPConfig boneCPConfig) throws ClassNotFoundException, SQLException { return createAgent(config, Thread.currentThread().getContextClassLoader(), boneCPConfig); } /** * Creates a new {@link SpringJDBCAgent}. This method takes a {@link ClassLoader} as a parameter * which is used to look for the MySQL Driver class. * * @param config mysql configuration used to connect to the database * @param classLoader the {@link ClassLoader} that will load the the database Driver class * @param boneCPConfig {@link BoneCPConfig} * * @return a new instance of {@link SpringJDBCAgent} * * @throws ClassNotFoundException thrown if the mysql driver is not found. * @throws SQLException thrown if the {@code config} data fails to connect to a mysql database */ public static SpringJDBCAgent createAgent(@Nonnull SQLConfig config, @Nullable ClassLoader classLoader, @Nullable BoneCPConfig boneCPConfig) throws ClassNotFoundException, SQLException { checkNotNull(classLoader, "class loader cannot be null."); ClassLoader previousClassLoader = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader(classLoader); if (boneCPConfig == null) { boneCPConfig = new BoneCPConfig(); boneCPConfig.setMinConnectionsPerPartition(3); boneCPConfig.setMaxConnectionsPerPartition(20); boneCPConfig.setPartitionCount(2); boneCPConfig.setConnectionTestStatement("SELECT 1"); } if (config instanceof MySQLConfig) { Class.forName("com.mysql.jdbc.Driver"); MySQLConfig mysql = (MySQLConfig) config; boneCPConfig.setJdbcUrl("jdbc:mysql://" + mysql.getIp() + ":" + mysql.getPort() + "/" + mysql.getDatabase()); boneCPConfig.setUser(mysql.getUsername()); boneCPConfig.setPassword(mysql.getPassword()); } else { Class.forName("org.sqlite.JDBC"); boneCPConfig.setJdbcUrl("jdbc:sqlite:" + new File(config.getFile()).getAbsolutePath()); } CDataSource dataSource = new CDataSource(new BoneCP(boneCPConfig)); Thread.currentThread().setContextClassLoader(previousClassLoader); return new SpringJDBCAgent(config, dataSource); } private SpringJDBCAgent(@Nonnull SQLConfig configuration, @Nonnull DataSource dataSource) throws SQLException { checkNotNull(configuration, "configuration cannot be null."); checkNotNull(dataSource, "data source cannot be null."); this.configuration = configuration; this.dataSource = dataSource; Connection connection = this.dataSource.getConnection(); checkNotNull(connection, "Failed to create connection, maybe the credentials are wrong?"); } /** * {@inheritDoc} */ @Nonnull @Override public DataSource getDataSource() { return this.dataSource; } /** * Gets this {@link SpringJDBCAgent}'s {@link SQLConfig}. * * @return {@link SQLConfig} */ public SQLConfig getConfiguration() { return configuration; } /** * Creates a new {@link JdbcTemplate} using this {@link SpringJDBCAgent}'s {@link DataSource}. * * @return newly constructed {@link JdbcTemplate} */ public JdbcTemplate createJdbcTemplate() { return new JdbcTemplate(getDataSource()); } /** * Creates a new {@link NamedParameterJdbcTemplate} using this {@link SpringJDBCAgent}'s {@link * DataSource}. * * @return newly constructed {@link NamedParameterJdbcTemplate} */ public NamedParameterJdbcTemplate createNamedParameterJdbcTemplate() { return new NamedParameterJdbcTemplate(getDataSource()); } }