diff --git a/README.md b/README.md
index 81642d7..75d277c 100644
--- a/README.md
+++ b/README.md
@@ -1,15 +1,54 @@
Simple example of how to use MyBatis with annotations.
-This example uses an embedded H2 database by default. This allows you to check the project out and immediately
-run a clean build via Maven:
+This example uses PostgreSQL with Testcontainers for automated testing. Tests automatically spin up a PostgreSQL
+container, run the tests, and clean up - no manual database setup required!
-``mvn clean verify
-``
+## Quick Start
-In addition, a MySQL Workbench file is included, along with a sample MyBatis generator file. You can use these
-to explore more complex mappings - for example, to use the generator with an existing schema.
+Simply run the tests via Maven. Testcontainers will automatically handle the PostgreSQL setup:
+
+```bash
+mvn clean verify
+```
+
+**Note:** Docker must be running for tests to work, as Testcontainers manages PostgreSQL containers automatically.
+
+## Manual Local Development (Optional)
+
+If you want to run PostgreSQL manually for development, use the included docker-compose.yml:
+
+```bash
+# Start PostgreSQL
+docker-compose up -d
+
+# Stop PostgreSQL
+docker-compose down
+
+# Stop and remove data
+docker-compose down -v
+```
+
+The PostgreSQL instance will be available at `localhost:5432` with:
+- Database: `testdb`
+- Username: `test`
+- Password: `test`
## Requirements
-- [Maven 3.1.0](http://maven.apache.org/)
-- Java 1.7+
+- [Maven 3.9.0+](http://maven.apache.org/)
+- Java 21+ (LTS)
+- Docker (for Testcontainers and docker-compose)
+
+## Dependencies
+
+This project uses the following major dependencies:
+- MyBatis 3.5.19
+- JUnit 5 (Jupiter) 5.11.4
+- Log4j 2.24.0
+- PostgreSQL JDBC Driver 42.7.7
+- Testcontainers 1.20.1
+
+## Additional Resources
+
+A MySQL Workbench file is included, along with a sample MyBatis generator file. You can use these
+to explore more complex mappings - for example, to use the generator with an existing schema.
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 0000000..078450b
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,22 @@
+version: '3.8'
+
+services:
+ postgres:
+ image: postgres:16-alpine
+ container_name: mybatis-postgres
+ environment:
+ POSTGRES_DB: testdb
+ POSTGRES_USER: test
+ POSTGRES_PASSWORD: test
+ ports:
+ - "5432:5432"
+ volumes:
+ - postgres_data:/var/lib/postgresql/data
+ healthcheck:
+ test: ["CMD-SHELL", "pg_isready -U test"]
+ interval: 10s
+ timeout: 5s
+ retries: 5
+
+volumes:
+ postgres_data:
diff --git a/pom.xml b/pom.xml
index 6e04e74..64d7e7f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -12,29 +12,59 @@
UTF-8
+ 21
+ 21
+ 5.11.4
+ 3.5.19
+ 2.24.0
+ 42.7.7
+ 1.20.1
- junit
- junit
- 4.12
+ org.junit.jupiter
+ junit-jupiter
+ ${junit.version}
test
org.mybatis
mybatis
- 3.3.0
+ ${mybatis.version}
- log4j
- log4j
- 1.2.17
+ org.apache.logging.log4j
+ log4j-core
+ ${log4j.version}
- com.h2database
- h2
- 1.4.189
+ org.apache.logging.log4j
+ log4j-api
+ ${log4j.version}
+
+
+ org.postgresql
+ postgresql
+ ${postgresql.version}
+
+
+ org.testcontainers
+ testcontainers
+ ${testcontainers.version}
+ test
+
+
+ org.testcontainers
+ postgresql
+ ${testcontainers.version}
+ test
+
+
+ org.testcontainers
+ junit-jupiter
+ ${testcontainers.version}
+ test
@@ -45,62 +75,62 @@
org.apache.maven.plugins
maven-site-plugin
- 3.4
+ 4.0.0-M16
org.apache.maven.plugins
maven-surefire-plugin
- 2.18.1
+ 3.5.2
org.apache.maven.plugins
maven-jar-plugin
- 2.6
+ 3.4.2
org.apache.maven.plugins
maven-antrun-plugin
- 1.8
+ 3.1.0
org.apache.maven.plugins
maven-assembly-plugin
- 2.5.4
+ 3.7.1
org.apache.maven.plugins
maven-release-plugin
- 2.5.2
+ 3.1.1
- org.apache.maven
+ org.apache.maven.plugins
maven-project-info-reports-plugin
- 2.7
+ 3.7.0
org.apache.maven.plugins
maven-dependency-plugin
- 2.10
+ 3.8.1
org.apache.maven.plugins
maven-clean-plugin
- 2.6.1
+ 3.4.0
org.apache.maven.plugins
maven-resources-plugin
- 2.7
+ 3.3.1
org.apache.maven.plugins
maven-deploy-plugin
- 2.8.2
+ 3.1.3
org.apache.maven.plugins
maven-install-plugin
- 2.5.2
+ 3.1.3
@@ -109,11 +139,9 @@
org.apache.maven.plugins
maven-compiler-plugin
- 3.3
+ 3.13.0
-
- 1.8
- 1.8
+ 21
@@ -131,7 +159,7 @@
org.apache.maven.doxia
doxia-module-markdown
- 1.6
+ 2.0.0-M12
@@ -145,15 +173,15 @@
org.apache.maven.plugins
maven-project-info-reports-plugin
- 2.7
+ 3.7.0
+ - you should use standard version numbering too! https://www.mojohaus.org/versions/versions-maven-plugin/version-rules.html -->
org.codehaus.mojo
versions-maven-plugin
- 2.1
+ 2.18.0
diff --git a/src/main/java/com/example/mybatis/TransactionTokenMapper.java b/src/main/java/com/example/mybatis/TransactionTokenMapper.java
index a3a1548..5a82791 100644
--- a/src/main/java/com/example/mybatis/TransactionTokenMapper.java
+++ b/src/main/java/com/example/mybatis/TransactionTokenMapper.java
@@ -17,7 +17,7 @@ public interface TransactionTokenMapper {
* of functionality to both intialize the database for test purposes as well as validating the bindings. For
* example, a standard schema() method and a validate() method, called as part of the factory setup.
*/
- @Update("create table trans_token (id bigint auto_increment, trans_id varchar, token_id varchar)")
+ @Update("create table trans_token (id bigserial primary key, trans_id varchar, token_id varchar)")
void schema();
@Select({
diff --git a/src/main/resources/Configuration.xml b/src/main/resources/Configuration.xml
index 61aacba..39d663b 100644
--- a/src/main/resources/Configuration.xml
+++ b/src/main/resources/Configuration.xml
@@ -9,20 +9,12 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
diff --git a/src/main/resources/log4j.xml b/src/main/resources/log4j.xml
deleted file mode 100644
index fc39356..0000000
--- a/src/main/resources/log4j.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml
new file mode 100644
index 0000000..32d4198
--- /dev/null
+++ b/src/main/resources/log4j2.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/test/java/com/example/mybatis/AppTest.java b/src/test/java/com/example/mybatis/AppTest.java
index f482dad..736f871 100644
--- a/src/test/java/com/example/mybatis/AppTest.java
+++ b/src/test/java/com/example/mybatis/AppTest.java
@@ -1,20 +1,50 @@
package com.example.mybatis;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.apache.ibatis.datasource.pooled.PooledDataSource;
+import org.apache.ibatis.io.Resources;
+import org.apache.ibatis.mapping.Environment;
+import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSession;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
-
+import org.apache.ibatis.session.SqlSessionFactory;
+import org.apache.ibatis.session.SqlSessionFactoryBuilder;
+import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.testcontainers.containers.PostgreSQLContainer;
+import org.testcontainers.junit.jupiter.Container;
+import org.testcontainers.junit.jupiter.Testcontainers;
+
+@Testcontainers
public class AppTest {
- @BeforeClass
+ @Container
+ static PostgreSQLContainer> postgres = new PostgreSQLContainer<>("postgres:16-alpine")
+ .withDatabaseName("testdb")
+ .withUsername("test")
+ .withPassword("test");
+
+ @BeforeAll
static public void testApp() {
- App.init();
+ // Create a custom configuration with Testcontainers PostgreSQL
+ PooledDataSource dataSource = new PooledDataSource();
+ dataSource.setDriver(postgres.getDriverClassName());
+ dataSource.setUrl(postgres.getJdbcUrl());
+ dataSource.setUsername(postgres.getUsername());
+ dataSource.setPassword(postgres.getPassword());
+
+ Environment environment = new Environment("development", new JdbcTransactionFactory(), dataSource);
+ Configuration config = new Configuration(environment);
+ config.setUseGeneratedKeys(true);
+ config.addMapper(TransactionTokenMapper.class);
+
+ App.factory = new SqlSessionFactoryBuilder().build(config);
assertNotNull(App.factory);
@@ -30,13 +60,13 @@ static public void testApp() {
private TransactionTokenMapper mapper = null;
private SqlSession session = null;
- @Before
+ @BeforeEach
public void setupSession() {
session = App.factory.openSession(); // This obtains a database connection!
mapper = session.getMapper(TransactionTokenMapper.class);
}
- @After
+ @AfterEach
public void closeSession() {
session.commit(); // This commits the data to the database. Required even if auto-commit=true
session.close(); // This releases the connection