Commit 64d67123 authored by Dr. Martin Goik's avatar Dr. Martin Goik

Surrogate keys, SQL CRUD unit tests

parent d84a1d23
This diff is collapsed.
This diff is collapsed.
......@@ -6,10 +6,11 @@
<artifactId>insert_user</artifactId>
<version>0.1</version>
<packaging>jar</packaging>
<description>Barebone data insertion: No properties, no exception handling.</description>
<name>insert_user</name>
<url>https://freedocs.mi.hdm-stuttgart.de/sd1SectToolsOfTheTrade2.html</url>
<url>https://freedocs.mi.hdm-stuttgart.de</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
......
......@@ -62,4 +62,4 @@ public class SimpleInsert {
// an Exception we won't get here at all, sigh!)
System.out.println("Successfully inserted " + updateCount + " dataset(s)");
}
}
\ No newline at end of file
}
/A1.log
/.settings
/.idea
/*.iml
/.classpath
/.project
/target
<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.hdm_stuttgart.sda1.insert</groupId>
<artifactId>insert_user</artifactId>
<version>0.1</version>
<packaging>jar</packaging>
<description>Providing unit test.</description>
<name>insert_user</name>
<url>https://freedocs.mi.hdm-stuttgart.de</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.8-dmr</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.9.1</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.0.2.RELEASE</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.10.4</version>
<configuration />
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<manifestEntries>
<Main-Class>de.hdm_stuttgart.sda1.insert.SimpleInsert</Main-Class>
</manifestEntries>
</transformer>
</transformers>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
package de.hdm_stuttgart.sda1.insert;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.sql.*;
import java.util.ResourceBundle;
import java.util.Scanner;
/**
* <p>A JDBC "getting started" example inserting person's data into a table</p>
*
* <p>Caveat: No error handling whatsoever is being supplied!</p>
*
* <p>Preconditions:</p>
*
* <ul>
* <li>A database matching {@link #main(String[])}'s connection setup must be configured.</li>
* <li>A database table »Person« corresponding to this project's file »resources/schema.sql« must exist.</li>
* </ul>
*
*/
public class SimpleInsert {
static private final Logger log = LogManager.getLogger (SimpleInsert.class);
static public final ResourceBundle jdbcProperties = ResourceBundle.getBundle("jdbc");
/**
* <p>Disclaimer:</p>
*
* <ul>
* <li>User credentials (name and password) are being hard-coded requiring compile time
* database configuration. This is absolutely uuuuuuugly!</li>
* <li>Furthermore no exception handling whatsoever is being supplied.</li>
* </ul>
*
* <p>In other words: **Never** do this in any professional setting.</p>
*
* @param args unused
* @throws SQLException possible causes:
* <ul>
* <li>Driver matching JDBC URL unavailable.</li>
* <li>Missing network link to database server.</li>
* <li>Invalid credentials.</li>
* <li>Database table 'Person' does not exist.</li>
* <li>duplicate email (UNIQUE key).</li>
* <li>... something forgotten to think about?</li>
* </ul>
*/
public static void main(String[] args) {
try (final Connection conn = DriverManager.getConnection(
jdbcProperties.getString("jdbcurl"),
jdbcProperties.getString("username"),
jdbcProperties.getString("password"))) {
handleUserInput(conn.createStatement());
} catch (SQLException e) {
log.error("General database connection problem, exiting.");
}
}
static private void handleUserInput(final Statement statement) throws SQLException {
try (final Scanner scanner = new Scanner(System.in)) {
while(true) {
System.out.print("Enter a person's name or hit <Return> to exit:");
final String name = scanner.next().trim();
if (name.equals("")) break;
System.out.print("Enter a person's email or hit <Return> to exit:");
final String email = scanner.next().trim();
if (email.equals("")) break;
final int insertCount = insertPerson(statement, name, email);
}
}
}
/**
* <p>Try inserting new Person record.</p>
*
* @param statement To be used for SQL INSERT attempt.
* @param name Person's name
* @param email Person's email
* @return Inserted reord count: 1 on successful INSERT, 0 in case of duplicate email violating UNIQUE constraint.
*
* @throws SQLException To be thrown in case of non - {@link SQLIntegrityConstraintViolationException}
* errors.
*/
static public int insertPerson(final Statement statement, final String name, final String email)
throws SQLException {
final String sql = "INSERT INTO Person VALUES('" + name + "', '" + email + "')";
log.info("Executing »" + sql + "«");
try {
return statement.executeUpdate(sql);
} catch (final SQLIntegrityConstraintViolationException ex) {
log.info("Constraint violation, possibly inserting duplicate email '" + email + "'");
return 0;
}
}
}
\ No newline at end of file
jdbcurl=jdbc:mysql://localhost:3306/hdm
password=XYZ
username=hdmuser
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
<Appenders>
<File name="A1" fileName="A1.log" append="false">
<PatternLayout pattern="%t %-5p %c{2} - %m%n"/>
</File>
<Console name="STDOUT" target="SYSTEM_OUT">
<PatternLayout pattern="%d %-5p [%t] %C{2} (%F:%L) - %m%n"/>
</Console>
</Appenders>
<Loggers>
<!-- You my want to define class or package level per-logger rules -->
<Logger name="de.hdm_stuttgart.sda1.insert.App" level="debug">
<AppenderRef ref="A1"/>
</Logger>
<Root level="info">
<AppenderRef ref="STDOUT"/>
</Root>
</Loggers>
</Configuration>
\ No newline at end of file
DROP TABLE IF EXISTS Person;
CREATE TABLE Person (
name char(80)
,email CHAR(20) UNIQUE
);
\ No newline at end of file
package de.hdm_stuttgart.sda1.insert;
import org.junit.*;
import org.junit.runners.MethodSorters;
import org.springframework.core.io.ClassPathResource;
import org.springframework.jdbc.datasource.init.ScriptUtils;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ResourceBundle;
/**
* Testing insert operations.
*/
@FixMethodOrder(MethodSorters.NAME_ASCENDING) // SQL inserts require fixed execution order.
public class InsertTest {
static private Connection conn;
static private Statement stmt;
/**
* Init connection
* @throws java.sql.SQLException Unable to establish connection.
*/
@BeforeClass
static public void initDatabase() throws SQLException {
conn = DriverManager.getConnection(
SimpleInsert.jdbcProperties.getString("jdbcurl"),
SimpleInsert.jdbcProperties.getString("username"),
SimpleInsert.jdbcProperties.getString("password"));
ScriptUtils.executeSqlScript(conn, new ClassPathResource("schema.sql"));
stmt = conn.createStatement();
}
@AfterClass
static public void releaseDatabase() throws SQLException {
conn.close();
}
@Test
public void test_010_insertJill() throws SQLException {
Assert.assertEquals(1, SimpleInsert.insertPerson(stmt, "Jill", "jill@programmer.org"));
}
@Test
public void test_020_insertDave() throws SQLException {
Assert.assertEquals(1, SimpleInsert.insertPerson(stmt, "Dave", "dave@genius.org"));
}
/**
* Insert fails due to UNIQUE constraint on email value »jill@programmer.org«
*
*/
@Test
public void test_030_insertJillAgain() throws SQLException {
Assert.assertEquals(0, SimpleInsert.insertPerson(stmt, "Jill", "jill@programmer.org"));
}
}
\ No newline at end of file
/target/
/.settings/
.classpath
.project
<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.hdm_stuttgart.sda1.users</groupId>
<artifactId>users</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>users</name>
<url>https://freedocs.mi.hdm-stuttgart.de/sd1SectToolsOfTheTrade2.html</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.9.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.10.4</version>
<configuration />
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<manifestEntries>
<Main-Class>de.hdm_stuttgart.sda1.users.App</Main-Class>
</manifestEntries>
</transformer>
</transformers>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
package de.hdm_stuttgart.sda1.users.model;
public class Group {
String gid; // Group's system identifier e.g. »user«
int gidNumber; // Group's unique numer e.g. »4321«
String commonName; // Group's common name e.g »All users«
}
\ No newline at end of file
package de.hdm_stuttgart.sda1.users.model;
public class User {
String uid; // Unique Login name e.g. »smith«
int uidNumber; // Unique number e.g. »1234«
String commonName; // User's full name e.g. »John Smith«
Group primaryGroup; // User's primary group
}
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
<Appenders>
<File name="A1" fileName="A1.log" append="false">
<PatternLayout pattern="%t %-5p %c{2} - %m%n"/>
</File>
<Console name="STDOUT" target="SYSTEM_OUT">
<PatternLayout pattern="%d %-5p [%t] %C{2} (%F:%L) - %m%n"/>
</Console>
</Appenders>
<Loggers>
<!-- You my want to define class or package level per-logger rules -->
<Logger name="de.hdm_stuttgart.sda1.users.App" level="debug">
<AppenderRef ref="A1"/>
</Logger>
<Root level="info">
<AppenderRef ref="STDOUT"/>
</Root>
</Loggers>
</Configuration>
\ No newline at end of file
package de.hdm_stuttgart.sda1.users;
import org.junit.Assert;
import org.junit.Test;
/**
* Unit test for simple App.
*/
public class AppTest {
/**
* Dummy test method
*/
@Test
public void testApp() {
Assert.assertTrue( true );
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment