Browse Source

Add JDBC exercise example

master
Pekka Helenius 3 years ago
parent
commit
4c983c392a
12 changed files with 530 additions and 5 deletions
  1. +6
    -5
      README.md
  2. +70
    -0
      exercises/spring-jdbc-test/pom.xml
  3. +57
    -0
      exercises/spring-jdbc-test/src/main/java/com/example/sqltest/SqlTestApplication.java
  4. +173
    -0
      exercises/spring-jdbc-test/src/main/java/com/example/sqltest/model/Customer.java
  5. +13
    -0
      exercises/spring-jdbc-test/src/main/java/com/example/sqltest/model/CustomerDAO.java
  6. +86
    -0
      exercises/spring-jdbc-test/src/main/java/com/example/sqltest/model/CustomerDAOImpl.java
  7. +27
    -0
      exercises/spring-jdbc-test/src/main/java/com/example/sqltest/model/CustomerMapper.java
  8. +35
    -0
      exercises/spring-jdbc-test/src/main/java/com/example/sqltest/web/CustomerController.java
  9. +12
    -0
      exercises/spring-jdbc-test/src/main/resources/application.properties
  10. +13
    -0
      exercises/spring-jdbc-test/src/main/resources/schema.sql
  11. +0
    -0
      exercises/spring-jdbc-test/src/main/resources/static/.gitignore
  12. +38
    -0
      exercises/spring-jdbc-test/src/main/resources/templates/customers.html

+ 6
- 5
README.md View File

@ -10,11 +10,12 @@ This repository contains various project exercises, known as `chapters`. Externa
### Chapters
| Chapter | Description |
|----------------------------------|------------------|
| [Chapter 0](exercises/chapter_0) | Hello World |
| [Chapter 1](exercises/chapter_1) | HTTP Requests |
| [Chapter 2](exercises/chapter_2) | Thymeleaf basics |
| Chapter | Description |
|-----------------------------------------|------------------|
| [Chapter 0](exercises/chapter_0) | Hello World |
| [Chapter 1](exercises/chapter_1) | HTTP Requests |
| [Chapter 2](exercises/chapter_2) | Thymeleaf basics |
| [JDBC](exercises/spring-jdbc-test) | JDBC Tests |
### Project work


+ 70
- 0
exercises/spring-jdbc-test/pom.xml View File

@ -0,0 +1,70 @@
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.4.RELEASE</version>
</parent>
<groupId>com.example.sql-test</groupId>
<artifactId>SQLTest</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>SQL Test</name>
<description>Spring SQL connection test</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
<finalName>${project.artifactId}</finalName>
</build>
</project>

+ 57
- 0
exercises/spring-jdbc-test/src/main/java/com/example/sqltest/SqlTestApplication.java View File

@ -0,0 +1,57 @@
package com.example.sqltest;
import java.math.BigDecimal;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.context.annotation.Bean;
import com.example.sqltest.model.Customer;
import com.example.sqltest.model.CustomerDAOImpl;
@SpringBootApplication
public class SqlTestApplication extends SpringBootServletInitializer {
private static final Logger logger = LoggerFactory.getLogger(SqlTestApplication.class);
public static void main(String[] args) {
SpringApplication.run(SqlTestApplication.class, args);
}
@Bean
public CommandLineRunner CustomerRunner(CustomerDAOImpl customerDAO) {
return (args) -> {
logger.info("Deleting old database table entries");
customerDAO.dropAll();
logger.info("Creating new database table entries");
customerDAO.save(new Customer(
"Daniel", "Thyssenlauf",
"man", "English",
new BigDecimal("0.45"),
"danthyf@gmail.com", null
));
customerDAO.save(new Customer(
"Janina", "Riikanen",
"woman", "Finnish",
new BigDecimal("1.74"),
"janskuuu@yahoo.com", "+358405341242"
));
logger.info("Created a new database table with the following values");
for (Customer customer : customerDAO.findAll()) {
logger.info("CUSTOMER table: {}", customer.toString());
}
};
}
}

+ 173
- 0
exercises/spring-jdbc-test/src/main/java/com/example/sqltest/model/Customer.java View File

@ -0,0 +1,173 @@
package com.example.sqltest.model;
import java.math.BigDecimal;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
//@Entity
public class Customer {
private Long id;
private String firstName;
private String lastName;
private String sex;
private String language;
@Min((long) 0.00)
@Max((long) 10.00)
private BigDecimal engagement;
private String email;
private String phone; //Yes, phone number can have other symbols than numbers. Do regex check for input validation
// TODO add street address table
// TODO add invoices data table (requires a joining table between CUSTOMER & INVOICE tables)
// Setters
public void setId(Long id) {
this.id = id;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public void setSex(String sex) {
this.sex = sex;
}
public void setLanguage(String language) {
this.language = language;
}
public void setEngagement(BigDecimal engagement) {
this.engagement = engagement;
}
public void setPhone(String phone) {
this.phone = phone;
}
public void setEmail(String email) {
this.email = email;
}
// Getters
public Long getId() {
return id;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public String getSex() {
return sex;
}
public String getLanguage() {
return language;
}
public BigDecimal getEngagement() {
return engagement;
}
public String getPhone() {
return phone;
}
public String getEmail() {
return email;
}
// Constructors
public Customer() {
this.id = (long) 0;
this.firstName = null;
this.lastName = null;
this.sex = null;
this.language = null;
this.engagement = null;
this.email = null;
this.phone = null;
}
public Customer(
Long id,
String firstName,
String lastName,
String sex,
String language,
BigDecimal engagement,
String email,
String phone
) {
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
this.sex = sex;
this.language = language;
this.engagement = engagement;
this.email = email;
this.phone = phone;
}
public Customer(
String firstName,
String lastName,
String sex,
String language,
BigDecimal engagement,
String email,
String phone
) {
this.id = (long) 0;
this.firstName = firstName;
this.lastName = lastName;
this.sex = sex;
this.language = language;
this.engagement = engagement;
this.email = email;
this.phone = phone;
}
// Overrides
@Override
public String toString() {
return "[" +
"id: " + this.id + ", " +
"firstname: " + this.firstName + ", " +
"lastname: " + this.lastName + ", " +
"sex: " + this.sex + ", " +
"language: " + this.language + ", " +
"engagement: " + this.engagement + ", " +
"email: " + this.email + ", " +
"phone: " + this.phone +
"]";
}
}

+ 13
- 0
exercises/spring-jdbc-test/src/main/java/com/example/sqltest/model/CustomerDAO.java View File

@ -0,0 +1,13 @@
package com.example.sqltest.model;
import java.util.List;
public interface CustomerDAO {
public void save(Customer customer);
public Customer findById(Long id);
public List<Customer> findAll();
public void dropAll();
}

+ 86
- 0
exercises/spring-jdbc-test/src/main/java/com/example/sqltest/model/CustomerDAOImpl.java View File

@ -0,0 +1,86 @@
package com.example.sqltest.model;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;
@Repository
public class CustomerDAOImpl implements CustomerDAO {
@Autowired
private JdbcTemplate jdbcTemplate;
// Setters
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
// Getters
public JdbcTemplate getJdbcTemplate() {
return this.jdbcTemplate;
}
// Abstract methods
@Override
public void save(Customer customer) {
String sqlQuery = "INSERT INTO CUSTOMER(" +
"firstname" + "," +
"lastname" + "," +
"sex" + "," +
"language" + "," +
"engagement" + "," +
"email" + "," +
"phone" +
") VALUES (?,?,?,?,?,?,?)";
Object[] sqlData = new Object[] {
customer.getFirstName(),
customer.getLastName(),
customer.getSex(),
customer.getLanguage(),
customer.getEngagement(),
customer.getEmail(),
customer.getPhone()
};
jdbcTemplate.update(sqlQuery, sqlData);
}
@Override
public Customer findById(Long id) {
String sqlQuery = "SELECT * FROM CUSTOMER WHERE ID = ?";
Object[] queryData = new Object[] { id };
RowMapper<Customer> mapper = new CustomerMapper();
Customer customer = jdbcTemplate.queryForObject(sqlQuery, queryData, mapper);
return customer;
}
@Override
public List<Customer> findAll() {
String sqlQuery = "SELECT * FROM CUSTOMER";
RowMapper<Customer> mapper = new CustomerMapper();
List<Customer> customers = jdbcTemplate.query(sqlQuery, mapper);
return customers;
}
@Override
public void dropAll() {
String sqlQueryDelete = "DELETE FROM CUSTOMER";
String sqlQueryResetId = "ALTER TABLE CUSTOMER AUTO_INCREMENT = 1";
jdbcTemplate.execute(sqlQueryDelete);
jdbcTemplate.execute(sqlQueryResetId);
}
}

+ 27
- 0
exercises/spring-jdbc-test/src/main/java/com/example/sqltest/model/CustomerMapper.java View File

@ -0,0 +1,27 @@
package com.example.sqltest.model;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.springframework.jdbc.core.RowMapper;
public class CustomerMapper implements RowMapper<Customer> {
@Override
public Customer mapRow(ResultSet resultSet, int rowNum) throws SQLException {
Customer customer = new Customer();
customer.setId(resultSet.getLong("id"));
customer.setFirstName(resultSet.getString("firstname"));
customer.setLastName(resultSet.getString("lastname"));
customer.setSex(resultSet.getString("sex"));
customer.setLanguage(resultSet.getString("language"));
customer.setEngagement(resultSet.getBigDecimal("engagement"));
customer.setEmail(resultSet.getNString("email"));
customer.setPhone(resultSet.getNString("phone"));
return customer;
}
}

+ 35
- 0
exercises/spring-jdbc-test/src/main/java/com/example/sqltest/web/CustomerController.java View File

@ -0,0 +1,35 @@
package com.example.sqltest.web;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import com.example.sqltest.model.Customer;
import com.example.sqltest.model.CustomerDAO;
@Controller
public class CustomerController {
@Autowired
private CustomerDAO customerDAO;
@RequestMapping(
value = "/customers",
method = RequestMethod.GET
)
public String customerWebFormGet(Model dataModel) {
List<Customer> customers = customerDAO.findAll();
dataModel.addAttribute("customers", customers);
return "customers";
}
@RequestMapping("*")
public String redirectWebForm() {
return "redirect:/customers";
}
}

+ 12
- 0
exercises/spring-jdbc-test/src/main/resources/application.properties View File

@ -0,0 +1,12 @@
server.port = 8080
# This MySQL database connection is established to a remote SQL server via SSH tunnel.
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/MYSQL_DATABASE?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
spring.datasource.username=MYSQL_USERNAME
spring.datasource.password=MYSQL_PASSWORD
spring.datasource.initialization-mode=always
logging.level.org.springframework.jdbc.core.JdbcTemplate=DEBUG
logging.level.org.springframework.jdbc.core.StatementCreatorUtils=TRACE

+ 13
- 0
exercises/spring-jdbc-test/src/main/resources/schema.sql View File

@ -0,0 +1,13 @@
CREATE TABLE IF NOT EXISTS CUSTOMER (
id INT(4) NOT NULL UNIQUE AUTO_INCREMENT,
firstname NVARCHAR(30) DEFAULT NULL,
lastname NVARCHAR(30) DEFAULT NULL,
sex VARCHAR(10) DEFAULT NULL,
language VARCHAR(20) DEFAULT NULL,
engagement DECIMAL(5,2) DEFAULT NULL,
email NVARCHAR(50) DEFAULT NULL,
phone VARCHAR(25) DEFAULT NULL,
PRIMARY KEY (id)
);
CREATE UNIQUE INDEX IF NOT EXISTS `CUSTOMER.id.IDX_UNIQUE` ON CUSTOMER (id ASC);

+ 0
- 0
exercises/spring-jdbc-test/src/main/resources/static/.gitignore View File


+ 38
- 0
exercises/spring-jdbc-test/src/main/resources/templates/customers.html View File

@ -0,0 +1,38 @@
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Customer SQL data dump</title>
</head>
<body>
<h1>Customer SQL data dump</h1>
<table>
<tr>
<th>First Name</th>
<th>First Name</th>
<th>Sex</th>
<th>Language</th>
<th>Engagement Level</th>
<th>Email Address</th>
<th>Phone Number</th>
</tr>
<tr th:each="customer : ${customers}">
<td th:text="${customer.firstName}"></td>
<td th:text="${customer.lastName}"></td>
<td th:text="${customer.sex}"></td>
<td th:text="${customer.language}"></td>
<td th:text="${customer.engagement}"></td>
<td th:text="${customer.email}"></td>
<td th:text="${customer.phone}"></td>
</tr>
</table>
</body>
</html>

Loading…
Cancel
Save