From: Gustavo Martin Morcuende Date: Sun, 29 Jun 2014 02:08:38 +0000 (+0200) Subject: Trying out JDBC: raw, raw lambda, raw with pool and Spring. X-Git-Url: https://git.gumartinm.name/?a=commitdiff_plain;h=48e5275f75de910e3c5d02749e0f289b613f5dfb;p=JavaForFun Trying out JDBC: raw, raw lambda, raw with pool and Spring. --- diff --git a/Allgemeines/JDBC/pom.xml b/Allgemeines/JDBC/pom.xml new file mode 100644 index 0000000..5f4884e --- /dev/null +++ b/Allgemeines/JDBC/pom.xml @@ -0,0 +1,115 @@ + + + 4.0.0 + de.sql.tests + sql-tests + jar + 1.0-SNAPSHOT + sql-tests + http://gumartinm.name + SQL Tests + + Gustavo Martin Morcuende + http://www.gumartinm.name + + + scm:git:http://git.gumartinm.name/SQLTest + http://git.gumartinm.name/SQLTest + + + UTF-8 + 4.0.5.RELEASE + + + + org.springframework + spring-context + ${spring.version} + + + org.springframework + spring-jdbc + ${spring.version} + + + + + org.apache.logging.log4j + log4j-slf4j-impl + 2.0-rc1 + + + + org.apache.logging.log4j + log4j-core + 2.0-rc1 + + + cglib + cglib + 2.2.2 + + + com.mchange + c3p0 + 0.9.2.1 + + + mysql + mysql-connector-java + + 5.1.6 + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.1 + + 1.8 + 1.8 + ${project.build.sourceEncoding} + -Xlint:deprecation + + + + org.apache.maven.plugins + maven-resources-plugin + 2.6 + + ${project.build.sourceEncoding} + + + + org.apache.maven.plugins + maven-jar-plugin + 2.3.1 + + + + ${project.description} + ${project.version} + ${project.organization.name} + ${project.description} + ${project.version} + ${project.organization.name} + + + + + + + diff --git a/Allgemeines/JDBC/src/main/java/de/sql/tests/RawJDBCExample.java b/Allgemeines/JDBC/src/main/java/de/sql/tests/RawJDBCExample.java new file mode 100644 index 0000000..bed8b55 --- /dev/null +++ b/Allgemeines/JDBC/src/main/java/de/sql/tests/RawJDBCExample.java @@ -0,0 +1,100 @@ +package de.sql.tests; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class RawJDBCExample { + private static final Logger logger = LoggerFactory.getLogger(RawJDBCExample.class); + private static final String DB_URL = + "jdbc:mysql://127.0.0.1:3306/n2a?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8"; + + public static void main(final String[] args) { + Connection connection = null; + Statement statement = null; + ResultSet answer = null; + PreparedStatement preparedStatement = null; + try { + // 1. Register JDBC driver + // + // Register JDBC driver (by itself) with the DriverManager!!! + // (see static initializers in com.mysql.jdbc.Driver) + // + // otherwise, you could do it like this: + // DriverManager.registerDriver(new Driver()); (it should be the same) + // + Class.forName("com.mysql.jdbc.Driver"); + + // 2. Open a connection + logger.info("Connecting to database"); + connection = DriverManager.getConnection(RawJDBCExample.DB_URL, "root", ""); + + // 3. Execute some query: statement + logger.info("Execute statement"); + statement = connection.createStatement(); + answer = statement.executeQuery("SELECT * FROM AD"); + // Loop through ResultSet a row at a time + while (answer.next()) { + final int adID = answer.getInt("AD_ID"); + final int adCode = answer.getInt("AD_CODE"); + final String description = answer.getString("DESCRIPTION"); + logger.info("AD_ID: " + adID + " AD_CODE: " + adCode + " DESCRIPTION: " + description); + } + logger.info("Statement executed successfully"); + + // 4. Execute some query: prepared statement + logger.info("Execute prepared statement"); + preparedStatement = connection.prepareStatement("SELECT * FROM AD"); + preparedStatement.executeQuery(); + // Loop through ResultSet a row at a time + while (answer.next()) { + final int adID = answer.getInt("AD_ID"); + final int adCode = answer.getInt("AD_CODE"); + final String description = answer.getString("DESCRIPTION"); + logger.info("AD_ID: " + adID + " AD_CODE: " + adCode + " DESCRIPTION: " + description); + } + logger.info("Prepared statement executed successfully"); + } catch (final ClassNotFoundException | SQLException e) { + logger.error("Program error: ", e); + } finally { + if (answer != null) { + // Explicitly close the cursor and connection. NOTE: IT IS NOT THE SAME AS "DECLARE CURSOR" OF SQL + // This is a cursor in program memory not in DBMS!!! + try { + answer.close(); // Cursor + } catch (final SQLException e) { + logger.error("Error while closing cursor: ", e); + } + } + if (statement != null) { + // I think closing ResultSet should be enough... + try { + statement.close(); + } catch (final SQLException e) { + logger.error("Error while closing statement: ", e); + } + } + if (preparedStatement != null) { + // I think closing ResultSet should be enough... + try { + preparedStatement.close(); + } catch (final SQLException e) { + logger.error("Error while closing prepared statement: ", e); + } + } + if (connection != null) { + try { + connection.close(); + } catch (final SQLException e) { + logger.error("Error while closing connection: ", e); + } + } + } + } +} diff --git a/Allgemeines/JDBC/src/main/java/de/sql/tests/RawJDBCLambdaExample.java b/Allgemeines/JDBC/src/main/java/de/sql/tests/RawJDBCLambdaExample.java new file mode 100644 index 0000000..a2050e0 --- /dev/null +++ b/Allgemeines/JDBC/src/main/java/de/sql/tests/RawJDBCLambdaExample.java @@ -0,0 +1,100 @@ +package de.sql.tests; + +import java.beans.PropertyVetoException; +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; + +import javax.sql.DataSource; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.mchange.v2.c3p0.ComboPooledDataSource; + +public class RawJDBCLambdaExample { + private static final Logger logger = LoggerFactory.getLogger(RawJDBCLambdaExample.class); + + /** + * Carry out query – method returns a ResultSet object + * + */ + private interface ExecuteStatement { + TResult executeStatement(final Statement statement) throws SQLException; + } + + private interface ExecuteResultSet { + void executeResultSet(final TResult resultSet) throws SQLException; + } + + public static void main(final String[] args) throws PropertyVetoException, SQLException { + + // Just for fun, programmatic configuration. + final DataSource dataSource = RawJDBCLambdaExample.getDataSource(); + try { + // The database connection (taken from c3p0 pool) + final Connection connection = dataSource.getConnection(); + + RawJDBCLambdaExample.executeQuery( + connection, + statement -> statement.executeQuery("SELECT * FROM AD"), + answer -> + { + // Loop through ResultSet a row at a time + while (answer.next()) { + final int adID = answer.getInt("AD_ID"); + final int adCode = answer.getInt("AD_CODE"); + final String description = answer.getString("DESCRIPTION"); + logger.info("AD_ID: " + adID + " AD_CODE: " + + adCode + " DESCRIPTION: " + description); + } + } + ); + } finally { + // Now we close the whole pool :) + ((ComboPooledDataSource)dataSource).close(); + } + } + + private static void executeQuery(final Connection connection, + final ExecuteStatement executeStatement, + final ExecuteResultSet executeResultSet) throws SQLException { + + try (final Statement statement = connection.createStatement(); + final ResultSet answer = executeStatement.executeStatement(statement)) { + executeResultSet.executeResultSet(answer); + } + + // Explicitly close the cursor and connection. NOTE: IT IS NOT THE SAME AS + // "DECLARE CURSOR" OF SQL. This is a cursor in program memory not in DBMS!!! + // answer.close(); // Cursor + + // NOTE: in this case I do not care if we hide Exceptions while closing!!! + } + + /** + * Just for fun, programmatic configuration. + * @return + * @throws PropertyVetoException + */ + private static DataSource getDataSource() throws PropertyVetoException { + final ComboPooledDataSource pool = new ComboPooledDataSource(); + + pool.setUser("root"); + pool.setPassword(""); + // We are going to use JDBC driver + pool.setDriverClass("com.mysql.jdbc.Driver"); + pool.setJdbcUrl("jdbc:mysql://127.0.0.1:3306/n2a?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8"); + pool.setInitialPoolSize(5); + pool.setMaxPoolSize(35); + pool.setMinPoolSize(10); + pool.setAcquireIncrement(1); + pool.setAcquireRetryAttempts(5); + pool.setAcquireRetryDelay(1000); + pool.setAutomaticTestTable("con_test"); + pool.setCheckoutTimeout(5000); + + return pool; + } +} diff --git a/Allgemeines/JDBC/src/main/java/de/sql/tests/RawJDBCPoolExample.java b/Allgemeines/JDBC/src/main/java/de/sql/tests/RawJDBCPoolExample.java new file mode 100644 index 0000000..5d543c3 --- /dev/null +++ b/Allgemeines/JDBC/src/main/java/de/sql/tests/RawJDBCPoolExample.java @@ -0,0 +1,146 @@ +package de.sql.tests; + +import java.beans.PropertyVetoException; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; + +import javax.sql.DataSource; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.mchange.v2.c3p0.ComboPooledDataSource; + +public class RawJDBCPoolExample { + private static final Logger logger = LoggerFactory.getLogger(RawJDBCPoolExample.class); + + public static void main(final String[] args) throws PropertyVetoException { + // Just for fun, programmatic configuration. + final DataSource dataSource = getDataSource(); + + // 1. Using Statement + Connection connection = null; + Statement statement = null; + ResultSet answer = null; + try { + // The database connection (taken from c3p0 pool) + connection = dataSource.getConnection(); + // Create a statement object for executing the query + statement = connection.createStatement(); + // Carry out query – method returns a ResultSet object + answer = statement.executeQuery("SELECT * FROM AD"); + // Loop through ResultSet a row at a time + while (answer.next()) { + final int adID = answer.getInt("AD_ID"); + final int adCode = answer.getInt("AD_CODE"); + final String description = answer.getString("DESCRIPTION"); + logger.info("AD_ID: " + adID + " AD_CODE: " + adCode + " DESCRIPTION: " + description); + } + + } catch (final SQLException e) { + logger.error("Using Statement: ", e); + } finally { + if (answer != null) { + // Explicitly close the cursor and connection. NOTE: IT IS NOT THE SAME AS "DECLARE CURSOR" OF SQL + // This is a cursor in program memory not in DBMS!!! + try { + answer.close(); // Cursor + } catch (final SQLException e) { + logger.error("Error while closing cursor: ", e); + } + } + if (statement != null) { + try { + statement.close(); + } catch (final SQLException e) { + logger.error("Error while closing statement: ", e); + } + } + if (connection != null) { + // try { + // connection.close(); final I do not think, I should do it final when having a connection pool :/ + // } catch (final SQLException e) { + // logger.error("Error while closing connection: ", e); + // } + } + } + + + // 2. Using PreparedStatement + PreparedStatement preparedStatement = null; + answer = null; + try { + // The database connection (taken from c3p0 pool) + connection = dataSource.getConnection(); + // Create a statement object for executing the query + preparedStatement = connection.prepareStatement("SELECT * FROM AD"); + // Carry out query – method returns a ResultSet object + answer = preparedStatement.executeQuery(); + // Loop through ResultSet a row at a time + while (answer.next()) { + final int adID = answer.getInt("AD_ID"); + final int adCode = answer.getInt("AD_CODE"); + final String description = answer.getString("DESCRIPTION"); + logger.info("AD_ID: " + adID + " AD_CODE: " + adCode + " DESCRIPTION: " + description); + } + } catch (final SQLException e) { + logger.error("Using PreparedStatement: ", e); + } finally { + if (answer != null) { + // Explicitly close the cursor and connection. NOTE: IT IS NOT THE SAME AS "DECLARE CURSOR" OF SQL + // This is a cursor in program memory not in DBMS!!! + try { + answer.close(); // Cursor + } catch (final SQLException e) { + logger.error("Error while closing cursor: ", e); + } + } + if (preparedStatement != null) { + // I think closing ResultSet should be enough... + try { + preparedStatement.close(); + } catch (final SQLException e) { + logger.error("Error while closing prepared statement: ", e); + } + } + if (connection != null) { + // try { + // connection.close(); final I do not think, I should do it final when having a connection pool :/ + // } catch (final SQLException e) { + // logger.error("Error while closing connection: ", e); + // } + } + } + + // Now we close the whole pool :) + ((ComboPooledDataSource)dataSource).close(); + } + + /** + * Just for fun, programmatic configuration. + * @return + * @throws PropertyVetoException + */ + private static DataSource getDataSource() throws PropertyVetoException { + final ComboPooledDataSource pool = new ComboPooledDataSource(); + + pool.setUser("root"); + pool.setPassword(""); + // We are going to use JDBC driver + pool.setDriverClass("com.mysql.jdbc.Driver"); + pool.setJdbcUrl("jdbc:mysql://127.0.0.1:3306/n2a?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8"); + pool.setInitialPoolSize(5); + pool.setMaxPoolSize(35); + pool.setMinPoolSize(10); + pool.setAcquireIncrement(1); + pool.setAcquireRetryAttempts(5); + pool.setAcquireRetryDelay(1000); + pool.setAutomaticTestTable("con_test"); + pool.setCheckoutTimeout(5000); + + return pool; + } +} diff --git a/Allgemeines/JDBC/src/main/java/de/sql/tests/RawSpringJDBCWithPoolExample.java b/Allgemeines/JDBC/src/main/java/de/sql/tests/RawSpringJDBCWithPoolExample.java new file mode 100644 index 0000000..6813e83 --- /dev/null +++ b/Allgemeines/JDBC/src/main/java/de/sql/tests/RawSpringJDBCWithPoolExample.java @@ -0,0 +1,85 @@ +package de.sql.tests; + +import java.beans.PropertyVetoException; +import java.util.HashMap; +import java.util.Map; + +import javax.sql.DataSource; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.jdbc.core.JdbcOperations; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.jdbc.core.simple.SimpleJdbcInsert; +import org.springframework.jdbc.core.simple.SimpleJdbcInsertOperations; +import org.springframework.jdbc.core.simple.SimpleJdbcOperations; +import org.springframework.jdbc.core.simple.SimpleJdbcTemplate; + +import com.mchange.v2.c3p0.ComboPooledDataSource; + +public class RawSpringJDBCWithPoolExample { + private static final Logger logger = LoggerFactory.getLogger(RawSpringJDBCWithPoolExample.class); + + + public static void main(final String[] args) throws PropertyVetoException { + // Just for fun, programmatic configuration. + final DataSource dataSource = getDataSource(); + + + final Map parameters = new HashMap(); + parameters.put("AD_ID", 1); + + + // 3. Using Spring JdbcTemplate + final JdbcOperations jdbcTemplate = new JdbcTemplate(dataSource); + jdbcTemplate.execute("SELECT * FROM AD"); + + + // 4. Using SimpleJdbcTemplate + final SimpleJdbcOperations simpleJdbcTemplate = new SimpleJdbcTemplate(dataSource); + final int deprecatedResult = simpleJdbcTemplate.queryForInt("SELECT * FROM AD", parameters); + logger.info("Deprecated result: " + deprecatedResult); + + + // 5. Using NamedParameterJdbcTemplate + final NamedParameterJdbcOperations namedParameterJdbcOperations = new NamedParameterJdbcTemplate(dataSource); + final int namedResult = namedParameterJdbcOperations.queryForInt("SELECT * FROM AD", parameters); + logger.info("Named result: " + namedResult); + + + // 6. Using Spring SimpleJdbcInsert + final SimpleJdbcInsertOperations simpleJdbcInsert = new SimpleJdbcInsert(dataSource); + simpleJdbcInsert.withTableName("ad"); + simpleJdbcInsert.execute(parameters); + + // Now we close the whole pool :) + ((ComboPooledDataSource)dataSource).close(); + } + + /** + * Just for fun, programmatic configuration. + * @return + * @throws PropertyVetoException + */ + private static DataSource getDataSource() throws PropertyVetoException { + final ComboPooledDataSource pool = new ComboPooledDataSource(); + + pool.setUser("root"); + pool.setPassword(""); + // We are going to use the JDBC driver + pool.setDriverClass("com.mysql.jdbc.Driver"); + pool.setJdbcUrl("jdbc:mysql://127.0.0.1:3306/n2a?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8"); + pool.setInitialPoolSize(5); + pool.setMaxPoolSize(35); + pool.setMinPoolSize(10); + pool.setAcquireIncrement(1); + pool.setAcquireRetryAttempts(5); + pool.setAcquireRetryDelay(1000); + pool.setAutomaticTestTable("con_test"); + pool.setCheckoutTimeout(5000); + + return pool; + } +} diff --git a/Allgemeines/JDBC/src/main/java/de/sql/tests/SpringContextLocator.java b/Allgemeines/JDBC/src/main/java/de/sql/tests/SpringContextLocator.java new file mode 100644 index 0000000..f493d38 --- /dev/null +++ b/Allgemeines/JDBC/src/main/java/de/sql/tests/SpringContextLocator.java @@ -0,0 +1,62 @@ +package de.sql.tests; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.ApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; + +/** + * Spring context locator. + * + */ +public final class SpringContextLocator { + private static final Logger logger = LoggerFactory.getLogger(SpringContextLocator.class); + + /** Spring ApplicationContext **/ + private final ApplicationContext context; + + /** Spring Context **/ + private static final String SPRING_CONFIG_CONTEXT="spring-config.xml"; + + + /** + * Private constructor. Singleton pattern. + */ + private SpringContextLocator() { + final String[] factoryFiles = new String[] { SPRING_CONFIG_CONTEXT }; + + logger.info("Loading context files " + SpringContextLocator.SPRING_CONFIG_CONTEXT); + + this.context = new ClassPathXmlApplicationContext(factoryFiles); + + logger.info("The context has been loaded successfully!! "); + } + + /** + * SingletonHolder Thread-safety. To use an Enum class (see Effective Java + * Second Edition) if we need serialization and thread-safety. + */ + private static class SingletonHolder { + public static final SpringContextLocator INSTANCE = new SpringContextLocator(); + } + + /** + * Return singleton instance. Thread-safety. + * + * @return Singleton instance. + */ + public static SpringContextLocator getInstance() { + return SingletonHolder.INSTANCE; + } + + /** + * Return bean from application context. + * + * @param beanId + * Bean's id. + * @return The bean instance. + */ + public Object getBean(final String beanId) { + return this.context.getBean(beanId); + } +} diff --git a/Allgemeines/JDBC/src/main/java/de/sql/tests/SpringSQLExample.java b/Allgemeines/JDBC/src/main/java/de/sql/tests/SpringSQLExample.java new file mode 100644 index 0000000..4ed46e1 --- /dev/null +++ b/Allgemeines/JDBC/src/main/java/de/sql/tests/SpringSQLExample.java @@ -0,0 +1,15 @@ +package de.sql.tests; + +import de.sql.tests.springtransaction.TransactionExample; + +public class SpringSQLExample { + + + public static void main(final String[] args) { + + final TransactionExample test = + (TransactionExample) SpringContextLocator.getInstance().getBean("transactionExample"); + test.doExample(); + + } +} diff --git a/Allgemeines/JDBC/src/main/java/de/sql/tests/springtransaction/NestedTransactionExample.java b/Allgemeines/JDBC/src/main/java/de/sql/tests/springtransaction/NestedTransactionExample.java new file mode 100644 index 0000000..60f43bb --- /dev/null +++ b/Allgemeines/JDBC/src/main/java/de/sql/tests/springtransaction/NestedTransactionExample.java @@ -0,0 +1,34 @@ +package de.sql.tests.springtransaction; + +import javax.sql.DataSource; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; + + +public class NestedTransactionExample { + private static final Logger logger = LoggerFactory.getLogger(NestedTransactionExample.class); + private DataSource dataSource; + + // Propagation.NESTED must be creating a SAVEPOINT to roll back when Exception + // (at least in InnoDB) + @Transactional(propagation=Propagation.NESTED) + public void doExample() + { + logger.info("BEGIN: NestedTransactionExample"); + + final JdbcTemplate jdbcTemplate = new JdbcTemplate(this.dataSource); + jdbcTemplate.execute("INSERT INTO AD VALUES (16)"); + + logger.info("END: NestedTransactionExample"); + throw new RuntimeException("GOING TO REOLLBACK NESTED TRANSACTION"); + } + + + public void setDataSource (final DataSource dataSource) { + this.dataSource = dataSource; + } +} diff --git a/Allgemeines/JDBC/src/main/java/de/sql/tests/springtransaction/TransactionExample.java b/Allgemeines/JDBC/src/main/java/de/sql/tests/springtransaction/TransactionExample.java new file mode 100644 index 0000000..3fec523 --- /dev/null +++ b/Allgemeines/JDBC/src/main/java/de/sql/tests/springtransaction/TransactionExample.java @@ -0,0 +1,37 @@ +package de.sql.tests.springtransaction; + +import javax.sql.DataSource; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.transaction.annotation.Transactional; + + +public class TransactionExample { + private static final Logger logger = LoggerFactory.getLogger(TransactionExample.class); + private DataSource dataSource; + private NestedTransactionExample nestedTransactionExample; + + @Transactional + public void doExample() + { + final JdbcTemplate jdbcTemplate = new JdbcTemplate(this.dataSource); + jdbcTemplate.execute("INSERT INTO AD VALUES (16)"); + + try { + this.nestedTransactionExample.doExample(); + } catch(final RuntimeException e) { + logger.error("Nested transaction performed roll back: ", e); + } + } + + public void setDataSource (final DataSource dataSource) { + this.dataSource = dataSource; + } + + public void setNestedTransactionExample ( + final NestedTransactionExample nestedTransactionExample) { + this.nestedTransactionExample = nestedTransactionExample; + } +} diff --git a/Allgemeines/JDBC/src/main/resources/log4j2.xml b/Allgemeines/JDBC/src/main/resources/log4j2.xml new file mode 100644 index 0000000..18a4008 --- /dev/null +++ b/Allgemeines/JDBC/src/main/resources/log4j2.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/Allgemeines/JDBC/src/main/resources/spring-config.xml b/Allgemeines/JDBC/src/main/resources/spring-config.xml new file mode 100644 index 0000000..f1d9040 --- /dev/null +++ b/Allgemeines/JDBC/src/main/resources/spring-config.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +