diff --git a/pom.xml b/pom.xml
index 1b8f30e92..8173972bd 100644
--- a/pom.xml
+++ b/pom.xml
@@ -225,6 +225,7 @@
In this example we will use the Table Module pattern to implement register + * and login methods for the records stored in the user table. The main + * method will initialise an instance of {@link UserTableModule} and use it to + * handle the domain logic for the user table.
+ */ +@Slf4j +public final class App { + private static final String DB_URL = "jdbc:h2:~/test"; + + /** + * Private constructor. + */ + private App() { + + } + + /** + * Program entry point. + * + * @param args command line args. + * @throws SQLException if any error occurs. + */ + public static void main(final String[] args) throws SQLException { + // Create data source and create the user table. + final var dataSource = createDataSource(); + createSchema(dataSource); + var userTableModule = new UserTableModule(dataSource); + + // Initialize two users. + var user1 = new User(1, "123456", "123456"); + var user2 = new User(2, "test", "password"); + + // Login and register using the instance of userTableModule. + userTableModule.registerUser(user1); + userTableModule.login(user1.getUsername(), user1.getPassword()); + userTableModule.login(user2.getUsername(), user2.getPassword()); + userTableModule.registerUser(user2); + userTableModule.login(user2.getUsername(), user2.getPassword()); + + deleteSchema(dataSource); + } + + private static void deleteSchema(final DataSource dataSource) + throws SQLException { + try (var connection = dataSource.getConnection(); + var statement = connection.createStatement()) { + statement.execute(UserTableModule.DELETE_SCHEMA_SQL); + } + } + + private static void createSchema(final DataSource dataSource) + throws SQLException { + try (var connection = dataSource.getConnection(); + var statement = connection.createStatement()) { + statement.execute(UserTableModule.CREATE_SCHEMA_SQL); + } + } + + private static DataSource createDataSource() { + var dataSource = new JdbcDataSource(); + dataSource.setURL(DB_URL); + return dataSource; + } +} diff --git a/table-module/src/main/java/com/iluwatar/tablemodule/User.java b/table-module/src/main/java/com/iluwatar/tablemodule/User.java new file mode 100644 index 000000000..ac307d450 --- /dev/null +++ b/table-module/src/main/java/com/iluwatar/tablemodule/User.java @@ -0,0 +1,23 @@ +package com.iluwatar.tablemodule; + +import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + + +/** + * A user POJO that represents the data that will be read from the data source. + */ +@Setter +@Getter +@ToString +@EqualsAndHashCode +@AllArgsConstructor +public class User { + private int id; + private String username; + private String password; + +} diff --git a/table-module/src/main/java/com/iluwatar/tablemodule/UserTableModule.java b/table-module/src/main/java/com/iluwatar/tablemodule/UserTableModule.java new file mode 100644 index 000000000..f1a4d0444 --- /dev/null +++ b/table-module/src/main/java/com/iluwatar/tablemodule/UserTableModule.java @@ -0,0 +1,96 @@ +package com.iluwatar.tablemodule; + +import java.sql.ResultSet; +import java.sql.SQLException; +import javax.sql.DataSource; + +import lombok.extern.slf4j.Slf4j; + + +/** + * This class organizes domain logic with the user table in the + * database. A single instance of this class contains the various + * procedures that will act on the data. + */ +@Slf4j +public class UserTableModule { + /** + * Public element for creating schema. + */ + public static final String CREATE_SCHEMA_SQL = + "CREATE TABLE IF NOT EXISTS USERS (ID NUMBER, USERNAME VARCHAR(30) " + + "UNIQUE,PASSWORD VARCHAR(30))"; + /** + * Public element for deleting schema. + */ + public static final String DELETE_SCHEMA_SQL = "DROP TABLE USERS IF EXISTS"; + private final DataSource dataSource; + + + /** + * Public constructor. + * + * @param userDataSource the data source in the database + */ + public UserTableModule(final DataSource userDataSource) { + this.dataSource = userDataSource; + } + + + /** + * Login using username and password. + * + * @param username the username of a user + * @param password the password of a user + * @return the execution result of the method + * @throws SQLException if any error + */ + public int login(final String username, final String password) + throws SQLException { + var sql = "select count(*) from USERS where username=? and password=?"; + ResultSet resultSet = null; + try (var connection = dataSource.getConnection(); + var preparedStatement = + connection.prepareStatement(sql) + ) { + var result = 0; + preparedStatement.setString(1, username); + preparedStatement.setString(2, password); + resultSet = preparedStatement.executeQuery(); + while (resultSet.next()) { + result = resultSet.getInt(1); + } + if (result == 1) { + LOGGER.info("Login successfully!"); + } else { + LOGGER.info("Fail to login!"); + } + return result; + } finally { + if (resultSet != null) { + resultSet.close(); + } + } + } + + /** + * Register a new user. + * + * @param user a user instance + * @return the execution result of the method + * @throws SQLException if any error + */ + public int registerUser(final User user) throws SQLException { + var sql = "insert into USERS (username, password) values (?,?)"; + try (var connection = dataSource.getConnection(); + var preparedStatement = + connection.prepareStatement(sql) + ) { + preparedStatement.setString(1, user.getUsername()); + preparedStatement.setString(2, user.getPassword()); + var result = preparedStatement.executeUpdate(); + LOGGER.info("Register successfully!"); + return result; + } + } +} diff --git a/table-module/src/test/java/com/iluwatar/tablemodule/AppTest.java b/table-module/src/test/java/com/iluwatar/tablemodule/AppTest.java new file mode 100644 index 000000000..cafae7cdb --- /dev/null +++ b/table-module/src/test/java/com/iluwatar/tablemodule/AppTest.java @@ -0,0 +1,16 @@ +package com.iluwatar.tablemodule; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; + +/** + * Tests that the table module example runs without errors. + */ +class AppTest { + + @Test + void shouldExecuteWithoutException() { + assertDoesNotThrow(() -> App.main(new String[]{})); + } +} diff --git a/table-module/src/test/java/com/iluwatar/tablemodule/UserTableModuleTest.java b/table-module/src/test/java/com/iluwatar/tablemodule/UserTableModuleTest.java new file mode 100644 index 000000000..86685f58d --- /dev/null +++ b/table-module/src/test/java/com/iluwatar/tablemodule/UserTableModuleTest.java @@ -0,0 +1,78 @@ +package com.iluwatar.tablemodule; + +import org.h2.jdbcx.JdbcDataSource; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import javax.sql.DataSource; +import java.sql.DriverManager; +import java.sql.SQLException; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +class UserTableModuleTest { + private static final String DB_URL = "jdbc:h2:~/test"; + + private static DataSource createDataSource() { + var dataSource = new JdbcDataSource(); + dataSource.setURL(DB_URL); + return dataSource; + } + + @BeforeEach + void setUp() throws SQLException { + try (var connection = DriverManager.getConnection(DB_URL); + var statement = connection.createStatement()) { + statement.execute(UserTableModule.DELETE_SCHEMA_SQL); + statement.execute(UserTableModule.CREATE_SCHEMA_SQL); + } + } + + @AfterEach + void tearDown() throws SQLException { + try (var connection = DriverManager.getConnection(DB_URL); + var statement = connection.createStatement()) { + statement.execute(UserTableModule.DELETE_SCHEMA_SQL); + } + } + + @Test + void loginShouldFail() throws SQLException { + var dataSource = createDataSource(); + var userTableModule = new UserTableModule(dataSource); + var user = new User(1, "123456", "123456"); + assertEquals(0, userTableModule.login(user.getUsername(), + user.getPassword())); + } + + @Test + void loginShouldSucceed() throws SQLException { + var dataSource = createDataSource(); + var userTableModule = new UserTableModule(dataSource); + var user = new User(1, "123456", "123456"); + userTableModule.registerUser(user); + assertEquals(1, userTableModule.login(user.getUsername(), + user.getPassword())); + } + + @Test + void registerShouldFail() throws SQLException { + var dataSource = createDataSource(); + var userTableModule = new UserTableModule(dataSource); + var user = new User(1, "123456", "123456"); + userTableModule.registerUser(user); + assertThrows(SQLException.class, () -> { + userTableModule.registerUser(user); + }); + } + + @Test + void registerShouldSucceed() throws SQLException { + var dataSource = createDataSource(); + var userTableModule = new UserTableModule(dataSource); + var user = new User(1, "123456", "123456"); + assertEquals(1, userTableModule.registerUser(user)); + } +} \ No newline at end of file diff --git a/table-module/src/test/java/com/iluwatar/tablemodule/UserTest.java b/table-module/src/test/java/com/iluwatar/tablemodule/UserTest.java new file mode 100644 index 000000000..669d86035 --- /dev/null +++ b/table-module/src/test/java/com/iluwatar/tablemodule/UserTest.java @@ -0,0 +1,131 @@ +package com.iluwatar.tablemodule; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class UserTest { + @Test + void testCanEqual() { + assertFalse((new User(1, "janedoe", "iloveyou")) + .canEqual("Other")); + } + + @Test + void testCanEqual2() { + var user = new User(1, "janedoe", "iloveyou"); + assertTrue(user.canEqual(new User(1, "janedoe", + "iloveyou"))); + } + + @Test + void testEquals1() { + var user = new User(1, "janedoe", "iloveyou"); + assertNotEquals("42", user); + } + + @Test + void testEquals2() { + var user = new User(1, "janedoe", "iloveyou"); + assertEquals(user, new User(1, "janedoe", + "iloveyou")); + } + + @Test + void testEquals3() { + var user = new User(123, "janedoe", "iloveyou"); + assertNotEquals(user, new User(1, "janedoe", + "iloveyou")); + } + + @Test + void testEquals4() { + var user = new User(1, null, "iloveyou"); + assertNotEquals(user, new User(1, "janedoe", + "iloveyou")); + } + + @Test + void testEquals5() { + var user = new User(1, "iloveyou", "iloveyou"); + assertNotEquals(user, new User(1, "janedoe", + "iloveyou")); + } + + @Test + void testEquals6() { + var user = new User(1, "janedoe", "janedoe"); + assertNotEquals(user, new User(1, "janedoe", + "iloveyou")); + } + + @Test + void testEquals7() { + var user = new User(1, "janedoe", null); + assertNotEquals(user, new User(1, "janedoe", + "iloveyou")); + } + + @Test + void testEquals8() { + var user = new User(1, null, "iloveyou"); + assertEquals(user, new User(1, null, + "iloveyou")); + } + + @Test + void testEquals9() { + var user = new User(1, "janedoe", null); + assertEquals(user, new User(1, "janedoe", + null)); + } + + @Test + void testHashCode1() { + assertEquals(-1758941372, (new User(1, "janedoe", + "iloveyou")).hashCode()); + + } + + @Test + void testHashCode2() { + assertEquals(-1332207447, (new User(1, null, + "iloveyou")).hashCode()); + } + + @Test + void testHashCode3() { + assertEquals(-426522485, (new User(1, "janedoe", + null)).hashCode()); + } + + @Test + void testSetId() { + var user = new User(1, "janedoe", "iloveyou"); + user.setId(2); + assertEquals(2, user.getId()); + } + + @Test + void testSetPassword() { + var user = new User(1, "janedoe", "tmp"); + user.setPassword("iloveyou"); + assertEquals("iloveyou", user.getPassword()); + } + + @Test + void testSetUsername() { + var user = new User(1, "tmp", "iloveyou"); + user.setUsername("janedoe"); + assertEquals("janedoe", user.getUsername()); + } + + @Test + void testToString() { + var user = new User(1, "janedoe", "iloveyou"); + assertEquals(String.format("User(id=%s, username=%s, password=%s)", + user.getId(), user.getUsername(), user.getPassword()), + user.toString()); + } +} +