Trying out JDBC: raw, raw lambda, raw with pool and Spring.
authorGustavo Martin Morcuende <gu.martinm@gmail.com>
Sun, 29 Jun 2014 02:08:38 +0000 (04:08 +0200)
committerGustavo Martin Morcuende <gu.martinm@gmail.com>
Sun, 29 Jun 2014 02:08:38 +0000 (04:08 +0200)
Allgemeines/JDBC/pom.xml [new file with mode: 0644]
Allgemeines/JDBC/src/main/java/de/sql/tests/RawJDBCExample.java [new file with mode: 0644]
Allgemeines/JDBC/src/main/java/de/sql/tests/RawJDBCLambdaExample.java [new file with mode: 0644]
Allgemeines/JDBC/src/main/java/de/sql/tests/RawJDBCPoolExample.java [new file with mode: 0644]
Allgemeines/JDBC/src/main/java/de/sql/tests/RawSpringJDBCWithPoolExample.java [new file with mode: 0644]
Allgemeines/JDBC/src/main/java/de/sql/tests/SpringContextLocator.java [new file with mode: 0644]
Allgemeines/JDBC/src/main/java/de/sql/tests/SpringSQLExample.java [new file with mode: 0644]
Allgemeines/JDBC/src/main/java/de/sql/tests/springtransaction/NestedTransactionExample.java [new file with mode: 0644]
Allgemeines/JDBC/src/main/java/de/sql/tests/springtransaction/TransactionExample.java [new file with mode: 0644]
Allgemeines/JDBC/src/main/resources/log4j2.xml [new file with mode: 0644]
Allgemeines/JDBC/src/main/resources/spring-config.xml [new file with mode: 0644]

diff --git a/Allgemeines/JDBC/pom.xml b/Allgemeines/JDBC/pom.xml
new file mode 100644 (file)
index 0000000..5f4884e
--- /dev/null
@@ -0,0 +1,115 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
+                             http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>de.sql.tests</groupId>
+    <artifactId>sql-tests</artifactId>
+    <packaging>jar</packaging>
+    <version>1.0-SNAPSHOT</version>
+    <name>sql-tests</name>
+    <url>http://gumartinm.name</url>
+    <description>SQL Tests</description>
+    <organization>
+        <name>Gustavo Martin Morcuende</name>
+        <url>http://www.gumartinm.name</url>
+    </organization>
+    <scm>
+        <developerConnection>scm:git:http://git.gumartinm.name/SQLTest</developerConnection>
+        <url>http://git.gumartinm.name/SQLTest</url>
+    </scm>
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <spring.version>4.0.5.RELEASE</spring.version>
+    </properties>
+    <dependencies>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-context</artifactId>
+            <version>${spring.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-jdbc</artifactId>
+            <version>${spring.version}</version>
+        </dependency>
+        <!--
+            ********************************************************************
+                SLF4J AND LOG4J 2. See: http://logging.apache.org/log4j/2.x/
+            ********************************************************************
+        -->
+        <!--
+            1/2 Required dependency for log4j 2 with slf4j: binding
+        -->
+        <dependency>
+            <groupId>org.apache.logging.log4j</groupId>
+            <artifactId>log4j-slf4j-impl</artifactId>
+            <version>2.0-rc1</version>
+        </dependency>
+        <!--
+            2/2 Required dependency for log4j 2 with slf4j: log4j 2 maven plugin
+        -->
+        <dependency>
+            <groupId>org.apache.logging.log4j</groupId>
+            <artifactId>log4j-core</artifactId>
+            <version>2.0-rc1</version>
+        </dependency>
+        <dependency>
+            <groupId>cglib</groupId>
+            <artifactId>cglib</artifactId>
+            <version>2.2.2</version>
+        </dependency>
+        <dependency>
+            <groupId>com.mchange</groupId>
+            <artifactId>c3p0</artifactId>
+            <version>0.9.2.1</version>
+        </dependency>
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+            <!-- I just have the source code for this version -->
+            <version>5.1.6</version>
+        </dependency>
+    </dependencies>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>3.1</version>
+                <configuration>
+                    <source>1.8</source>
+                    <target>1.8</target>
+                    <encoding>${project.build.sourceEncoding}</encoding>
+                    <compilerArgument>-Xlint:deprecation</compilerArgument>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-resources-plugin</artifactId>
+                <version>2.6</version>
+                <configuration>
+                    <encoding>${project.build.sourceEncoding}</encoding>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-jar-plugin</artifactId>
+                <version>2.3.1</version>
+                <configuration>
+                    <archive>
+                        <manifestEntries>
+                            <Specification-Title>${project.description}</Specification-Title>
+                            <Specification-Version>${project.version}</Specification-Version>
+                            <Specification-Vendor>${project.organization.name}</Specification-Vendor>
+                            <Implementation-Title>${project.description}</Implementation-Title>
+                            <Implementation-Version>${project.version}</Implementation-Version>
+                            <Implementation-Vendor>${project.organization.name}</Implementation-Vendor>
+                        </manifestEntries>
+                    </archive>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>
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 (file)
index 0000000..bed8b55
--- /dev/null
@@ -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&amp;useUnicode=true&amp;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 (file)
index 0000000..a2050e0
--- /dev/null
@@ -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> {
+        TResult executeStatement(final Statement statement) throws SQLException;
+    }
+
+    private interface ExecuteResultSet<TResult> {
+        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<ResultSet> executeStatement,
+            final ExecuteResultSet<ResultSet> 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&amp;useUnicode=true&amp;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 (file)
index 0000000..5d543c3
--- /dev/null
@@ -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&amp;useUnicode=true&amp;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 (file)
index 0000000..6813e83
--- /dev/null
@@ -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<String, Object> parameters = new HashMap<String, Object>();
+        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&amp;useUnicode=true&amp;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 (file)
index 0000000..f493d38
--- /dev/null
@@ -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 (file)
index 0000000..4ed46e1
--- /dev/null
@@ -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 (file)
index 0000000..60f43bb
--- /dev/null
@@ -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 (file)
index 0000000..3fec523
--- /dev/null
@@ -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 (file)
index 0000000..18a4008
--- /dev/null
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Configuration status="trace" strict="true"
+                name="XMLConfigTest" packages="org.apache.logging.log4j.test">
+    <Appenders>
+        <Appender type="Console" name="STDOUT">
+            <PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n"/>
+        </Appender>
+    </Appenders>
+    <Loggers>
+        <Root level="trace">
+            <AppenderRef ref="STDOUT"/>
+        </Root>
+    </Loggers>
+</Configuration>
diff --git a/Allgemeines/JDBC/src/main/resources/spring-config.xml b/Allgemeines/JDBC/src/main/resources/spring-config.xml
new file mode 100644 (file)
index 0000000..f1d9040
--- /dev/null
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns:aop="http://www.springframework.org/schema/aop"
+       xmlns:tx="http://www.springframework.org/schema/tx"
+       xsi:schemaLocation="http://www.springframework.org/schema/beans
+                           http://www.springframework.org/schema/beans/spring-beans.xsd
+                           http://www.springframework.org/schema/tx
+                           http://www.springframework.org/schema/tx/spring-tx.xsd
+                           http://www.springframework.org/schema/aop
+                           http://www.springframework.org/schema/aop/spring-aop.xsd">
+
+
+    <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>
+
+       <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
+                <property name="user" value="root"/>
+                <property name="password" value=""/>
+                <property name="driverClass" value="com.mysql.jdbc.Driver"/>
+                <property name="jdbcUrl" value="jdbc:mysql://127.0.0.1:3306/n2a?autoReconnect=true&amp;useUnicode=true&amp;characterEncoding=UTF-8"/>
+                <property name="initialPoolSize" value="5"/>
+                <property name="maxPoolSize" value="35"/>
+                <property name="minPoolSize" value="10"/>
+                <property name="acquireIncrement" value="1"/>
+                <property name="acquireRetryAttempts" value="5"/>
+                <property name="acquireRetryDelay" value="1000"/>
+                <property name="automaticTestTable" value="con_test"/>
+                <property name="checkoutTimeout" value="5000"/>
+    </bean>
+       
+    <bean id="transactionExample" class="de.spring.example.web.TransactionExample"> 
+        <property name="dataSource" ref="dataSource"/>
+        <property name="nestedTransactionExample" ref="testB"/>
+    </bean>
+    
+    <bean id="nestedTransactionExample" class="de.spring.example.web.NestedTransactionExample"> 
+        <property name="dataSource" ref="dataSource"/>
+    </bean>
+    
+</beans>