This commit is contained in:
myname 2023-05-31 16:39:32 +09:00
commit 86b15ca473
12 changed files with 107 additions and 71 deletions

View File

@ -5,7 +5,6 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.itn.mjonApi.cmn.idgen.service.IdgenService; import com.itn.mjonApi.cmn.idgen.service.IdgenService;
import com.itn.mjonApi.cmn.msg.RestResponse; import com.itn.mjonApi.cmn.msg.RestResponse;
import com.itn.mjonApi.mjon.api.send.mapper.domain.MsgRequestVO;
import com.itn.mjonApi.mjon.log.service.mapper.LettnAccessLogMapper; import com.itn.mjonApi.mjon.log.service.mapper.LettnAccessLogMapper;
import com.itn.mjonApi.mjon.log.service.mapper.domain.LettnAccessLogVO; import com.itn.mjonApi.mjon.log.service.mapper.domain.LettnAccessLogVO;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -20,13 +19,14 @@ import org.springframework.web.context.request.ServletRequestAttributes;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Field;
/** /**
* packageName : com.itn.mjonApi.cmn.aop * packageName : com.itn.mjonApi.cmn.aop
* fileName : SendAspect * fileName : LogAspect
* author : hylee * author : hylee
* date : 2023-05-24 * date : 2023-05-24
* description : send package 관련 AOP * description : lettngnrlmber_access_log 기록 남기는 AOP
* =========================================================== * ===========================================================
* DATE AUTHOR NOTE * DATE AUTHOR NOTE
* ----------------------------------------------------------- * -----------------------------------------------------------
@ -35,7 +35,7 @@ import javax.servlet.http.HttpServletRequest;
@Slf4j @Slf4j
@Aspect @Aspect
@Component @Component
public class SendAspect { public class LogAspect {
// @Autowired // @Autowired
// private LettnAccessLogService lettnAccessLogService; // private LettnAccessLogService lettnAccessLogService;
@ -45,31 +45,41 @@ public class SendAspect {
private IdgenService idgenApiAccessLogId; private IdgenService idgenApiAccessLogId;
/** /**
* @description SendServiceImpl.sendMsgData 메소드 실행 로그 처리 * @description com.itn.mjonApi.mjon.api 패키지 하위에 모든 *Impl 클래스의 모든 메소드 실행
* - 대량문자와 개별문자의 파마리터 VO가 다르므로 메소드로 분기 처리하기위함
* @param joinPoint * @param joinPoint
* @important 메소드의 매개변수 VO의 필드명이 다르면 수정 필요
* - mberId
* - accessKey
*/ */
@Before(value = "execution(* com.itn.mjonApi.mjon.api.send.service.impl.SendServiceImpl.sendMsgData(..))" ) @Before(value = "execution(* com.itn.mjonApi.mjon.api.*..*Impl.*(..))" )
public void before(JoinPoint joinPoint){ // @Before(value = "execution(* com.itn.mjonApi.mjon.api.send.service.impl.SendServiceImpl.*(..))" )
log.info(" :: SendAspect before :: "); public void before(JoinPoint joinPoint) throws IllegalAccessException {
log.info(" :: AOP before :: ");
// HttpServletRequest 객체를 가져옴
HttpServletRequest request = this.getHttpServletRequest(); HttpServletRequest request = this.getHttpServletRequest();
//메서드에 들어가는 매개변수 배열을 읽어옴 // VO 객체를 가져옴
Object[] args = joinPoint.getArgs(); Object objectVO = joinPoint.getArgs()[0];
MsgRequestVO msgRequestVO = (MsgRequestVO) args[0];
// VO 객체의 필드값을 가져옴
// 각각 메소드들의 매개변수VO가 다름으로
// 필드명으로 구분하여 값을 가져옴
String mberId = "";
String accessKey = "";
for(Field field : objectVO.getClass().getDeclaredFields()){
field.setAccessible(true);
if("mberId".equals(field.getName())){ mberId=field.get(objectVO).toString(); }
if("accessKey".equals(field.getName())){ accessKey=field.get(objectVO).toString(); }
}
String nextStringId = idgenApiAccessLogId.getNextStringId(); String nextStringId = idgenApiAccessLogId.getNextStringId();
LettnAccessLogVO lettnAccessLogVO = new LettnAccessLogVO() LettnAccessLogVO lettnAccessLogVO = new LettnAccessLogVO()
.builder() .builder()
.logId(nextStringId) .logId(nextStringId)
.accessType("K") // key : K , token : T // TODO accessType 구분추가 .accessType("K") // key : K , token : T // TODO accessType 구분추가
.accessKey(msgRequestVO.getAccessKey()) .accessKey(accessKey)
.reqUserId(msgRequestVO.getMberId()) .reqUserId(mberId)
.reqCn("문자 전송") .reqCn(joinPoint.toString())
.reqInfoRef(request.getHeader("Referer")) .reqInfoRef(request.getHeader("Referer"))
.reqUrl(request.getRequestURI()) .reqUrl(request.getRequestURI())
.build(); .build();
@ -80,6 +90,7 @@ public class SendAspect {
// setAttribute logId값 저장 -> @AfterReturning에서 사용하기 위함 // setAttribute logId값 저장 -> @AfterReturning에서 사용하기 위함
request.setAttribute("logId", nextStringId); request.setAttribute("logId", nextStringId);
} }
@ -90,7 +101,7 @@ public class SendAspect {
* @param returnValue * @param returnValue
* @throws JsonProcessingException * @throws JsonProcessingException
*/ */
@AfterReturning(pointcut = "execution(* com.itn.mjonApi.mjon.api.send.service.impl.SendServiceImpl.*(..))", returning = "returnValue") @AfterReturning(pointcut = "execution(* com.itn.mjonApi.mjon.api.*..*Impl.*(..))", returning = "returnValue")
public void afterReturning(JoinPoint joinPoint, RestResponse returnValue) throws JsonProcessingException { public void afterReturning(JoinPoint joinPoint, RestResponse returnValue) throws JsonProcessingException {
log.info(" :: AfterReturning :: "); log.info(" :: AfterReturning :: ");
@ -102,8 +113,6 @@ public class SendAspect {
RestResponse restResponse = (RestResponse) returnValue; RestResponse restResponse = (RestResponse) returnValue;
// lettngnrlmber_access_log 응답값 Udpate // lettngnrlmber_access_log 응답값 Udpate
LettnAccessLogVO lettnAccessLogVO = new LettnAccessLogVO() LettnAccessLogVO lettnAccessLogVO = new LettnAccessLogVO()
.builder() .builder()

View File

@ -1,12 +1,16 @@
package com.itn.mjonApi.cmn.msg; package com.itn.mjonApi.cmn.msg;
import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter; import lombok.Setter;
import java.time.LocalDateTime; import java.time.LocalDateTime;
@Setter @Setter
@Getter @Getter
@NoArgsConstructor
@AllArgsConstructor
public class RestResponse{ public class RestResponse{
private String resultCode = "0"; private String resultCode = "0";

View File

@ -62,6 +62,11 @@ public enum StatMsg {
private static final List<StatMsg> VALUES = Collections.unmodifiableList(Arrays.asList(values())); private static final List<StatMsg> VALUES = Collections.unmodifiableList(Arrays.asList(values()));
private static final int SIZE = VALUES.size(); private static final int SIZE = VALUES.size();
private static final Random RANDOM = new Random(); private static final Random RANDOM = new Random();
/**
* @description : 랜덤한 에러코드를 반환한다.
* @return errorCode
*/
public static String randomErrorStatCode() { public static String randomErrorStatCode() {
String errorCode = ""; String errorCode = "";
while(true){ while(true){

View File

@ -19,14 +19,14 @@ import org.apache.ibatis.annotations.Mapper;
public interface PriceMapper { public interface PriceMapper {
/** /**
* @methodName : selectUserMoney * @methodName : selectMberMoney
* @author : JunHo Lee * @author : JunHo Lee
* @date : 2023.05.22 * @date : 2023.05.22
* @description : * @description :
* @param priceVO * @param priceVO
* @return * @return
*/ */
double selectUserMoney(String mberId); double selectMberMoney(String mberId);
Map<String, String>selectMberPriceInfo(String mberId); Map<String, String>selectMberPriceInfo(String mberId);

View File

@ -28,7 +28,7 @@ public class PriceResponse {
private double longPrice; // 장문 이용단가 private double longPrice; // 장문 이용단가
private double picturePrice; // 그림 이용단가 private double picturePrice; // 그림 이용단가
private double userMoney; // 잔액 private double mberMoney; // 잔액
private int shortSendPsbltEa; // 단문 발송 가능건 private int shortSendPsbltEa; // 단문 발송 가능건
private int longSendPsbltEa; // 장문 발송 가능건 private int longSendPsbltEa; // 장문 발송 가능건

View File

@ -23,7 +23,7 @@ public class PriceVO implements Serializable{
private double longPrice; // 장문 이용단가 private double longPrice; // 장문 이용단가
private double picturePrice; // 그림 이용단가 private double picturePrice; // 그림 이용단가
private double userMoney; // 잔액 private double mberMoney; // 잔액
private int shortSendPsbltEa; // 단문 발송 가능건 private int shortSendPsbltEa; // 단문 발송 가능건
private int longSendPsbltEa; // 장문 발송 가능건 private int longSendPsbltEa; // 장문 발송 가능건

View File

@ -1,6 +1,6 @@
package com.itn.mjonApi.mjon.api.inqry.service; package com.itn.mjonApi.mjon.api.inqry.service;
import com.itn.mjonApi.mjon.api.inqry.mapper.domain.PriceResponse; import com.itn.mjonApi.cmn.msg.RestResponse;
/** /**
* @packageName : com.itn.mjonApi.mjon.api.inqry.service * @packageName : com.itn.mjonApi.mjon.api.inqry.service
@ -15,6 +15,6 @@ import com.itn.mjonApi.mjon.api.inqry.mapper.domain.PriceResponse;
*/ */
public interface PriceService { public interface PriceService {
public PriceResponse selectUserPrice(String mberId) throws Exception; public RestResponse selectUserPrice(String mberId) throws Exception;
} }

View File

@ -1,18 +1,21 @@
package com.itn.mjonApi.mjon.api.inqry.service.impl; package com.itn.mjonApi.mjon.api.inqry.service.impl;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import com.itn.mjonApi.cmn.msg.RestResponse;
import com.itn.mjonApi.cmn.msg.StatMsg; import com.itn.mjonApi.cmn.msg.StatMsg;
import com.itn.mjonApi.mjon.api.inqry.mapper.PriceMapper; import com.itn.mjonApi.mjon.api.inqry.mapper.PriceMapper;
import com.itn.mjonApi.mjon.api.inqry.mapper.domain.PriceResponse; import com.itn.mjonApi.mjon.api.inqry.mapper.domain.PriceResponse;
import com.itn.mjonApi.mjon.api.inqry.mapper.domain.PriceVO; import com.itn.mjonApi.mjon.api.inqry.mapper.domain.PriceVO;
import com.itn.mjonApi.mjon.api.inqry.service.PriceService; import com.itn.mjonApi.mjon.api.inqry.service.PriceService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.math.BigDecimal; import lombok.extern.slf4j.Slf4j;
import java.time.LocalDateTime;
import java.util.Map;
/** /**
* @packageName : com.itn.mjonApi.mjon.api.inqry.service.impl * @packageName : com.itn.mjonApi.mjon.api.inqry.service.impl
@ -37,15 +40,15 @@ public class PriceServiceImpl implements PriceService {
private String STAT_CODE; private String STAT_CODE;
@Override @Override
public PriceResponse selectUserPrice(String mberId) throws Exception { public RestResponse selectUserPrice(String mberId) throws Exception {
PriceResponse priceResponse = new PriceResponse(); PriceResponse priceResponse = new PriceResponse();
try { try {
//사용자 잔액 //사용자 잔액
double userMoney = priceMapper.selectUserMoney(mberId); double mberMoney = priceMapper.selectMberMoney(mberId);
// 이용단가, 발송가능 건수 // 이용단가, 발송가능 건수
PriceVO priceVO = price_refine(mberId, userMoney, priceMapper); PriceVO priceVO = price_refine(mberId, mberMoney, priceMapper);
//response set //response set
priceResponse = PriceResponse.builder() priceResponse = PriceResponse.builder()
@ -54,7 +57,7 @@ public class PriceServiceImpl implements PriceService {
.message(StatMsg.valueOf(STAT_CODE).getMsg()) .message(StatMsg.valueOf(STAT_CODE).getMsg())
.localDateTime(LocalDateTime.now()) .localDateTime(LocalDateTime.now())
//1. 잔액 //1. 잔액
.userMoney(userMoney) .mberMoney(mberMoney)
//2. 이용단가 //2. 이용단가
.shortPrice(priceVO.getShortPrice()) .shortPrice(priceVO.getShortPrice())
.longPrice(priceVO.getLongPrice()) .longPrice(priceVO.getLongPrice())
@ -82,11 +85,12 @@ public class PriceServiceImpl implements PriceService {
.localDateTime(LocalDateTime.now()) .localDateTime(LocalDateTime.now())
.build(); .build();
} }
return priceResponse;
return new RestResponse(priceResponse);
} }
private PriceVO price_refine(String mberId, double userMoney, PriceMapper priceMapper) { private PriceVO price_refine(String mberId, double mberMoney, PriceMapper priceMapper) {
//시스템 단가 변수 //시스템 단가 변수
double sys_shortPrice = 0.0f; double sys_shortPrice = 0.0f;
@ -121,16 +125,16 @@ public class PriceServiceImpl implements PriceService {
int pictureSendPsbltEa = 0; int pictureSendPsbltEa = 0;
//2-1. 소수점 연산을 위한 BigDecimal Casting //2-1. 소수점 연산을 위한 BigDecimal Casting
BigDecimal userMoney_big = new BigDecimal(String.valueOf(userMoney)); BigDecimal mberMoney_big = new BigDecimal(String.valueOf(mberMoney));
BigDecimal shortPrice_big = new BigDecimal(String.valueOf(priceMap.get("sysShortPrice"))); BigDecimal shortPrice_big = new BigDecimal(String.valueOf(priceMap.get("sysShortPrice")));
BigDecimal longPrice_big = new BigDecimal(String.valueOf(priceMap.get("sysLongPrice"))); BigDecimal longPrice_big = new BigDecimal(String.valueOf(priceMap.get("sysLongPrice")));
BigDecimal picturePrice_big = new BigDecimal(String.valueOf(priceMap.get("sysPicturePrice"))); BigDecimal picturePrice_big = new BigDecimal(String.valueOf(priceMap.get("sysPicturePrice")));
//2-2. userMoney가 0일경우 제외 //2-2. mberMoney가 0일경우 제외
if(userMoney_big.compareTo(BigDecimal.ZERO) != 0) { if(mberMoney_big.compareTo(BigDecimal.ZERO) != 0) {
shortSendPsbltEa = userMoney_big.divide(shortPrice_big, BigDecimal.ROUND_DOWN).intValue(); shortSendPsbltEa = mberMoney_big.divide(shortPrice_big, BigDecimal.ROUND_DOWN).intValue();
longSendPsbltEa = userMoney_big.divide(longPrice_big, BigDecimal.ROUND_DOWN).intValue(); longSendPsbltEa = mberMoney_big.divide(longPrice_big, BigDecimal.ROUND_DOWN).intValue();
pictureSendPsbltEa = userMoney_big.divide(picturePrice_big, BigDecimal.ROUND_DOWN).intValue(); pictureSendPsbltEa = mberMoney_big.divide(picturePrice_big, BigDecimal.ROUND_DOWN).intValue();
} }
//result set //result set

View File

@ -5,7 +5,7 @@ import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import com.itn.mjonApi.mjon.api.inqry.mapper.domain.PriceResponse; import com.itn.mjonApi.cmn.msg.RestResponse;
import com.itn.mjonApi.mjon.api.inqry.mapper.domain.PriceVO; import com.itn.mjonApi.mjon.api.inqry.mapper.domain.PriceVO;
import com.itn.mjonApi.mjon.api.inqry.service.PriceService; import com.itn.mjonApi.mjon.api.inqry.service.PriceService;
@ -34,7 +34,7 @@ public class PriceRestController {
* @throws Exception * @throws Exception
*/ */
@PostMapping("/api/inqry/selectPrice") @PostMapping("/api/inqry/selectPrice")
public ResponseEntity<PriceResponse> selectPrice(PriceVO priceVO) throws Exception{ public ResponseEntity<RestResponse> selectPrice(PriceVO priceVO) throws Exception{
return ResponseEntity.ok(priceService.selectUserPrice(priceVO.getMberId())); return ResponseEntity.ok(priceService.selectUserPrice(priceVO.getMberId()));
} }

View File

@ -54,6 +54,7 @@ public class SendServiceImpl implements SendService {
//step1.발신자 전화번호 사용 가능 여부 체크(해당 사용자의 등록된 번호만 발송 가능) //step1.발신자 전화번호 사용 가능 여부 체크(해당 사용자의 등록된 번호만 발송 가능)
// 1010 // 1010
msgRequestVO.setCallFrom(MunjaUtil.removeCharactersWithRegex(msgRequestVO.getCallFrom()));
if(!sendMapper.findByCallFrom(msgRequestVO)){ if(!sendMapper.findByCallFrom(msgRequestVO)){
return new RestResponse("STAT_1010"); return new RestResponse("STAT_1010");
} }
@ -61,7 +62,7 @@ public class SendServiceImpl implements SendService {
// step2.수신자 전화번호 정상 여부 체크(정상 번호에 대해서만 발송 가능) // step2.수신자 전화번호 정상 여부 체크(정상 번호에 대해서만 발송 가능)
// 1020 // 1020
// 폰번호 확인 - -> 유효성 정규식 // 폰번호 확인 - -> 유효성 정규식
if(StringUtils.isNotEmpty(this.getCallToListChk(msgRequestVO))){ if(this.getCallToListChk(msgRequestVO)){
return new RestResponse("STAT_1020"); return new RestResponse("STAT_1020");
} }
@ -117,17 +118,20 @@ public class SendServiceImpl implements SendService {
private RestResponse _getTestReturnData(String testYn) private RestResponse _getTestReturnData(String testYn)
{ {
// YF => 실패 테스트 데이터
if("YF".equals(testYn)) if("YF".equals(testYn))
{ {
// 실패 코드 랜덤으로 리턴
return new RestResponse(StatMsg.randomErrorStatCode()); return new RestResponse(StatMsg.randomErrorStatCode());
}else{ }else{
return new RestResponse(SendSuccessRestResponse.builder() return new RestResponse(
.msgGroupId("MSGGID_0000000000000") // 전송 메세지 그룹 ID SendSuccessRestResponse.builder()
.successCnt("5") // 성공 건수 .msgGroupId("MSGGID_0000000000000") // 전송 메세지 그룹 ID
.blockCnt("2") // 수신거부 건수 .successCnt("5") // 성공 건수
.msgType("LMS") .blockCnt("2") // 수신거부 건수
.failCnt("0") .msgType("LMS")
.build() .failCnt("0")
.build()
); );
} }
} }
@ -136,17 +140,12 @@ public class SendServiceImpl implements SendService {
public RestResponse sendMsgsData(MsgsRequestVO msgsRequestVO) throws Exception { public RestResponse sendMsgsData(MsgsRequestVO msgsRequestVO) throws Exception {
if(StringUtils.isNotEmpty(msgsRequestVO.getTest_yn())){ if(StringUtils.isNotEmpty(msgsRequestVO.getTest_yn())){
// YF => 실패 테스트 데이터
return this._getTestReturnData(msgsRequestVO.getTest_yn()); return this._getTestReturnData(msgsRequestVO.getTest_yn());
} }
// msgsVO -> msgVO List로 변환 // msgsVO -> msgVO List로 변환
List<MsgRequestVO> msgRequestVOList = this.getDataCleaning(msgsRequestVO); List<MsgRequestVO> msgRequestVOList = this.getDataCleaning(msgsRequestVO);
msgRequestVOList.forEach(msgRequestVO -> {
log.info("msgRequestVO getCallToList() :: [{}]", msgRequestVO.getCallToList());
log.info("msgRequestVO getSmsTxt() :: [{}]", msgRequestVO.getSmsTxt());
log.info("======================");
});
//step1.발신자 전화번호 사용 가능 여부 체크(해당 사용자의 등록된 번호만 발송 가능) //step1.발신자 전화번호 사용 가능 여부 체크(해당 사용자의 등록된 번호만 발송 가능)
// 1010 // 1010
if(!sendMapper.findByCallFrom(msgRequestVOList.get(0))){ if(!sendMapper.findByCallFrom(msgRequestVOList.get(0))){
@ -154,12 +153,13 @@ public class SendServiceImpl implements SendService {
} }
//step2.수신자 전화번호 정상 여부 체크(정상 번호에 대해서만 발송 가능) // step2.수신자 전화번호 정상 여부 체크(정상 번호에 대해서만 발송 가능)
// 1020 // 1020
// 폰번호 확인 - -> 유효성 정규식 // 폰번호 확인 - -> 유효성 정규식
for(MsgRequestVO msgRequestVO : msgRequestVOList){ for(MsgRequestVO msgRequestVO : msgRequestVOList){
if(StringUtils.isNotEmpty(this.getCallToListChk(msgRequestVO))){ if(this.getCallToListChk(msgRequestVO)){
return callToErrorReturnData(msgRequestVO); // if(StringUtils.isNotEmpty(this.getCallToListChk(msgRequestVO))){
return this.callToErrorReturnData(msgRequestVO);
} }
} }
@ -443,18 +443,29 @@ public class SendServiceImpl implements SendService {
/** /**
* 수신자 목록 번호 검증 * 수신자 목록 번호 검증
* message가 없으면 정상
* @param msgRequestVO * @param msgRequestVO
* @return * @return String
*/ */
private static String getCallToListChk(MsgRequestVO msgRequestVO) { private static Boolean getCallToListChk(MsgRequestVO msgRequestVO) {
String message = ""; Boolean returnData = false;
for(String callTo : msgRequestVO.getCallToList()){ for(String callTo : msgRequestVO.getCallToList()){
/*
if(!MunjaUtil.checkPhoneNumberEmpty(callTo)){ if(!MunjaUtil.checkPhoneNumberEmpty(callTo)){
message = "수신 목록에 핸드폰 번호가 없는 항목이 있습니다."; break;}; message = "수신 목록에 핸드폰 번호가 없는 항목이 있습니다."; break;};
if(!MunjaUtil.validatePNumWithRegex(callTo)){ if(!MunjaUtil.validatePNumWithRegex(callTo)){
message = "휴대폰 번호가 올바르지 않습니다. : " + callTo; break;}; message = "휴대폰 번호가 올바르지 않습니다. : " + callTo; break;};
*/
if(!MunjaUtil.validatePNumWithRegex(callTo) // 비여있는지 체크
|| !MunjaUtil.validatePNumWithRegex(callTo) // 정규식으로 번호 체크
)
{
returnData = true;
break;
};
} }
return message; return returnData;
} }

View File

@ -39,6 +39,9 @@ public class MunjaUtil {
public static String replaceCommaToStrSymbol(String name) { public static String replaceCommaToStrSymbol(String name) {
return name.replaceAll(",", "§"); return name.replaceAll(",", "§");
} }
public static String removeCharactersWithRegex(String str) {
return str.replaceAll("[^0-9]", "");
}

View File

@ -5,11 +5,11 @@
<mapper namespace="com.itn.mjonApi.mjon.api.inqry.mapper.PriceMapper"> <mapper namespace="com.itn.mjonApi.mjon.api.inqry.mapper.PriceMapper">
<select id="selectUserMoney" <select id="selectMberMoney"
resultType="double" resultType="double"
> >
SELECT a.USER_MONEY AS userMoney SELECT a.USER_MONEY AS mberMoney
FROM lettngnrlmber a FROM lettngnrlmber a
WHERE a.MBER_ID = #{mberId} WHERE a.MBER_ID = #{mberId}