안드로이드에서 정해진 시간마다 데이터베이스에 시간/위치 정보를 저장할 수 있게
시간 정보와 Location 정보의 데이터베이스를 처리하는 서버를 만들겠습니다.
먼저 Project를 생성한 뒤, dependency를 추가해 줍니다.
<pom.xml>
<?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>2.6.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.kakaroo.springlocationjpa</groupId>
<artifactId>SpringLocationJPA</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>SpringLocationJPA</name>
<description>Eclipse JPA project for Spring Boot</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
db 이름과 user 정보를 저장해 줍니다.
<application.properties>
spring.datasource.url=jdbc:mysql://localhost:3306/locationdb?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Seoul
spring.datasource.username=kakaroo
spring.datasource.password=kakaroo11
logging.level.com.kakaroo.springlocationjpa.LocationRespository=TRACE
<MySQL database 생성>
데이터베이스 생성
sql>create database locationdb default CHARACTER SET UTF8
생성한 데이터베이스로 이동
sql>use locationdb
계정생성
sql>create user 'kakaroo@localhost' identified by 'kakaroo11'
권한 부여
sql>grant all privileges on *.* to 'kakaroo'@'localhost'
sql>flush privileges
Table Entity 는 id, 시간정보, 위도, 경도로 정의합니다.
@Getter
@NoArgsConstructor
@Entity
public class LocationEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private LocalDateTime time;
private Double latitude;
private Double longitude;
@Builder
public LocationEntity(Long id, LocalDateTime time, Double latitude, Double longitude) {
this.id = id;
this.time = time;
this.latitude = latitude;
this.longitude = longitude;
}
}
Create, ReadAll, Delete, DeleteAll 을 구현해 줍니다.
(Update와 ReadById는 사용하지 않기 때문에 제외합니다.)
@RequiredArgsConstructor
@Service
public class LocationService {
private final LocationRepository repository;
@Transactional
public Long create(LocationCreateDto createDto) {
return repository.save(createDto.toEntity()).getId();
}
@Transactional(readOnly = true)
public List<LocationReadDto> readAll() {
List<LocationReadDto> list = repository.findAll().stream().map(entity -> new LocationReadDto(entity)).collect(Collectors.toList());
return list;
}
@Transactional
public Long delete(Long id) {
LocationEntity entity = repository.findById(id).orElseThrow(() -> new IllegalArgumentException("delete error!!! id: " + id));
repository.delete(entity);
return id;
}
@Transactional
public Long deleteAll() {
repository.deleteAll();
return repository.count();
}
}
* 구현부분에 대해 궁금하신 분은 이전에 포스팅했던 글을 참조하시면 됩니다.
https://kakaroo.tistory.com/49
Error : SQL table doesn't exist
실행시켰더니 테이블이 생성되어 있지 않아 에러가 발생합니다.
java.sql.SQLSyntaxErrorException: Table 'locationdb.location_entity' doesn't exist
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:120) ~[mysql-connector-java-8.0.28.jar:8.0.28]
at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122) ~[mysql-connector-java-8.0.28.jar:8.0.28]
at com.mysql.cj.jdbc.ClientPreparedStatement.executeInternal(ClientPreparedStatement.java:953) ~[mysql-connector-java-8.0.28.jar:8.0.28]
<application.properties> 속성 추가
spring.jpa.hibernate.ddl-auto=create
spring.jpa.hibernate.ddl-auto 속성
create: 기존 테이블을 삭제하고 새로 생성 (DROP - CREATE)
create-drop: create와 동일하나 어플리케이션 종료시 테이블 삭제 (DROP - CREATE - DROP)
update: 데이터베이스 테이블 - 엔터티 매핑정보를 비교해서 변경사항만 수정
validate: 데이터베이스 테이블 - 엔터티 매핑정보를 비교해서 차이가있으면 어플리케이션을 실행하지 않음
none: 자동 생성 기능을 사용하지 않음
위 auto create를 실행한 뒤, Default item 을 넣어서 table에 값이 잘 들어가는지 확인해 보겠습니다.
SQL에 시간 정보는 아래와 같이 LocalDateTime 타입으로 값을 변환해서 저장합니다.
@GetMapping("/")
public String init() {
Double latitude = 37.3863871;
Double longitude = 126.9648526;
for (int i = 0; i < 5; i++) {
//java.sql.TimeStamp
SimpleDateFormat formatter = new SimpleDateFormat ("yyyy-MM-dd hh:mm:ss");
Calendar cal = Calendar.getInstance();
String today = formatter.format(cal.getTime());
Timestamp ts = Timestamp.valueOf(today);
System.out.println("timestamp : "+ts);
LocalDateTime ldt = ts.toLocalDateTime();
System.out.println("SQL type of timestamp : "+ldt);
Double reviseValueA = i * 0.001;
Double reviseValueB = i * 0.002;
repository
.save(LocationEntity.builder().time(ldt).latitude(latitude+reviseValueA).longitude(longitude+reviseValueB).build());
}
return "Default item is inserted";
}
다행히 잘 들어갔네요.
코드는 아래에 있습니다.
https://github.com/kakarooJ/JPA-MySql-Location-Server
서버측은 간단하게 구성이 끝났습니다.
다음 포스팅에서는 클라이언트가 되는 안드로이드에서 값을 주기적으로 저장하고,
저장된 정보를 읽어와서 지도화면에 시간별로 출력해 보겠습니다.
Auto_Increment 속성이 있는 ID가 table value가 추가될 때마다 증가해서
delete all 이후, id를 1부터 reset 하기 위한 query가 필요해졌습니다.
Controller 에 EntityManager의 createNativeQuery를 적용하여 query를 구현할 수 있습니다.
//LocationService.java
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
public class LocationService {
@PersistenceContext
EntityManager entityManager;
..
@Transactional
public Long deleteAll() {
repository.deleteAll();
Long count = repository.count();
String jpql = "ALTER TABLE locations AUTO_INCREMENT = 1"; //locations : table name
entityManager.createNativeQuery(jpql).executeUpdate();
return count;
}
}
이전에 Class 이름(LocationEntity)으로 생성된 테이블 이름이 location_entity로 너무 길고 맘에 들지 않아,
아래와 같이 테이블 이름을 locations 로 변경했기 때문에 위 query 문의 테이블 이름이 변경되었습니다.
@Entity
@Table(name = "locations")
public class LocationEntity {
delete all 이후, add 했을 때 아래와 같이 id가 1부터 새로 부여됩니다.
database는 서버가 재실행될때마다 drop 되어서 create 값에서 update로 변경했습니다.
spring.jpa.hibernate.ddl-auto=update
'Web' 카테고리의 다른 글
2. AWS - RDS 환경 구축 (0) | 2022.03.04 |
---|---|
1. AWS 서버 환경 구축 (AWS EC2) (0) | 2022.03.04 |
Android에서 SpringBoot JPA 서버와 연동하기 (0) | 2022.02.17 |
Spring Boot - Eclipse Maven으로 Spring Web Layer 실습 (0) | 2022.02.14 |
3 - Spring Boot - 웹화면 구성 with JPA, Mustache (0) | 2022.02.11 |