ECE366 - Lesson 6

Spring Boot, JPA

Instructor: Professor Hong

Review & Questions

## Review
## Spring Boot - a service layer that will connect your database to your user interface - use the Spring Initializr: [https://start.spring.io/](https://start.spring.io/) - you may have to remove the test dependency (or fix the test) or use an older version of spring boot
## pom.xml [https://mvnrepository.com/](https://mvnrepository.com/) ``` <?xml version="1.0" encoding="UTF-8"?> <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>3.0.2</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.chrishong</groupId> <artifactId>rps</artifactId> <version>0.0.1-SNAPSHOT</version> <name>rps</name> <description>RPS Game</description> <properties> <java.version>19</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.postgresql</groupId> <artifactId>postgresql</artifactId> <version>42.5.4</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project> ```
## Maven ``` $ mvn package $ java -jar target/rps-0.0.1-SNAPSHOT.jar ```
## Docker Compose ``` services: db: image: postgres volumes: - $HOME/srv/postgres:/var/lib/postgresql/data environment: - POSTGRES_DB=rps - POSTGRES_PASSWORD=password expose: - 5432:5432 ports: - 5432:5432 restart: always app: build: . ports: - 8080:8080 environment: - POSTGRES_DB=rps - POSTGRES_HOST=db - POSTGRES_PASSWORD=password depends_on: - db ``` - Set up your database and service to communicate - Expose ports as necessary (db port)
## Dockerfile ``` FROM maven:3.8.7-eclipse-temurin-19 AS build ADD . /project WORKDIR /project RUN mvn -e package FROM eclipse-temurin:latest COPY --from=build /project/target/rps-0.0.1-SNAPSHOT.jar /app/rps.jar ENTRYPOINT ["java","-jar","/app/rps.jar"] ```
## Docker Compose Commands ``` $ docker compose build $ docker compose up ```
## DBeaver - Connect to your docker's Postgres - localhost - db: rps - port: 5432 - user name: postgres - password: password
## JPA
## Java Persistence API (JPA) - Standard Java EE (Jakarta EE) specification for ORM (Object–Relational Mapping) - Allows you to map between objects and database tables - Streamlines persistence to standard format - Reduces JDBC code - Focus on OOP
## application.properties ``` spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect spring.jpa.hibernate.ddl-auto=update spring.datasource.url=jdbc:postgresql://${POSTGRES_HOST}:5432/${POSTGRES_DB} spring.datasource.username=postgres spring.datasource.password=${POSTGRES_PASSWORD} ```
## Hard coded ``` spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect spring.jpa.hibernate.ddl-auto=update spring.datasource.url=jdbc:postgresql://$localhost:5432/rps spring.datasource.username=postgres spring.datasource.password=password ```
## pom.xml ``` <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> ```
## Important Annotations - ```@RestController``` - enables API endpoints - ```@Entity``` - a row from the database - ```@Table``` - the table name - ```@Id``` - the ID of a table row - ```@Column``` - a column of the table - ```@GeneratedValue``` - strategies for primary key
## Code Organization for JPA
## User Class data/User.java ``` package com.chrishong.rps.data; import jakarta.persistence.*; @Entity @Table(name="USERS") public class User { @Id @Column(name="USER_ID") @GeneratedValue(strategy = GenerationType.IDENTITY) private long userId; @Column(name="USER_NAME") private String userName; @Column(name="PASSWORD") private String password; @Column(name="TOTAL_GAMES") private int totalGames; @Column(name="TOTAL_WIN") private int totalWin; @Column(name="TOTAL_LOSS") private int totalLoss; @Column(name="TOTAL_TIE") private int totalTie; public long getUserId() { return userId; } public void setUserId(long userId) { this.userId = userId; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public int getTotalGames() { return totalGames; } public void setTotalGames(int totalGames) { this.totalGames = totalGames; } public int getTotalWin() { return totalWin; } public void setTotalWin(int totalWin) { this.totalWin = totalWin; } public int getTotalLoss() { return totalLoss; } public void setTotalLoss(int totalLoss) { this.totalLoss = totalLoss; } public int getTotalTie() { return totalTie; } public void setTotalTie(int totalTie) { this.totalTie = totalTie; } @Override public String toString() { return "User{" + "userId=" + userId + ", userName='" + userName + '\'' + ", password='" + password + '\'' + ", totalGames=" + totalGames + ", totalWin=" + totalWin + ", totalLoss=" + totalLoss + ", totalTie=" + totalTie + '}'; } } ```
## UserRepository Interface data/UserRepository.java ``` package com.chrishong.rps.data; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @Repository public interface UserRepository extends JpaRepository { } ```
## UserService business/UserService ``` package com.chrishong.rps.business; import com.chrishong.rps.data.User; import com.chrishong.rps.data.UserRepository; import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.Comparator; import java.util.List; @Service public class UserService { private final UserRepository userRepository; public UserService(UserRepository userRepository) { this.userRepository = userRepository; } public List getUsers(){ Iterable users = this.userRepository.findAll(); List userList = new ArrayList<>(); users.forEach(user->{userList.add(user);}); return userList; } } ```
## WebserviceController webservice/WebserviceController.java ``` package com.chrishong.rps.webservice; import com.chrishong.rps.business.UserService; import com.chrishong.rps.data.User; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import java.util.List; @RestController public class WebserviceController { private final UserService userService; public WebserviceController(UserService userService) { this.userService = userService; } @GetMapping("/users") public List getUsers(){ System.out.println("getUsers"); return this.userService.getUsers(); } @GetMapping("/testuser") public String getTestUser() { return "TEST USERS"; } } ```