해당 글에서는 Spring Boot내에 Mybatis와 PostgreSQL을 연결하고 로직 처리를 위한 환경 설정 및 파일 구성에 대해서 공유합니다.
![](https://t1.daumcdn.net/keditor/emoticon/face/large/073.png)
💡 최하단에 해당 환경 구성과 관련하여 '로컬 DB 구성 방법', 'HikariCP'를 통한 Connection 관리, 'Spring Security' 구성 및 'JWT'를 통한 인증 방법에 대해서 관련 글들도 참고해 보시면 좋을 것 같습니다 🙏
1) 사전 확인 작업
1. DB 드라이버 설치 확인
# postgreSQL 버전을 확인한다.
$ postgres --version
# 설치가 안되었다면 설치를 한다.
$ brew install postgresql
2. 개발 환경 확인
구분 | 언어 / 라이브러리 |
언어 | Java |
웹 프레임워크 | Spring Boot |
Persistence Framework | Mybatis |
자동화 빌드 툴 | Gradle |
3. 데이터 흐름 확인
![](http://t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png)
💡 [참고] 구성에 사용 N-Tier Architecure에 대해 궁금하시면 아래의 글을 참고하시면 도움이 됩니다.
[Java] 계층화된 아키텍처(Layered Architecture) : N Tier Architecture
해당 글에서는 Java의 아키텍처 구성 중 계층화된 아키텍처인 N Tier 아키텍처에 대해서 이해를 돕기 위해 작성한 글입니다. 1) 계층화된 아키텍처(Layered Architecture) 💡 계층화된 아키텍처란? - 계층
adjh54.tistory.com
2) 설정 파일 구성
💡 해당 설정 파일 구성은 로컬 PostgreSQL과 연동하는 과정을 작성하였습니다.
1. Gradle 환경 설정
💡 build.gradle 파일 내에서는 최소한의 환경설정만 구성하였습니다.
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-validation'
compileOnly 'org.projectlombok:lombok'
runtimeOnly 'org.postgresql:postgresql'
annotationProcessor 'org.projectlombok:lombok'
providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
2. MyBatis 환경 설정
💡 해당 부분에서는 @Configuration 어노테이션을 이용하는 방법이 아닌 '. yml' 파일로 환경설정을 구성하였습니다.
💡 참고로 '. java' 파일 내에 @Configuration 어노테이션을 이용한 방법도 참고하였습니다.
구분 | 속성 | 설명 |
PostgreSQL | spring.datasource.driver-class-name | 연결하려는 데이터베이스 드라이브를 입력합니다 |
spring.datasource.url | 연결하려는 데이터베이스 URL을 입력합니다 | |
spring.datasource.username | 연결하려는 데이터베이스 사용자 이름을 입력합니다. | |
spring.datasource.password | 연결하려는 데이터베이스 비밀번호를 입력합니다. | |
Mybatis | mybatis.type-aliases-package | Mybatis에서 resultType으로 사용되는 패키지 명의 기본값을 지정합니다. |
mybatis.mapper-locations | Mybatis 파일들의 경로를 지정합니다. classpath: 는 resource 폴더를 바라보고 있습니다. |
|
mybatis.configuration.map-underscore-to-camel-case | Mybatis의 쿼리 수행 이후 반환 값을 CamelCase로 반환 받습니다. |
2.1. Mybatis 구성을 '. yml' 파일로 지정하는 방법
spring:
# PostgreSQL DB 설정
datasource:
driver-class-name: org.postgresql.Driver
url: jdbc:postgresql://localhost:5432/postgres
username:
password:
# Mybatis 설정
mybatis:
# default Package location - resultType의 Alias를 지정합니다.
type-aliases-package: com.demo.demoApi.model
# mapper location - 바라 볼 xml 파일을 지정합니다.
mapper-locations: classpath:mapper/*.xml
# column name to camel case - 반환 받는 컬럼명을 CamelCase로 받는 설정을 합니다.
configuration:
map-underscore-to-camel-case: true
2.2. Mybatis 구성을 '. java' 파일로 지정하는 방법
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.sql.DataSource;
/**
* 데이터 베이스 연결에 사용이 된다.
*/
@Configuration
@MapperScan(basePackages = "com.demo.demoApi.mapper")
@EnableTransactionManagement
public class DBConfig {
/**
* SqlSessionFactory 구성
* - MyBatis 설정 파일을 읽어들여 SqlSession을 생성하는 팩토리 클래스
* 1. DataSource 지정
* 2. Mapper.xml 파일 연결
* 3. 최종 구성 객체 반환
*
* @param dataSource
* @return
* @throws Exception
*/
@Bean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
sessionFactory.setDataSource(dataSource); // 데이터베이스와 연결을 위한 DataSource 지정
sessionFactory.setTypeAliasesPackage("com.adjh.multiflexapi.model");
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
sessionFactory.setMapperLocations(resolver.getResources("mapper/*.xml")); // 구성한 Mapper 파일의 경로를 지정
return sessionFactory.getObject(); // SqlSessionFactory 객체 구성
}
/**
* SqlSessionTemplate 구성
* - SQL 실행과 트랜잭션 관리를 담당하며, SqlSession 인스턴스의 생명주기를 관리하고 필요한 설정을 자동으로 수행
*
* @param sqlSessionFactory
* @return
* @throws Exception
*/
@Bean
public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) throws Exception {
final SqlSessionTemplate sqlSessionTemplate = new SqlSessionTemplate(sqlSessionFactory);
return sqlSessionTemplate;
}
}
[참고] Mybatis의 default Schema를 구성하는 방법
💡 spring.datasource.url 내에 ‘쿼리 스트링’으로 currentSchema = default Schema를 정의합니다.
spring:
# PostgreSQL DB 설정
datasource:
driver-class-name: org.postgresql.Driver
jdbc-url: jdbc:postgresql://localhost:8080/TEST_DATABASE?currentSchema=default_schema
username: name
password: password
3) 프로젝트 파일 구성하기
1. TemplateVO.java
💡 해당 파일은 객체를 구성하는 목적으로 사용되는 파일입니다.
💡 Lombok 라이브러리의 @Data 어노테이션을 통하여서 getter / setter / toString() 메서드 사용을 축약하였습니다.
/**
* [ 템플릿 설명 ]
* - 해당 파일은 객체를 구성하는 목적으로 사용되는 파일입니다.
* - Lombok 기능을 이용하여 간단한 VO 구성을 하였습니다.
*/
@Data // getter / setter / toString() 사용
@NoArgsConstructor // 생성자를 사용하지 않도록 선언
public class TemplateVO {
private Integer templateId;
private String templateName;
private String templateEtc;
}
💡 [참고] Lombok에 대해 궁금하시면 아래의 글을 참고하시면 도움이 됩니다.
[Java] 생성자 패턴 이해하기 : 점층적 생성자, 자바 빈즈, Builder 패턴)
해당 글에서는 생성자 패턴에 대해서 이해하고, 어떤 패턴으로 생성자를 구성하는 것이 좋을지에 대해서 공유합니다. 1) 생성자 패턴의 종류 1. 점층적 생성자 패턴 (Telescoping Constructor Pattern) 💡
adjh54.tistory.com
[Java] 생성자 패턴 - Builder() 심화 속성 이해하기 -1 : Lombok Annotation
해당 글에서는 생성자 패턴 중 Builder() 패턴을 기반으로 상세 속성을 이용하여 심화 내용의 이해를 돕기 위한 목적으로 작성한 글입니다. 💡 해당 글은 이전에 작성한 Builder() 생성자 패턴에 대
adjh54.tistory.com
2. TemplateMapper.java
💡 해당 파일은 xml 파일과 1:1 매핑되는 인터페이스입니다. (환경 파일 내에서 지정함)
💡 해당 파일에서는 CRUD 쿼리에 대한 인터페이스를 구성하였습니다.
/**
* - 해당 파일은 xml 파일과 1:1 매핑되는 인터페이스 입니다. (환경파일 내에서 지정함)
* - 해당 Mapper 폴더는 @Repository 어노테이션을 필수적으로 사용합니다.
* [ 참고 ]
* - xml 파일이 아닌 해당 파일 내에서 처리하려면 @Mapper 어노테이션을 사용하길 권장합니다.
*/
@Repository
public interface TemplateMapper {
List<TemplateVO> selectTempList();
TemplateVO selectTempById(Integer templateId);
int insertTemp(TemplateVO templateVO);
int updateTemp(TemplateVO templateVO);
int deleteTempById(Integer templateId);
}
3. TemplateMapper.xml
💡 해당 파일은 SQL문을 작성하는 곳입니다.
💡 해당 경로는 src/main/resource/mapper/TemplateMapper.xml 형태로 구성하였습니다.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--
[템플릿 설명]
- 해당 파일은 SQL 문을 작성하는 곳입니다.
-->
<mapper namespace="com.demo.demoApi.mapper.TemplateMapper">
<select id="selectTempList" resultType="TemplateVO">
SELECT template_id,
template_name,
template_etc
FROM tb_template;
</select>
<select id="selectTempById" resultType="TemplateVO">
SELECT template_id,
template_name,
template_etc
FROM tb_template
WHERE template_id = #{templateId}
</select>
<insert id="insertTemp" parameterType="TemplateVO">
INSERT INTO tb_template(template_id, template_name, template_etc)
values (#{templateId}, #{templateName}, #{templateEtc});
</insert>
<update id="updateTemp" parameterType="TemplateVO">
UPDATE tb_template
SET template_name= #{templateName}
, template_etc = #{templateEtc}
WHERE template_id = #{templateId}
</update>
<!--테이블 row delete-->
<delete id="deleteTempById">
DELETE
FROM tb_template
WHERE template_id = #{templateId}
</delete>
</mapper>
4. TemplateService.java
💡 해당 파일은 *ServiceImpl 내에서 구현된 구현체를 사용하기 위한 인터페이스입니다.
/**
* [ 템플릿 설명 ]
* - 해당 파일은 **ServiceImpl 내에서 구현된 구현체를 사용하기 위한 인터페이스 입니다.
* - 해당 파일의 기능은 구현체에서 작성한 비즈니스 로직을 Controller 내에서 호출하기 위한 interface 입니다.
*
* @author lee
* @since 2022.09.30
*/
@Service
public interface TemplateService {
List<TemplateVO> selectTempList();
TemplateVO selectTempById(Integer templateId);
int insertTemp(TemplateVO templateVO);
int updateTemp(TemplateVO templateVO);
int deleteTempById(Integer templateId);
}
5. TemplateServiceImpl.java
💡 해당 파일은 실제 비즈니스 로직에 대한 구현을 구성하는 파일입니다.
💡 간단하게 데이터 처리를 하는 Mapper의 처리과정을 가져오는 부분만 구현을 하였습니다.
/**
* [ 템플릿 설명 ]
* - 해당 파일은 서비스의 비즈니스 로직을 구현하는 곳입니다.
* - 해당 *ServiceImpl 에서는 @Service 어노테이션을 필수적으로 사용합니다.
*/
@Slf4j
@Service
public class TemplateServiceImpl implements TemplateService {
/**
* '생성자 주입 형태'로 사용합니다.
* - Autowired 는 권장되지 않기에 생성자 주입 형태로 구성합니다.
*/
private final SqlSession sqlSession;
public TemplateServiceImpl(SqlSession ss) {
this.sqlSession = ss;
}
/**
* Template 리스트 값 조회
*
* @return List<TemplateVO> 반환값
*/
@Transactional(readOnly = true)
public List<TemplateVO> selectTempList() {
TemplateMapper tm = sqlSession.getMapper(TemplateMapper.class);
return tm.selectTempList();
}
/**
* 키 값을 기반으로 Template 리스트 조회
*
* @param templateId 조회 키 값
* @return TemplateVO 반환 값
*/
@Transactional(readOnly = true)
public TemplateVO selectTempById(Integer templateId) {
TemplateMapper tm = sqlSession.getMapper(TemplateMapper.class);
return tm.selectTempById(templateId);
}
/**
* Template INSERT
*
* @param templateVO 저장 할 값
* @return TemplateVO 결과값 반환
*/
@Transactional
public int insertTemp(TemplateVO templateVO) {
TemplateMapper tm = sqlSession.getMapper(TemplateMapper.class);
return tm.insertTemp(templateVO);
}
/**
* Template Update
*
* @param templateVO Update Value
* @return TemplateVO 결과값 반환
*/
@Transactional
public int updateTemp(TemplateVO templateVO) {
TemplateMapper tm = sqlSession.getMapper(TemplateMapper.class);
return tm.updateTemp(templateVO);
}
/**
* Template Delete
*
* @param tempId 삭제 아이디
* @return TemplateVO 결과값 반환
*/
@Transactional
public int deleteTempById(Integer templateId) {
TemplateMapper tm = sqlSession.getMapper(TemplateMapper.class);
return tm.deleteTempById(templateId);
}
}
6. TemplateController.java
💡 해당 파일에서는 직접적으로 URL을 통하여서 페이지를 리턴하거나 API 역할을 수행하는 파일이다.
/**
* [ 템플릿 설명 ]
* - 해당 파일은 Restful API 형태로 URL 관리하는 파일입니다
* - 뷰 자체만을 리턴해주거나 API 호출에 대한 처리를 해줍니다.
* [ Annotation 설명 ]
* - @Slf4j : 로그를 위해 사용하는 Annotation
* - @RestController: Restful API 구조에서 JSON 타입으로 데이터를 반환 받기 위해 사용하는 Annotation
* - @Controller: Spring MVC 패턴을 사용하기 위한 Annotation
* - @RequestMapper: Controller URL Default
*
* @author lee
* @since 2022.09.30
*/
@Slf4j
@RequestMapping("/temp")
@Controller
public class TemplateController {
// 필드 주입이 아닌 생성자 주입형태로 사용합니다. '생성자 주입 형태'로 사용합니다.
private final TemplateService templateService;
public TemplateController(TemplateService ts) {
this.templateService = ts;
}
/**
* [VIEW] Thymeleaf 화면 만을 출력하는 함수
*
* @param model 전송 할 데이터
* @return 페이지
*/
@GetMapping("main")
public String selectTemplateView(Model model) {
model.addAttribute("title", "템플릿 화면");
return "temp/templatePage";
}
/**
* [API] 템플릿 리스트 출력 함수
*
* @return ApiResponseWrapper<List < TemplateVO>> : 응답 결과 및 응답 코드 반환
*/
@PostMapping("templateList")
public ResponseEntity<List<TemplateVO>> selectTemplateList() {
List<TemplateVO> resultList = templateService.selectTempList();
return new ResponseEntity<>(resultList, HttpStatus.OK);
}
/**
* [API] 템플릿 아이디 별 조회
*
* @param templateVO 템플릿 생성 데이터
* @return ApiResponseWrapper<TemplateVO> : 응답 결과 및 응답 코드 반환
*/
@PutMapping("selectTempById")
public ResponseEntity<TemplateVO> selectTemplateById(@Valid @RequestBody TemplateVO templateVO) {
TemplateVO result = templateService.selectTempById(templateVO.getTemplateId());
return new ResponseEntity<>(result, HttpStatus.OK);
}
/**
* [API] 템플릿 생성 함수
*
* @param templateVO 템플릿 생성 데이터
* @return ApiResponseWrapper<TemplateVO> : 응답 결과 및 응답 코드 반환
*/
@PostMapping("insertTemplate")
public ResponseEntity<Integer> insertTemplate(@Valid @RequestBody TemplateVO templateVO) {
Integer result = templateService.insertTemp(templateVO);
return new ResponseEntity<>(result, HttpStatus.OK);
}
/**
* [API] 템플릿 수정 함수
*
* @param templateVO 템플릿 생성 데이터
* @return ApiResponseWrapper<TemplateVO> : 응답 결과 및 응답 코드 반환
*/
@PutMapping("updateTemplate")
public ResponseEntity<Integer> updateTemplate(@Valid @RequestBody TemplateVO templateVO) {
Integer result = templateService.updateTemp(templateVO);
return new ResponseEntity<>(result, HttpStatus.OK);
}
/**
* [API] 템플릿 삭제 함수
*
* @param templateVO 템플릿 생성 데이터
* @return ApiResponseWrapper<TemplateVO> : 응답 결과 및 응답 코드 반환
*/
@DeleteMapping("deleteTemplate")
public ResponseEntity<Integer> deleteTemplate(@Valid @RequestBody TemplateVO templateVO) {
Integer result = templateService.deleteTempById(templateVO.getTemplateId());
return new ResponseEntity<>(result, HttpStatus.OK);
}
}
4) 결과 화면
💡 해당 테스트는 구성한 프로젝트를 기준으로 Postman 툴을 이용하여서 API 테스트를 진행하였습니다
1. 리스트 조회
![](https://blog.kakaocdn.net/dn/043DX/btrNMF8z1BL/yCLFTEpWA9VpwC3hW5qsxk/img.png)
2. 추가
![](https://blog.kakaocdn.net/dn/uvWcf/btrNNoL9Ndt/NHKVaC3laK0xO9Bd8pGHp1/img.png)
3. 수정
![](https://blog.kakaocdn.net/dn/rYdSi/btrNKWCRAUG/eTWPLBo0L0Z0WHvUJ6Zd31/img.png)
4. 삭제
![](https://blog.kakaocdn.net/dn/dL6svd/btrNNZSLJ5T/9pkgw5QkEay1mfSW2Glkqk/img.png)
5. 리스트 조회
![](https://blog.kakaocdn.net/dn/b6S2Da/btrNFTfPWpR/UHu49U4aZx9CCHkCldu7Sk/img.png)
5) 참고
💡 [참고] 해당 프로젝트를 구성한 아키텍처와 관한 글입니다.
[Java] 계층화된 아키텍처(Layered Architecture) : N Tier Architecture
해당 글에서는 Java의 아키텍처 구성 중 계층화된 아키텍처인 N Tier 아키텍처에 대해서 이해를 돕기 위해 작성한 글입니다. 1) 계층화된 아키텍처(Layered Architecture) 💡 계층화된 아키텍처란? - 계층
adjh54.tistory.com
💡 [참고] RESTful은 정확하게 사용하고 있는지 설계 방법에 관한 글입니다.
[Java] REST API 설계 방법 -1 : 이해하기
해당 글에서는 Restful API에 대해서 이해하며 이를 통해 설계를 하는 방법에 대해서 이해하기 위해 작성한 글입니다. 1) REST / RESTful API 💡 REST(Representational State Transfer)란? - 웹 애플리케이션을 개발
adjh54.tistory.com
[Java] RESTful API 설계 방법 -2 : 구성하기
해당 글에서는 Restful API의 제약 조건과 설계 방법에 대해 이해한 것을 바탕으로 실제 RESTful API를 구성하는 목적으로 작성하였습니다. 💡 이전에 이해한 RESTful API 설계 방법을 기반으로 해당 글
adjh54.tistory.com
💡 [참고] 로컬 PostgreSQL 데이터베이스 구성 방법에 관한 글입니다.
[DB] PostgreSQL 로컬 데이터베이스 구성 방법
해당 글에서는 PostgreSQL을 로컬 디비로 구성하는 방법에 대해서 공유합니다. 1) PostgreSQL을 설치합니다. 💡 PostgreSQL의 버전을 확인하고 설치가 안 되어 있다면 설치를 하고 서비스를 수행합니다. #
adjh54.tistory.com
💡[참고]JDBC의 'HikariCP'를 이용하여 Connection Pool을 관리하는 방법에 대해서 설정을 하면 도움이 많이 됩니다.
[Java/Library] HikariCP 이해하고 적용하기 (with. MyBatis)
해당 글에서는 HikariCP에 대해 이해하고 영속성 프레임워크(Persistence Framework)인 MyBatis와 연동을 하는 적용 방법에 대해서 공유 목적으로 작성한 글입니다. [참고] 이전에 구성하였던 환경에 'HikariC
adjh54.tistory.com
💡[참고] 해당 부분에 이어서 Spring Security를 구성하는 방법입니다.
[Java] Spring Boot Security 이해하기 -2 : 5.7.x 버전 구현하기
해당 글에서는 이전에 Spring Security 5.7.x 버전에 대해 이해한 내용을 기반으로 실제 구현하는 방법에 대해서 공유합니다. [참고] Spring Boot Security를 적용하기 이전의 이해하기 위한 글을 참고하시
adjh54.tistory.com
💡[참고] Spring Security에서 이어서 JWT를 통한 인증 방식을 구성하는 방법입니다.
[Java] Spring Boot Security 이해하기 -4: JWT 환경 설정 및 구성 하기
해당 글에서는 Spring Boot Security내에 ‘인증’ 방식을 JWT를 이용하여서 사용자의 인증을 구성하는 환경 설정방법에 대해서 이해하기 위한 글입니다. [참고] 해당 글은 이전에 작성한 'JWT 이론'에
adjh54.tistory.com
💡 [참고] 해당 내용을 담은 Repository입니다.
blog-codes/spring-boot-3tier-form at main · adjh54ir/blog-codes
Contributor9 티스토리 블로그 내에서 활용한 내용들을 담은 레포지토리입니다. Contribute to adjh54ir/blog-codes development by creating an account on GitHub.
github.com
오늘도 감사합니다😀
'Java > Spring Boot' 카테고리의 다른 글
[Java/Library] Thymeleaf, Thymeleaf Layout 적용하기 (6) | 2022.10.30 |
---|---|
[Java/Library] HikariCP 이해하고 적용하기 (with. MyBatis) (0) | 2022.10.20 |
[Java/Library] Spring Boot 2.x 환경에서 Swagger 이해하고 적용하기 : SpringDoc openAPI UI (2) | 2022.10.18 |
[Java/Library] Lombok 이해하고 적용하기 -1 : 설정 및 기초 (0) | 2022.10.18 |
[Java/IntelliJ] Spring Boot Devtools 이해하고 설정하기 (2) | 2022.09.29 |