@ -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> |