@ -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> |
@ -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()); | |||
} | |||
}; | |||
} | |||
} |
@ -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 + | |||
"]"; | |||
} | |||
} |
@ -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(); | |||
} |
@ -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); | |||
} | |||
} |
@ -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; | |||
} | |||
} |
@ -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"; | |||
} | |||
} |
@ -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 |
@ -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 +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> |