반응형
해당 글에서는 Spring Boot내에 Mybatis와 PostgreSQL을 연결하고 로직 처리를 위한 환경 설정 및 파일 구성에 대해서 공유합니다.
💡 최하단에 해당 환경 구성과 관련하여 '로컬 DB 구성 방법', 'HikariCP'를 통한 Connection 관리, 'Spring Security' 구성 및 'JWT'를 통한 인증 방법에 대해서 관련 글들도 참고해 보시면 좋을 것 같습니다 🙏
1) 사전 확인 작업
1. DB 드라이버 설치 확인
# postgreSQL 버전을 확인한다.
$ postgres --version
# 설치가 안되었다면 설치를 한다.
$ brew install postgresql
2. 개발 환경 확인
구분 | 언어 / 라이브러리 |
언어 | Java |
웹 프레임워크 | Spring Boot |
Persistence Framework | Mybatis |
자동화 빌드 툴 | Gradle |
3. 데이터 흐름 확인
💡 [참고] 구성에 사용 N-Tier Architecure에 대해 궁금하시면 아래의 글을 참고하시면 도움이 됩니다.
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에 대해 궁금하시면 아래의 글을 참고하시면 도움이 됩니다.
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. 리스트 조회
2. 추가
3. 수정
4. 삭제
5. 리스트 조회
5) 참고
💡 [참고] 해당 프로젝트를 구성한 아키텍처와 관한 글입니다.
💡 [참고] RESTful은 정확하게 사용하고 있는지 설계 방법에 관한 글입니다.
💡 [참고] 로컬 PostgreSQL 데이터베이스 구성 방법에 관한 글입니다.
💡[참고]JDBC의 'HikariCP'를 이용하여 Connection Pool을 관리하는 방법에 대해서 설정을 하면 도움이 많이 됩니다.
💡[참고] 해당 부분에 이어서 Spring Security를 구성하는 방법입니다.
💡[참고] Spring Security에서 이어서 JWT를 통한 인증 방식을 구성하는 방법입니다.
💡 [참고] 해당 내용을 담은 Repository입니다.
오늘도 감사합니다😀
반응형
'Java > Spring Boot' 카테고리의 다른 글
[Java/Library] Slf4j - Log4j2 이해하고 설정하기 (2) | 2022.10.21 |
---|---|
[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 |