Compare commits

...

1 Commits

Author SHA1 Message Date
박성영 43d8dae41b 멀티 디비 최초 적용 5 months ago

@ -0,0 +1,3 @@
{
"svn.ignoreMissingSvnWarning": true
}

@ -154,6 +154,7 @@ dependencies {
providedCompile "org.apache.tomcat:tomcat-servlet-api:${tomcatVersion}"
// -
providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'
implementation 'org.springframework.boot:spring-boot-starter-jta-atomikos'
}
// ===== =====

@ -1,66 +0,0 @@
package egovframework.config;
import egovframework.exception.EgovAopExceptionTransfer;
import egovframework.exception.EgovDefaultExcepHndlr;
import egovframework.exception.EgovDefaultOthersExcepHndlr;
import org.egovframe.rte.fdl.cmmn.aspect.ExceptionTransfer;
import org.egovframe.rte.fdl.cmmn.exception.handler.ExceptionHandler;
import org.egovframe.rte.fdl.cmmn.exception.manager.DefaultExceptionHandleManager;
import org.egovframe.rte.fdl.cmmn.exception.manager.ExceptionHandlerService;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.util.AntPathMatcher;
@Configuration
@EnableAspectJAutoProxy
public class EgovConfigAspect {
@Bean
public EgovDefaultExcepHndlr egovHandler() {
return new EgovDefaultExcepHndlr();
}
@Bean
public EgovDefaultOthersExcepHndlr otherHandler() {
return new EgovDefaultOthersExcepHndlr();
}
@Bean
public DefaultExceptionHandleManager defaultExceptionHandleManager(AntPathMatcher antPathMatcher, EgovDefaultExcepHndlr egovHandler) {
DefaultExceptionHandleManager defaultExceptionHandleManager = new DefaultExceptionHandleManager();
defaultExceptionHandleManager.setReqExpMatcher(antPathMatcher);
defaultExceptionHandleManager.setPatterns(new String[]{"**service.impl.*"});
defaultExceptionHandleManager.setHandlers(new ExceptionHandler[]{egovHandler});
return defaultExceptionHandleManager;
}
@Bean
public DefaultExceptionHandleManager otherExceptionHandleManager(AntPathMatcher antPathMatcher, EgovDefaultOthersExcepHndlr othersExcepHndlr) {
DefaultExceptionHandleManager defaultExceptionHandleManager = new DefaultExceptionHandleManager();
defaultExceptionHandleManager.setReqExpMatcher(antPathMatcher);
defaultExceptionHandleManager.setPatterns(new String[]{"**service.impl.*"});
defaultExceptionHandleManager.setHandlers(new ExceptionHandler[]{othersExcepHndlr});
return defaultExceptionHandleManager;
}
@Bean
public ExceptionTransfer exceptionTransfer(
@Qualifier("defaultExceptionHandleManager") DefaultExceptionHandleManager defaultExceptionHandleManager,
@Qualifier("otherExceptionHandleManager") DefaultExceptionHandleManager otherExceptionHandleManager) {
ExceptionTransfer exceptionTransfer = new ExceptionTransfer();
exceptionTransfer.setExceptionHandlerService(new ExceptionHandlerService[] {
defaultExceptionHandleManager, otherExceptionHandleManager
});
return exceptionTransfer;
}
@Bean
public EgovAopExceptionTransfer aopExceptionTransfer(ExceptionTransfer exceptionTransfer) {
EgovAopExceptionTransfer egovAopExceptionTransfer = new EgovAopExceptionTransfer();
egovAopExceptionTransfer.setExceptionTransfer(exceptionTransfer);
return egovAopExceptionTransfer;
}
}

@ -0,0 +1,62 @@
package egovframework.config;
import com.atomikos.jdbc.AtomikosDataSourceBean;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import javax.sql.DataSource;
import java.util.Properties;
@Configuration
@MapperScan(basePackages = "egovframework, go.kr.project.**.mapper", sqlSessionFactoryRef = "sqlSessionFactory")
public class EgovConfigDatabase {
@Value("${spring.datasource.xa-data-source-class-name}")
private String xaDataSourceClassName;
@Value("${spring.datasource.url}")
private String url;
@Value("${spring.datasource.username}")
private String username;
@Value("${spring.datasource.password}")
private String password;
@Bean(name = "dataSource")
@Primary
public DataSource dataSource() {
AtomikosDataSourceBean xaDataSource = new AtomikosDataSourceBean();
xaDataSource.setUniqueResourceName("db1");
xaDataSource.setXaDataSourceClassName(xaDataSourceClassName);
Properties xaProps = new Properties();
xaProps.setProperty("user", username);
xaProps.setProperty("password", password);
xaProps.setProperty("url", url);
xaDataSource.setXaProperties(xaProps);
return xaDataSource;
}
@Value("${mybatis.config-location}")
private String mybatisConfigLocation;
@Value("${mybatis.mapper-locations}")
private String mybatisMapperLocations;
@Value("${mybatis.type-aliases-package}")
private String mybatisTypeAliasesPackage;
@Bean(name = "sqlSessionFactory")
@Primary
public SqlSessionFactory sqlSessionFactory(@Qualifier("dataSource") DataSource dataSource) throws Exception {
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
factoryBean.setDataSource(dataSource);
factoryBean.setConfigLocation(new PathMatchingResourcePatternResolver().getResource(mybatisConfigLocation));
factoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(mybatisMapperLocations));
factoryBean.setTypeAliasesPackage(mybatisTypeAliasesPackage);
return factoryBean.getObject();
}
}

@ -0,0 +1,59 @@
package egovframework.config;
import com.atomikos.jdbc.AtomikosDataSourceBean;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import javax.sql.DataSource;
import java.util.Properties;
@Configuration
@MapperScan(basePackages = "go.kr.project.**.mapper2", sqlSessionFactoryRef = "sqlSessionFactory2")
public class EgovConfigDatabase2 {
@Value("${spring.datasource-second.xa-data-source-class-name}")
private String xaDataSourceClassName;
@Value("${spring.datasource-second.url}")
private String url;
@Value("${spring.datasource-second.username}")
private String username;
@Value("${spring.datasource-second.password}")
private String password;
@Bean(name = "dataSource2")
public DataSource dataSource2() {
AtomikosDataSourceBean xaDataSource = new AtomikosDataSourceBean();
xaDataSource.setUniqueResourceName("db2");
xaDataSource.setXaDataSourceClassName(xaDataSourceClassName);
Properties xaProps = new Properties();
xaProps.setProperty("user", username);
xaProps.setProperty("password", password);
xaProps.setProperty("url", url);
xaDataSource.setXaProperties(xaProps);
return xaDataSource;
}
@Value("${mybatis2.config-location}")
private String mybatisConfigLocation;
@Value("${mybatis2.mapper-locations}")
private String mybatisMapperLocations;
@Value("${mybatis2.type-aliases-package}")
private String mybatisTypeAliasesPackage;
@Bean(name = "sqlSessionFactory2")
public SqlSessionFactory sqlSessionFactory2(@Qualifier("dataSource2") DataSource dataSource2) throws Exception {
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
factoryBean.setDataSource(dataSource2);
factoryBean.setConfigLocation(new PathMatchingResourcePatternResolver().getResource(mybatisConfigLocation));
factoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(mybatisMapperLocations));
factoryBean.setTypeAliasesPackage(mybatisTypeAliasesPackage);
return factoryBean.getObject();
}
}

@ -0,0 +1,45 @@
package egovframework.config;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.aop.Advisor;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.interceptor.*;
import org.springframework.transaction.jta.JtaTransactionManager;
import java.util.Collections;
import java.util.HashMap;
@Configuration
public class EgovConfigJtaAop {
@Bean
public TransactionInterceptor txAdvice(JtaTransactionManager jtaTransactionManager) {
TransactionInterceptor txAdvice = new TransactionInterceptor();
txAdvice.setTransactionManager(jtaTransactionManager);
txAdvice.setTransactionAttributeSource(getNameMatchTransactionAttributeSource());
return txAdvice;
}
private NameMatchTransactionAttributeSource getNameMatchTransactionAttributeSource() {
NameMatchTransactionAttributeSource txAttributeSource = new NameMatchTransactionAttributeSource();
HashMap<String, TransactionAttribute> txMethods = new HashMap<>();
RuleBasedTransactionAttribute txAttribute = new RuleBasedTransactionAttribute();
txAttribute.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
txAttribute.setRollbackRules(Collections.singletonList(new RollbackRuleAttribute(Exception.class)));
txMethods.put("*", txAttribute);
txAttributeSource.setNameMap(txMethods);
return txAttributeSource;
}
@Bean
public Advisor txAdvisor(TransactionInterceptor txAdvice) {
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
pointcut.setExpression(
"execution(* go.kr.project..impl.*Impl.*(..)) or execution(* egovframework.com..*Impl.*(..))"
);
return new DefaultPointcutAdvisor(pointcut, txAdvice);
}
}

@ -1,95 +0,0 @@
package egovframework.config;
import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.Advisor;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.interceptor.*;
import javax.annotation.PostConstruct;
import javax.sql.DataSource;
import java.util.Collections;
import java.util.HashMap;
/**
* @ClassName : EgovConfigAppTransaction.java
* @Description : Transaction
*
* @author :
* @since : 2021. 7. 20
* @version : 1.0
*
* <pre>
* << (Modification Information) >>
*
*
* ------------- ------------ ---------------------
* 2021. 7. 20
* </pre>
*
*/
@Slf4j
@Configuration
public class EgovConfigTransaction {
@Autowired
DataSource dataSource;
@PostConstruct
public void init() {
log.info("Datasource type: {}", dataSource.getClass().getName());
}
@Bean
public DataSourceTransactionManager txManager() {
DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
dataSourceTransactionManager.setDataSource(dataSource);
return dataSourceTransactionManager;
}
// -------------------------------------------------------------
// TransactionAdvice 설정
// -------------------------------------------------------------
@Bean
public TransactionInterceptor txAdvice(DataSourceTransactionManager txManager) {
TransactionInterceptor txAdvice = new TransactionInterceptor();
txAdvice.setTransactionManager(txManager);
txAdvice.setTransactionAttributeSource(getNameMatchTransactionAttributeSource());
return txAdvice;
}
private NameMatchTransactionAttributeSource getNameMatchTransactionAttributeSource() {
NameMatchTransactionAttributeSource txAttributeSource = new NameMatchTransactionAttributeSource();
txAttributeSource.setNameMap(getRuleBasedTxAttributeMap());
return txAttributeSource;
}
private HashMap<String, TransactionAttribute> getRuleBasedTxAttributeMap() {
HashMap<String, TransactionAttribute> txMethods = new HashMap<String, TransactionAttribute>();
RuleBasedTransactionAttribute txAttribute = new RuleBasedTransactionAttribute();
txAttribute.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
txAttribute.setRollbackRules(Collections.singletonList(new RollbackRuleAttribute(Exception.class)));
txMethods.put("*", txAttribute);
return txMethods;
}
// -------------------------------------------------------------
// TransactionAdvisor 설정
// -------------------------------------------------------------
@Bean
public Advisor txAdvisor(DataSourceTransactionManager txManager) {
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
pointcut.setExpression(
"execution(* go.kr.project..impl.*Impl.*(..)) or execution(* egovframework.com..*Impl.*(..))");
return new DefaultPointcutAdvisor(pointcut, txAdvice(txManager));
}
}

@ -1,20 +0,0 @@
package egovframework.config;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.validation.Validator;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
@Configuration
public class EgovConfigValidation {
@Bean
public Validator getValidator(@Qualifier("messageSource") MessageSource messageSource) {
LocalValidatorFactoryBean localValidatorFactoryBean = new LocalValidatorFactoryBean();
localValidatorFactoryBean.setValidationMessageSource(messageSource);
return localValidatorFactoryBean;
}
}

@ -7,7 +7,6 @@ import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.http.CacheControl;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
@ -22,14 +21,6 @@ import java.util.List;
@Setter
@Configuration
@RequiredArgsConstructor
@Import({
EgovConfigAspect.class,
EgovConfigCommon.class,
EgovConfigTransaction.class,
EgovConfigValidation.class,
EgovConfigInterceptor.class,
EgovErrorConfig.class
})
public class EgovConfigWeb implements WebMvcConfigurer, ApplicationContextAware {
private ApplicationContext applicationContext;

@ -0,0 +1,132 @@
package go.kr.project.template.noticeSample.mapper2;
import go.kr.project.template.noticeSample.model.NoticeSampleFileVO;
import go.kr.project.template.noticeSample.model.NoticeSampleVO;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
* packageName : go.kr.project.crudtemplate.notice.mapper
* fileName : BbsNoticeMapper
* author :
* date : 2025-05-17
* description : Mapper
* ===========================================================
* DATE AUTHOR NOTE
* -----------------------------------------------------------
* 2025-05-17
*/
@Mapper
public interface NoticeSampleMapper2 {
/**
* .
*
* @param noticeId ID
* @return
*/
NoticeSampleVO selectNotice(String noticeId);
/**
* .
*
* @param vo VO
* @return
*/
List<NoticeSampleVO> selectNoticeList(NoticeSampleVO vo);
/**
* .
*
* @param vo VO
* @return
*/
int selectNoticeListTotalCount(NoticeSampleVO vo);
/**
* ID .
*
* @return BBSN00000001 ID
*/
String generateNoticeId();
/**
* .
*
* @param vo VO
* @return
*/
int insertNotice(NoticeSampleVO vo);
/**
* .
*
* @param vo VO
* @return
*/
int updateNotice(NoticeSampleVO vo);
/**
* .
*
* @param noticeId ID
* @return
*/
int updateNoticeViewCount(String noticeId);
/**
* .
*
* @param noticeId ID
* @return
*/
int deleteNotice(String noticeId);
/**
* .
*
* @param fileId ID
* @return
*/
NoticeSampleFileVO selectNoticeFile(String fileId);
/**
* .
*
* @param noticeId ID
* @return
*/
List<NoticeSampleFileVO> selectNoticeFileList(String noticeId);
/**
* ID .
*
* @return BBSF00000001 ID
*/
String generateFileId();
/**
* .
*
* @param vo VO
* @return
*/
int insertNoticeFile(NoticeSampleFileVO vo);
/**
* .
*
* @param noticeId ID
* @return
*/
int deleteNoticeFileByNoticeId(String noticeId);
/**
* .
*
* @param fileId ID
* @return
*/
int deleteNoticeFile(String fileId);
}

@ -6,6 +6,7 @@ import go.kr.project.common.model.FileVO;
import go.kr.project.common.model.HtmlEditorFileVO;
import go.kr.project.common.service.HtmlEditorService;
import go.kr.project.template.noticeSample.mapper.NoticeSampleMapper;
import go.kr.project.template.noticeSample.mapper2.NoticeSampleMapper2;
import go.kr.project.template.noticeSample.model.NoticeSampleFileVO;
import go.kr.project.template.noticeSample.model.NoticeSampleVO;
import go.kr.project.template.noticeSample.service.NoticeSampleService;
@ -39,6 +40,7 @@ import java.util.List;
public class NoticeSampleSampleServiceImpl extends EgovAbstractServiceImpl implements NoticeSampleService {
private final NoticeSampleMapper noticeSampleMapper;
private final NoticeSampleMapper2 noticeSampleMapper2;
private final FileUtil fileUtil;
private final HtmlEditorService htmlEditorService;
@ -53,7 +55,7 @@ public class NoticeSampleSampleServiceImpl extends EgovAbstractServiceImpl imple
public NoticeSampleVO selectNotice(String noticeId, boolean increaseViewCnt) {
// 조회수 증가 처리
if (increaseViewCnt) {
noticeSampleMapper.updateNoticeViewCount(noticeId);
noticeSampleMapper2.updateNoticeViewCount(noticeId);
}
// 게시물 정보 조회

@ -9,6 +9,7 @@ spring:
restart:
enabled: true
datasource:
xa-data-source-class-name: org.mariadb.jdbc.MariaDbDataSource
driver-class-name: org.mariadb.jdbc.Driver
url: jdbc:mariadb://211.119.124.9:4407/xitframework?characterEncoding=UTF-8&serverTimezone=Asia/Seoul
username: egov
@ -22,6 +23,19 @@ spring:
validation-timeout: 60000 #60초
#hikari.connection-test-query 는 JDBC 4.0 이상을 사용하면 설정하지 않는 것을 권장. (공식문서)
#connection-test-query: select 1
datasource-second:
xa-data-source-class-name: org.mariadb.jdbc.MariaDbDataSource
driver-class-name: org.mariadb.jdbc.Driver
url: jdbc:mariadb://211.119.124.9:4407/xitframework?characterEncoding=UTF-8&serverTimezone=Asia/Seoul
username: egov
password: xit1807
hikari:
maximum-pool-size: 10
minimum-idle: 5
connection-timeout: 30000
idle-timeout: 600000
max-lifetime: 1800000
validation-timeout: 60000
mail:
host: smtp.gmail.com
port: 587
@ -96,4 +110,4 @@ batch:
archive-dir: d:/data/xit-framework/batch/zip/archive # ZIP 파일 아카이브 디렉토리
error-archive-dir: d:/data/xit-framework/batch/zip/error-archive # ZIP 파일 에러 아카이브 디렉토리
error-extract-dir: d:/data/xit-framework/batch/zip/error-extract # ZIP 파일 에러 압축해제파일 디렉토리 (하위 :/yyyy/zip file name/)
create-date-subdir-pattern: yyyy # yyyy, yyyyMM, yyyyMMdd 하위 디렉토리 구조
create-date-subdir-pattern: yyyy # yyyy, yyyyMM, yyyyMMdd 하위 디렉토리 구조

@ -58,6 +58,11 @@ mybatis:
mapper-locations: classpath:mybatis/mapper/**/*_${Globals.DbType}.xml
type-aliases-package: go.kr.project.**.model,egovframework.**.model
mybatis2:
config-location: classpath:mybatis/mybatis-config.xml
mapper-locations: classpath:mybatis/mapper2/**/*.xml
type-aliases-package: go.kr.project.**.model,egovframework.**.model
# Springdoc OpenAPI 설정
springdoc:
api-docs:

@ -0,0 +1,293 @@
<?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">
<mapper namespace="go.kr.project.template.noticeSample.mapper2.NoticeSampleMapper2">
<!-- 게시물 정보 조회 -->
<select id="selectNotice" parameterType="String" resultType="go.kr.project.template.noticeSample.model.NoticeSampleVO">
SELECT
n.NOTICE_ID,
n.TITLE,
n.CONTENT,
n.WRITER_NM,
n.VIEW_CNT,
n.NOTICE_YN,
n.USE_YN,
n.REG_DTTM,
n.RGTR,
n.MDFCN_DTTM,
n.MDFR,
r.USER_NM as rgtrName,
r.USER_ACNT as rgtrAcnt,
m.USER_NM as mdfrName,
m.USER_ACNT as mdfrAcnt
FROM
tb_bbs_notice_sample n
LEFT JOIN tb_user r ON n.RGTR = r.USER_ID
LEFT JOIN tb_user m ON n.MDFR = m.USER_ID
WHERE
n.NOTICE_ID = #{noticeId}
</select>
<!-- 게시물 목록 조회 -->
<select id="selectNoticeList" parameterType="go.kr.project.template.noticeSample.model.NoticeSampleVO" resultType="go.kr.project.template.noticeSample.model.NoticeSampleVO">
SELECT
n.NOTICE_ID,
n.TITLE,
n.CONTENT,
n.WRITER_NM,
n.VIEW_CNT,
n.NOTICE_YN,
n.USE_YN,
n.REG_DTTM,
n.RGTR,
n.MDFCN_DTTM,
n.MDFR,
r.USER_NM as rgtrName,
r.USER_ACNT as rgtrAcnt,
m.USER_NM as mdfrName,
m.USER_ACNT as mdfrAcnt,
(SELECT COUNT(*) FROM tb_bbs_notice_sample_file f WHERE f.NOTICE_ID = n.NOTICE_ID) AS FILE_COUNT
FROM
tb_bbs_notice_sample n
LEFT JOIN tb_user r ON n.RGTR = r.USER_ID
LEFT JOIN tb_user m ON n.MDFR = m.USER_ID
WHERE
1=1
<if test="searchKeyword != null and searchKeyword != ''">
<choose>
<when test="searchCondition == 'title'">
AND n.TITLE LIKE CONCAT('%', #{searchKeyword}, '%')
</when>
<when test="searchCondition == 'content'">
AND n.CONTENT LIKE CONCAT('%', #{searchKeyword}, '%')
</when>
<when test="searchCondition == 'writer'">
AND m.USER_NM LIKE CONCAT('%', #{searchKeyword}, '%')
</when>
<otherwise>
AND (
n.TITLE LIKE CONCAT('%', #{searchKeyword}, '%')
OR n.CONTENT LIKE CONCAT('%', #{searchKeyword}, '%')
OR m.USER_NM LIKE CONCAT('%', #{searchKeyword}, '%')
)
</otherwise>
</choose>
</if>
<if test="searchUseYn != null and searchUseYn != ''">
AND n.USE_YN = #{searchUseYn}
</if>
<if test='searchStartDt != null and searchEndDt != null'>
AND n.REG_DTTM BETWEEN STR_TO_DATE(CONCAT(#{searchStartDt},' 00:00:00'), '%Y-%m-%d %H:%i:%s')
AND STR_TO_DATE(CONCAT(#{searchEndDt},' 23:59:59'), '%Y-%m-%d %H:%i:%s')
</if>
ORDER BY
n.NOTICE_YN DESC,
n.REG_DTTM DESC
<if test="pagingYn != null and pagingYn.toString() == 'Y'.toString()">
LIMIT #{startIndex}, #{perPage}
</if>
</select>
<!-- 게시물 목록 총 개수 조회 -->
<select id="selectNoticeListTotalCount" parameterType="go.kr.project.template.noticeSample.model.NoticeSampleVO" resultType="int">
SELECT
COUNT(*)
FROM
tb_bbs_notice_sample n
LEFT JOIN tb_user r ON n.RGTR = r.USER_ID
LEFT JOIN tb_user m ON n.MDFR = m.USER_ID
WHERE
1=1
<if test="searchKeyword != null and searchKeyword != ''">
<choose>
<when test="searchCondition == 'title'">
AND n.TITLE LIKE CONCAT('%', #{searchKeyword}, '%')
</when>
<when test="searchCondition == 'content'">
AND n.CONTENT LIKE CONCAT('%', #{searchKeyword}, '%')
</when>
<when test="searchCondition == 'writer'">
AND m.USER_NM LIKE CONCAT('%', #{searchKeyword}, '%')
</when>
<otherwise>
AND (
n.TITLE LIKE CONCAT('%', #{searchKeyword}, '%')
OR n.CONTENT LIKE CONCAT('%', #{searchKeyword}, '%')
OR m.USER_NM LIKE CONCAT('%', #{searchKeyword}, '%')
)
</otherwise>
</choose>
</if>
<if test="searchUseYn != null and searchUseYn != ''">
AND n.USE_YN = #{searchUseYn}
</if>
<if test='searchStartDt != null and searchEndDt != null'>
AND n.REG_DTTM BETWEEN STR_TO_DATE(CONCAT(#{searchStartDt},' 00:00:00'), '%Y-%m-%d %H:%i:%s')
AND STR_TO_DATE(CONCAT(#{searchEndDt},' 23:59:59'), '%Y-%m-%d %H:%i:%s')
</if>
</select>
<!-- 게시물 ID 생성 -->
<select id="generateNoticeId" resultType="String">
SELECT CONCAT('BBSN', LPAD(NEXTVAL(seq_notice_id), 8, '0'))
</select>
<!-- 게시물 정보 등록 -->
<insert id="insertNotice" parameterType="go.kr.project.template.noticeSample.model.NoticeSampleVO">
INSERT INTO tb_bbs_notice_sample (
NOTICE_ID,
TITLE,
CONTENT,
WRITER_NM,
VIEW_CNT,
NOTICE_YN,
USE_YN,
REG_DTTM,
RGTR,
MDFCN_DTTM,
MDFR
) VALUES (
#{noticeId},
#{title},
#{content},
#{writerNm},
#{viewCnt},
#{noticeYn},
#{useYn},
NOW(),
#{rgtr},
NOW(),
#{mdfr}
)
</insert>
<!-- 게시물 정보 수정 -->
<update id="updateNotice" parameterType="go.kr.project.template.noticeSample.model.NoticeSampleVO">
UPDATE
tb_bbs_notice_sample
SET
TITLE = #{title},
CONTENT = #{content},
<if test="writerNm != null">
WRITER_NM = #{writerNm},
</if>
<if test="noticeYn != null">
NOTICE_YN = #{noticeYn},
</if>
<if test="useYn != null">
USE_YN = #{useYn},
</if>
MDFCN_DTTM = NOW(),
MDFR = #{mdfr}
WHERE
NOTICE_ID = #{noticeId}
</update>
<!-- 게시물 조회수 증가 -->
<update id="updateNoticeViewCount" parameterType="String">
UPDATE
tb_bbs_notice_sample
SET
VIEW_CNT = VIEW_CNT + 1
WHERE
NOTICE_ID = #{noticeId}
</update>
<!-- 게시물 정보 삭제 -->
<delete id="deleteNotice" parameterType="String">
DELETE FROM
tb_bbs_notice_sample
WHERE
NOTICE_ID = #{noticeId}
</delete>
<!-- 파일 정보 조회 -->
<select id="selectNoticeFile" parameterType="String" resultType="go.kr.project.template.noticeSample.model.NoticeSampleFileVO">
SELECT
FILE_ID,
NOTICE_ID,
ORIGINAL_FILE_NM,
STORED_FILE_NM,
FILE_PATH,
FILE_SIZE,
FILE_EXT,
REG_DTTM,
RGTR
FROM
tb_bbs_notice_sample_file
WHERE
FILE_ID = #{fileId}
</select>
<!-- 게시물에 첨부된 파일 목록 조회 -->
<select id="selectNoticeFileList" parameterType="String" resultType="go.kr.project.template.noticeSample.model.NoticeSampleFileVO">
SELECT
FILE_ID,
NOTICE_ID,
ORIGINAL_FILE_NM,
STORED_FILE_NM,
FILE_PATH,
FILE_SIZE,
FILE_EXT,
REG_DTTM,
RGTR,
CASE
WHEN FILE_SIZE > 1048576 THEN CONCAT(ROUND(FILE_SIZE/1048576, 2), ' MB')
WHEN FILE_SIZE > 1024 THEN CONCAT(ROUND(FILE_SIZE/1024, 2), ' KB')
ELSE CONCAT(FILE_SIZE, ' bytes')
END AS FILE_SIZE_STR
FROM
tb_bbs_notice_sample_file
WHERE
NOTICE_ID = #{noticeId}
ORDER BY
REG_DTTM DESC
</select>
<!-- 파일 ID 생성 -->
<select id="generateFileId" resultType="String">
SELECT CONCAT('BBSF', LPAD(NEXTVAL(seq_file_id), 8, '0'))
</select>
<!-- 파일 정보 등록 -->
<insert id="insertNoticeFile" parameterType="go.kr.project.template.noticeSample.model.NoticeSampleFileVO">
INSERT INTO tb_bbs_notice_sample_file (
FILE_ID,
NOTICE_ID,
ORIGINAL_FILE_NM,
STORED_FILE_NM,
FILE_PATH,
FILE_SIZE,
FILE_EXT,
REG_DTTM,
RGTR
) VALUES (
#{fileId},
#{noticeId},
#{originalFileNm},
#{storedFileNm},
#{filePath},
#{fileSize},
#{fileExt},
NOW(),
#{rgtr}
)
</insert>
<!-- 게시물에 첨부된 파일 정보 삭제 -->
<delete id="deleteNoticeFileByNoticeId" parameterType="String">
DELETE FROM
tb_bbs_notice_sample_file
WHERE
NOTICE_ID = #{noticeId}
</delete>
<!-- 파일 정보 삭제 -->
<delete id="deleteNoticeFile" parameterType="String">
DELETE FROM
tb_bbs_notice_sample_file
WHERE
FILE_ID = #{fileId}
</delete>
</mapper>
Loading…
Cancel
Save