tuter77

2023.01.12 TIL 본문

TIL

2023.01.12 TIL

tuter77 2023. 1. 12. 21:51

<목차>

  1. <공부계획표>
  2. Java
  3. Group Study

<공부계획표>

13:00 ~ 14:00 블로그 작성

14:00 ~ 18:00 (3시간) 온라인강의 시청.

           14:00 ~ 15:00 그룹스터디 과제

           15:00 ~ 16:00 그룹스터디 과제

           17:00 ~ 18:00 그룹스터디 과제

18:00 ~ 19:00 식사시간

19:00 ~ 22:00 온라인 강의시청

           19:00 ~ 20:00 java 온라인 강의 시청

           20:00 ~ 21:00 java 온라인 강의 시청

           21:00 ~ 22:00 java 온라인 강의 시청

22:00 ~ 23:00 프로그래머스 문제 풀기.


<Java>

● 인터페이스를 활용한 다형성 구현(DAO)

▷ 인터페이스와 다형성

- 하나의 인터페이스를 여러 객체가 구현하게 되면 클라이언트 프로그램은 인터페이스의 메서드를 활용하여 여러 객체의 구현을 사용할 수 있다.(다형성)

 

인터페이스를 활용한 다형성 구현(DAO) - 실습.

 

- db에 회원 정보를 넣는 dao(data access object)를 여러 db 제품이 지원될 수 있게 구현한다.

- 환경 파일(db.properties)에서 database의 종류에 대한 정보를 읽고 그 정보에 맞게 dao인스턴스를 생성하여 실행 될 수 있게 한다.

 

- source hierachy

 

 

- 먼저 userInfoDao 클래스를 정의한다.

여기에서는 각 dao에 필요한 정보들을 미리 정의한다.

 

package ch13.domain.userinfo;

public class UserInfo {
	
	private String userId;
	private String password;
	private String userName;
	
	public String getUserId() {
		return userId;
	}
	public void setUserId(String userId) {
		this.userId = userId;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public String getUserName() {
		return userName;
	}
	public void setUserName(String userName) {
		this.userName = userName;
	}
	
	
}

 

유저가 가입하게 되면 필요한 기본적인 사항인 id, 패스워드, 이름 이렇게 세가지 변수를 private로 정의하고 get,set메서드를 생성한다.

 

다음으로 UserInfo 인터페이스를 생성해서 각 db에 따른 dao에서 구현해야 할 것들을 정의한다.

 

package ch13.domain.userinfo.dao;

import ch13.domain.userinfo.UserInfo;

public interface UserInfoDao {

	//dao는 이러이러 해야한다는 것을 구현.
	void insertUserInfo(UserInfo userInfo);
	void updateUserInfo(UserInfo userInfo);
	void deleteUserInfo(UserInfo userInfo);
	
}

 

삽입, 갱신, 삭제 기능만 객체를 매개변수로 받게끔 정의해놓는다.

 

- 각 db dao

 

dao는 db종류에 따라 각각 만들었다.

먼저 mysql dao의 경우 아래와 같다.

package ch13.domain.userinfo.dao.mysql;

import ch13.domain.userinfo.UserInfo;
import ch13.domain.userinfo.dao.UserInfoDao;

public class UserInfoMysqlDao implements UserInfoDao{

	@Override
	public void insertUserInfo(UserInfo userInfo) {
		System.out.println("Insert into MySql DB userId = " + userInfo.getUserId());
	}

	@Override
	public void updateUserInfo(UserInfo userInfo) {
		System.out.println("Update into MySql DB userId = " + userInfo.getUserId());
	}

	@Override
	public void deleteUserInfo(UserInfo userInfo) {
		System.out.println("Delete from MySql DB userId = " + userInfo.getUserId());		
	}

}

implements를 통해 인터페이스를 상속받고 해당 메서드들을 구현한다.

각 메서드는 콘솔창에 어떤 기능이 어디 db의 것인지만 출력되게 표기해놓았다.

 

마찬가지로 oracledao도 똑같이 구현한다.

 

package ch13.domain.userinfo.dao.oracle;

import ch13.domain.userinfo.UserInfo;
import ch13.domain.userinfo.dao.UserInfoDao;

public class UserInfoOracleDao implements UserInfoDao{

	@Override
	public void insertUserInfo(UserInfo userInfo) {
		System.out.println("Insert into Oracle DB userId = " + userInfo.getUserId());		
	}

	@Override
	public void updateUserInfo(UserInfo userInfo) {
		System.out.println("Insert into Oracle DB userId = " + userInfo.getUserId());				
	}

	@Override
	public void deleteUserInfo(UserInfo userInfo) {
		System.out.println("Insert into Oracle DB userId = " + userInfo.getUserId());				
	}

}

 

 

이제 어떤 db를 사용중인지를 나타내는 환경설정 파일을 생성한다.(db.properties)

 

해당 파일 내에는 db가 어떤 타입인지만 알 수 있게 해놓는다.

다른 db를 사용하게 되면 이 부분만 바꾸면된다.

최종적으로 web패키지의 userinfo 패키지를 만들어 클라이언트의 요청이 수행되는 클래스를 만든다.

 

package ch13.web.userinfo;

import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;

import ch13.domain.userinfo.UserInfo;
import ch13.domain.userinfo.dao.UserInfoDao;
import ch13.domain.userinfo.dao.mysql.UserInfoMysqlDao;
import ch13.domain.userinfo.dao.oracle.UserInfoOracleDao;

public class UserInfoClient {

	public static void main(String[] args) throws IOException {
		
		FileInputStream fis = new FileInputStream("db.properties");
		
		Properties prop = new Properties(); //한 페어로 읽어들이는 객체
		prop.load(fis);
		
		String dbType = prop.getProperty("DBTYPE"); //해당되는 밸류를 반환
		
		UserInfo userInfo =new UserInfo();
		userInfo.setUserId("12345");
		userInfo.setPassword("!@#@!$");
		userInfo.setUserName("Lee");
		
		
		UserInfoDao userInfoDao = null;
		
		if(dbType.equals("ORACLE")) {
			userInfoDao = new UserInfoOracleDao();
		}
		else if(dbType.equals("MYSQL")) {
			userInfoDao = new UserInfoMysqlDao();
		}
		else {
			System.out.println("db error");
			return;
		}
		
		userInfoDao.insertUserInfo(userInfo);
		userInfoDao.updateUserInfo(userInfo);
		userInfoDao.deleteUserInfo(userInfo);
	}
}

FileInpitStream 이라는 객체는 환경설정 파일값을 받아오는 객체이다.

Properties 객체는 해당 환경 변수 값들을 한쌍의 페어로 읽어들이는 객체이다. 

 

때문에 prop객체에 load라는 메서드를 이용하여 환경변수값이 저장된 fis 객체를 읽어들인다.

이를 통해 db 타입이 어떤것인지 객체에 저장한다.

그 아래의 dbType이라는 변수를 생성해 getProperty메서드로 prop에 저장된 페어에 DBTYPE에 해당하는 값을 저장한다.

 

그 아래는 생성자를 통해 신규 유저를 생성한 모습이고, UserInfoDao 인터페이스 객체를 null 값으로 초기화한다.

이후 앞서 db 타입 값을 저장해놓은 dbType 값에 equal메서드를 사용하여 mysql과 db oracle을 비교하고 해당하는 dao에서 메서드를 가져오도록 한다.

 

맨 아래는 메서드를 실행하는 구문으로 db타입만 properties파일에서 바꿔주면 다른 메서드를 사용할 수 있게 된다.

다형성이 구현된 모습이다.

 

 

 

 

 


<Group Study>

● 저장, 삭제 기능 구현.

 

▷ 저장 html 페이지

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>헬스장 정보 저장 페이지</title>
</head>

<body>
<table>
    <form th:action="@{/write/post}" method="post">
        <p>아래에 자료를 입력하세요.</p>
            <tr>
                <td><input type="text" name="brand_name"></td>
            </tr>
            <tr>
                <td><input type="text" name="land_number"></td>
            </tr>
            <tr>
                <td><input type="text" name="road_number"></td>
            </tr>
            <tr>
                <td><input type="text" name="category"></td>
            </tr>
            <td><input type="reset" value="취소"></td>
            <td><button type="submit">저장</button></td>
        </tr>
    </form>
</table>
</body>
</html>

▷컨트롤러 저장 메서드

@RequiredArgsConstructor
@Controller
@Slf4j
public class HomeController {
    private final HealthRepository healthRepository;
    private final HomeService homeService;
 
 	@GetMapping("/write") // 저장 페이지.
    public String write(){
        return "writer";
    }
  
  	@PostMapping("/write/post") //저장 기능 구현.
    public String writerPost(HealthInfo healthInfo){
        healthRepository.save(HealthInfo.builder()
                .brand_name(healthInfo.getBrand_name())
                .road_number(healthInfo.getRoad_number())
                .land_number(healthInfo.getLand_number())
                .category(healthInfo.getCategory())
                .build());

        return "redirect:/home"; //prg패턴.
    }
}

 

새로운 데이터를 저장하는 것이라 id값을 따로 지정해두지 않고 이전에 healthInfo 엔티티를 생성할 때 @GeneratedValue 어노테이션으로 id값을 자동으로 지정하는 걸 설정해놓은 것을 그대로 사용했다.

 

이후 html파일은 타임리프문을 활용하여, 자료를 저장할 시에 post method로 Post 매핑된 writePost 메서드가 동작하도록 설정했다.

저장 메서드는 healthInfo 객체에 각 값들을 builder로 저장하고 홈html파일을 반환한다.

 

위의 get매핑 write메서드는 writer라는 위의 html파일을 브라우저에 출력하는 용도이다.

 

▷삭제기능

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>상세페이지</title>
</head>

<body>
    <h1 th:text="${healthInfo.brand_name}"></h1>
    <p th:text="${healthInfo.land_number}"></p>
    <p th:text="${healthInfo.road_number}"></p>
    <p th:text="${healthInfo.category}"></p>
    <a th:href="@{/modified{id}(id=${healthInfo.id})}">수정</a>
    <a th:href="@{/home/delete(id=${healthInfo.id})}">삭제</a>
    <button type="submit" onclick="location.href='/home'">뒤로</button>
</body>
</html>
@GetMapping("/home/delete")
    public String healthDelete(@RequestParam Long id){
        homeService.healthDelete(id);
        return "redirect:/home";
    }

삭제기능은 상세페이지의 삭제 태그를 타고 들어가서 실행이 가능하다.

코드를 보면, healthInfo의 id값을통해 저장된 자료를 가져와 delete메서드에 반환해준다.

 delete메서드에서는 반환받은 id값을 delete기능을 통해 지워준다.

homeSerVice의 healthDelete기능은 

@Override
        public boolean healthDelete(@RequestParam Long id){
        healthRepository.deleteById(id);
        return true;
        }

이와 같이 구현되어있다.

JPA레포지토리 의 deleteById메서드를 사용하는것을 볼 수 있다.

해당 healthDelete는 boolean값을 반환하는데 정상적으로 삭제되었을 경우 true를 반환하는 것을 볼 수 있다.

'TIL' 카테고리의 다른 글

2023.01.16 TIL  (0) 2023.01.16
2023.01.13  (0) 2023.01.13
2023.01.11 TIL  (0) 2023.01.11
2023.01.10 TIL  (0) 2023.01.10
2023.01.09 TIL  (0) 2023.01.09