쿠폰 테이블, 트리거
/*
[포인트 테이블 생성시 고려할 점]
기획자 => COUPON => 할인율 or 포인트 or 적립금 => 컬럼 필요
1. 할인율, 포인트 기능
2. 쿠폰을 사용할 수 있는 날짜 제한
3. 해당 쿠폰을 사용할 수 있는 상품 설정
*/
create table COUPON(
MIDX NUMBER(3) NOT NULL,
COUPON_NM NVARCHAR2(50) NOT NULL,
COUPON_POINT NUMBER(6) NOT NULL,
COUPON_DATE TIMESTAMP DEFAULT SYSDATE
)
/*
트리거는 테이블 생성후 생성
IDE에서 트리거 생성시 오류 발생함
SQL developer에서 트리거 만들어야함
*/
-- 아래 테이블 SQL developer에서 실행 후 커밋해서 실제테이블에 적용하기
CREATE OR REPLACE TRIGGER CP
AFTER INSERT ON MEMBERSHIP
FOR EACH ROW
BEGIN
INSERT INTO COUPON (MIDX,COUPON_NM,COUPON_POINT,COUPON_DATE)
VALUES (:NEW.MIDX,'신규회원가입 쿠폰',1000,SYSDATE);
END;
-- 트리거 정지
ALTER TRIGGER CP DISABLE;
-- 트리거 재실행
ALTER TRIGGER CP ENABLE;
-- drop trigger cp; -- 트리거 삭제
-- 트리거 조회
SELECT TRIGGER_NAME FROM USER_TRIGGERS WHERE TABLE_NAME ='MEMBERSHIP';
-- 쿠폰 조회
SELECT * FROM COUPON;
/*
Oracle Table JOIN시 주의점 on사용후 where 적용하기
1. JOIN ON WHERE
2. JOIN ON
3. JOIN , WHERE
*/
-- 조인해서 검색하기 ON
SELECT A.MIDX, A.MCODE, A.MID, A.MNAME, A.MEMAIL, B.COUPON_NM
FROM MEMBERSHIP A JOIN COUPON B ON A.MIDX = B.MIDX
WHERE A.MIDX='39';
-- 조인해서 검색하기 WHERE
-- 조인시 where을 바로 사용해야 할 경우 테이블과 테이블 사이에 콤마, 를 사용해 핸들링
SELECT A.MIDX, A.MCODE, A.MID, A.MNAME, A.MEMAIL, B.COUPON_NM
FROM MEMBERSHIP A, COUPON B WHERE A.MIDX = B.MIDX;
-- 뷰 생성 위 쿼리를 이용
CREATE VIEW USER_INFO AS SELECT A.MIDX, A.MCODE, A.MID, A.MNAME, A.MEMAIL, B.COUPON_NM
FROM MEMBERSHIP A, COUPON B WHERE A.MIDX = B.MIDX;
SELECT * FROM USER_INFO; -- 검색
DROP VIEW USER_INFO; -- 삭제
kakao2.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>로그인및 외부 API 로그인 방식(Kakao)</title>
</head>
<body>
<form id="frm" method="post" action="./ajax/web_loginok.do">
<!-- code = 1일반로그인 2카카오로그인 -->
<input type="hidden" name="code" value="1">
<input type="hidden" name="kakao_id" value="">
<input type="hidden" name="kakao_nicknm" value="">
<!-- autocomplete 자동완성 해제 : 보안굿 -->
아이디 : <input type="text" name="mid" autocomplete="off"><br>
패스워드 : <input type="password" name="mpass"><br>
<input type="submit" value="로그인"><br>
<input type="checkbox" id="save_id">아이디 저장<br>
<!--
자동로그인 기능은 실제로그인이 한번 돼야 활성화됨
자동로그인은 Back-end가 세션스토리지가 아니라 로컬스토리지로 셋아이템으로 브라우저에 저장해야함
아이디 저장은 Front-end가 로컬스토리지에 저장함
-->
</form>
<br>
<br>
<img src="./ajax/kakao_login.png" onclick="kakao_login()">
<p id="token-result"></p>
</body>
<script src="https://t1.kakaocdn.net/kakao_js_sdk/v1/kakao.js"></script>
<script>
Kakao.init('키');
function kakao_login() {
// Kakao.Auth.login : 카카오 회원가입 및 로그인 페이지를 출력하는 함수
Kakao.Auth.login({
//성공시 출력되는 형태
success : function(response) { //response : 결과화면 (사실 여기서 안넣어도됨)
Kakao.API.request({ //사용자 가입정보를 요청
url : '/v2/user/me', // 사용자 정보 가져오기
success : function(response) { //API서버에서 가입정보를 가져옴
console.log(response);
let id = response["id"]; //고유값
let nickname = response["kakao_account"]["profile"]["nickname"]; //카카오 닉네임
frm.code.value = "2";
frm.kakao_id.value = id;
frm.kakao_nicknm.value = nickname;
frm.submit();
},
fail : function(error) {
console.log(error);
console.log("카카오 API 접속 오류");
}
});
},
//API 키가 맞지 않을 경우 출력되는 함수
fail : function(error) {
console.log(error);
console.log("카카오 key 접속 오류 및 환경설정 오류");
}
});
}
</script>
<script>
</script>
<script>
//해당 페이지로 접속시 작동되는 함수
window.onload = function(){
let userid = localStorage.getItem("userid");
if(userid != null){ //아이디 저장기능 활성화
frm.mid.value = userid;
document.querySelector("#save_id").checked = true; //아이디 저장 체크박스 체크
}
}
//아이디 저장
document.querySelector("#save_id").addEventListener("click", function(e) {
if(frm.mid.value == ""){
alert("아이디를 입력하셔야 해당 기능을 사용할 수 있습니다.");
this.checked = false; //체크안되게 만들기
}else{
if(this.checked == true){
localStorage.setItem("userid",frm.mid.value);
}else{
localStorage.clear();
}
}
});
// ECMA => submit 사용 시 return, return false가 없습니다.
document.querySelector("#frm").addEventListener("submit", function(e) {
e.preventDefault(); // 강제정지
if (frm.mid.value == "") {
alert("아이디를 입력하세요");
} else if (frm.mpass.value == "") {
alert("패스워드를 입력하세요");
} else {
frm.submit();
}
});
</script>
</html>
mapper.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">
<mapper namespace="mytld.mycompany.myapp.membership_mapper">
<!--
map 이용하여 하나의 쿼리문으로 조건에 맞는 sql이 작동 되도록 설정
-->
<select id="id_info" resultType="membership_DTO" parameterType="Map">
select mid,mpass,mhp,memail from membership
<choose>
<when test="part == 'login'"> <!-- 로그인 -->
<where> <!-- where 태그는 where절을 입력시키는 태그 -->
mid= #{mid} and mpass= #{mpass}
</where>
</when>
<when test="part == 'myinfo'"> <!-- 자신의 정보확인 및 수정 (kakao) -->
where mid= #{mid}
</when>
<otherwise> <!-- 회원전체 리스트 -->
order by midx desc
</otherwise>
</choose>
</select>
<select id="id_row" resultType="String">
select count(*) as ctl from membership where mid=#{mid}
</select>
<insert id="join_insert">
insert into membership (MIDX,MCODE,MID,MNAME,MNICK,MPASS,MEMAIL,MHP,MJOIN,MDATE)
values (MNO.NEXTVAL,#{MCODE},#{MID},#{MNAME},#{MNICK},#{MPASS},#{MEMAIL},#{MHP},#{MJOIN},SYSDATE)
</insert>
<update id="id_update" parameterType="Map">
update membership set
<choose>
<when test="MPASS != null"> <!-- MPASS의 값이 있을 경우 -->
MPASS = #{MPASS}, MHP = #{MHP}, MEMAIL = #{MEMAIL}
</when>
<otherwise> <!-- MPASS의 값이 없을 경우 -->
MHP = #{MHP}, MEMAIL = #{MEMAIL}
</otherwise>
</choose>
where MID=#{MID}
</update>
</mapper>
membership_mapper.java
package mytld.mycompany.myapp;
import java.util.List;
import java.util.Map;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface membership_mapper {
public String id_row(String mid);
public int join_insert(membership_DTO dto);
public List<membership_DTO> id_info(String mid, String mpass);
public int id_update(Map<String,String> map); //개인정보 수정
}
membership_DAO.java
package mytld.mycompany.myapp;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import org.mybatis.spring.SqlSessionTemplate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Repository;
@Repository("membership_DAO")
public class membership_DAO implements membership_mapper {
@Resource(name="sqltemp")
public SqlSessionTemplate st;
Map<String, String> mp = null;
private static final Logger logger = LoggerFactory.getLogger(membership_DAO.class);
@Override
public List<membership_DTO> id_info(String mid, String mpass) {
//Map 생성하는 이유 : mapper.xml에서 choose을 사용하여 각 when(조건) 별로 query를 다르게 실행 시키기 위함
this.mp = new HashMap<String, String>();
if(mpass != "") {
this.mp.put("part", "login");
this.mp.put("mid", mid);
this.mp.put("mpass", mpass);
}
else {
this.mp.put("part", "myinfo");
this.mp.put("mid", mid);
}
//해당 조건에 mapper값을 return받음
List<membership_DTO> all = this.st.selectList("id_info",this.mp);
return all;
}
@Override
public String id_row(String mid) {
String result = null;
try {
//id는 대문자 소문자를 구분한다.
result = st.selectOne("id_row",mid);
}catch (Exception e) {
System.out.println(e);
}
return result;
}
@Override
public int join_insert(membership_DTO dto) {
int result = 0;
result = st.insert("join_insert",dto);
return result;
}
@Override
public int id_update(Map<String, String> map) {
int result = this.st.update("id_update",map);
return result;
}
}
controller.java
package mytld.mycompany.myapp;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import javax.annotation.Resource;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.apache.commons.dbcp.BasicDataSource;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.SessionAttribute;
@Controller
public class HomeController {
private static final Logger logger = LoggerFactory.getLogger(HomeController.class);
@Autowired
BasicDataSource dbinfo;
@Resource(name = "membership_DAO")
membership_DAO dao;
@Resource(name = "m_md5")
m_md5 md5 = null;
HttpSession session = null;
PrintWriter pw = null;
String msg = null;
// kakao2.jsp에서 넘어옴
// @Post도 받고 @Get도 받아야됨
// @Post => 일반로그인, kakao api, @Get => kakao Script
// 일반로그인 + Kakao Script Login => @RequestMapping
// 일반로그인 + Kakao API => @PostMapping
/*
* ServletRequest, ServletResponse => session 사용 불가능 HttpServletRequest,
* HttpServletResponse => session 사용가능
*/
@RequestMapping("/ajax/web_loginok.do")
public String web_loginok( // DTO로 받아도됨
@RequestParam(name = "code") String code, @RequestParam(name = "mid", required = false) String mid,
@RequestParam(name = "mpass", required = false) String mpass,
@RequestParam(name = "kakao_id", required = false) String kakao_id,
@RequestParam(name = "kakao_nicknm", required = false) String kakao_nicknm, Model m,
HttpServletRequest req) {
this.session = req.getSession();
if (code.equals("1")) { // 일반 로그인 처리
String pw = this.md5.md5_pass(mpass); // 사용자가 입력한 값을 암호화하여 회신
List<membership_DTO> all = this.dao.id_info(mid, pw);
System.out.println(all.size());
if (all.size() > 0) {
// 해당 로그인시 아이디를 session으로 등록함
this.session.setAttribute("mid", all.get(0).getMID());
System.out.println("세션 MID: " + this.session.getAttribute("mid"));
// this.msg = "alert('로그인하였습니다');location.href='./myinfo.do';";
this.msg = "setTimeout(function() { alert('로그인하였습니다'); location.href='./myinfo.do'; }, 300);";
this.logger.info("로그인확인");
} else {
this.msg = "alert('로그인 실패하였습니다');" + "history.go(-1);";
this.logger.info("로그인미확인");
}
m.addAttribute("msg", msg);
} else if (code.equals("2")) { // 카카오 로그인 처리
List<membership_DTO> all = this.dao.id_info(kakao_id, "");
if (all.size() > 0) {
//해당 로그인시 아이디를 session으로 등록함
this.session.setAttribute("mid", all.get(0).getMID());
msg = "alert('로그인 하셨습니다.'); location.href='./myinfo.do';";
} else {
// sessionStorage를 이용하여 간편회원가입을 등록하려함
// 단 닉네임일 경우 특수문자를 사용할 수있으므로 생성시 ''로 변수값을 적용하여 처리
this.msg = "alert('카카오 사용자로 로그인시 간편회원가입이 필요합니다.');"
+ "sessionStorage.setItem('mid','"+ kakao_id +"');"
+ "sessionStorage.setItem('mnick','"+ kakao_nicknm +"');"
+ "location.href='../join.jsp';";
}
m.addAttribute("msg", msg);
}
return "joinok";
}
// 아이디 체크
@PostMapping("/login_idck.do")
public String login_idck(@RequestParam(name = "id") String id, ServletResponse res) {
String result = null;
try {
// this.logger.info(id);
this.pw = res.getWriter();
// 아이디 대소문자 구별함
// toUpperCase : 대문자로
// toLowerCase : 소문자로
result = this.dao.id_row(id.toLowerCase());
// this.logger.info(result);
if (result == null || result.equals("0")) {
this.pw.write("ok");
} else {
this.pw.write("no");
}
} catch (Exception e) {
this.logger.info(e.toString());
} finally {
this.pw.close();
}
return null;
}
@PostMapping("/joinok.do")
public String joinok(@ModelAttribute membership_DTO dto, Model m) {
String pw = dto.getMPASS();
dto.setMPASS(this.md5.md5_pass(pw)); // 암호화 후 setter 사용
try {
int result = this.dao.join_insert(dto);
if (result > 0) {
m.addAttribute("msg", "alert('정상적으로 회원가입이 완료되었습니다');" + "location.href='./kakao2.jsp';");
} else {
m.addAttribute("msg", "alert('회원가입이 완료되지 않았습니다.');" + "history.go(-1);");
}
} catch (Exception e) {
this.logger.info(e.toString());
}
return null;
}
// 로그인 사용자 정보 출력하는 페이지
@GetMapping("/ajax/myinfo.do")
public String myinfo(@SessionAttribute("mid") String MID, Model m) {
//사용자 정보 가져옴
List<membership_DTO> mydata = this.dao.id_info(MID, "");
m.addAttribute("mydata",mydata);
//세션 ID 전송
//this.logger.info(MID);
m.addAttribute("MID", MID);
return "/myinfo";
}
// 로그아웃
@GetMapping("/ajax/logout.do")
public String logout(HttpServletRequest req, Model m) {
this.session = req.getSession();
this.session.invalidate();
this.msg = "alert('로그아웃 완료'); location.href='../kakao2.jsp';";
m.addAttribute("msg", this.msg);
return "joinok";
}
//배열키에 맞춰서 보내달라고 해야함
//API Patch로 개인정보 수정
@PatchMapping("/ajax/myinfo_modify.do/{key}")
public String myinfo_modify(ServletResponse res,
@PathVariable("key") String key,
@RequestBody String datainfo) {
try {
this.pw = res.getWriter();
if(key.equals("mykey")) {
JSONObject jo = new JSONObject(datainfo); //=> MAP
Map<String,String> userdata = new HashMap<String, String>();
//System.out.println(jo.keySet());
for(String k : jo.keySet()) {
if(!jo.get(k).equals("")) { //값이 비어있지 않을 경우 맵에 추가
if(k.equals("MPASS")) { //패스워드도 넘어온 경우
//md5로 암호화해서 맵에 추가
userdata.put(k, this.md5.md5_pass(jo.get(k).toString()));
}else {
userdata.put(k, jo.getString(k).toString());
}
}
}
this.logger.info(datainfo.toString());
int result = this.dao.id_update(userdata);
if(result > 0) {
this.pw.write("ok");
}else {
this.pw.write("no");
}
}
else {
this.pw.write("key error");
}
} catch (Exception e) {
System.out.println(e);
this.pw.write("error");
}finally {
this.pw.close();
}
return null;
}
}
myinfo.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="cr" uri="http://java.sun.com/jsp/jstl/core" %>
<%@page import="java.util.Date"%>
<%Date date = new Date();%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>회원정보</title>
</head>
<!-- a 태그에 javascript 함수를 호출 시 javascript: 단어를 입력 후 호출 -->
<body>
${sessionScope.mid}님 환영합니다. <a href="javascript:kakao_logout()">[로그아웃]</a>
<br><br><br>
<!-- SPA?형태로 제작 : 어디로 이동 안하고 ajax를 이용 -->
<input type="hidden" id="MID" value="${mydata.get(0).MID}"><br>
이름 : ${mydata.get(0).MID}<br>
<!-- 패스워드에 절대 값 때리면 안됨
굳이 때리고 싶으면 값 때려도 ******로 그냥 때리기
암호화해도 시간만 이쓰면 뚫음 개발자도구에서 password 대신 text로 때리면 다보임 -->
패스워드 : <input type="password" id="MPASS"><br>
<!--
주의 : disabled된 애는 핸들링이 안됨 말그대로 사용하지 않겠다는 뜻
Backend로도 안가고 Javascript에서도 핸들링이 불가능함!!!!
풀고싶다면 버튼을 이용해서 인풋의 속성 disabled를 false로 해주기
-->
연락처 : <input type="text" id="MHP" value="${mydata.get(0).MHP}" maxlength="11" disabled>
<input type="button" value="연락처수정" id="hpmodify"><br>
<!-- 실무에선 연락처에 나이스 인증 붙어있음 -->
이메일 : <input type="text" id="MEMAIL" value="${mydata.get(0).MEMAIL}" disabled>
<input type="button" value="이메일수정" id="mailmodify"><br>
<input type="button" value="개인정보수정" id="modify_myinfo">
</body>
<script src="../myinfo.js?v=<%=date%>"></script>
<script src="https://t1.kakaocdn.net/kakao_js_sdk/v1/kakao.js"></script>
<script>
Kakao.init('키'); //키발급된 번호
function kakao_logout(){
if(!Kakao.Auth.getAccessToken()){
location.href = './logout.do';
}
else{
Kakao.Auth.setAccessToken(undefined);
sessionStorage.clear();
localStorage.clear();
location.href = './logout.do';
}
}
</script>
</html>
myinfo.js
//disabled된 애는 핸들링이 안됨
//Backend로도 안가고 Javascript에서도 핸들링이 불가능함!!!!
document.querySelector("#hpmodify").addEventListener("click",function(){
//해당 연락처 수정 버튼을 클릭시 연락처 입력부분을 수정할 수 있도록 disable 정지시킴
if(confirm("연락처를 수정하시겠습니까?")){
document.querySelector("#MHP").disabled = false;
}
});
//이메일 수정시 적용되는 이벤트 핸들링 함수
document.querySelector("#mailmodify").addEventListener("click",function(){
if(confirm("이메일을 수정하시겠습니까?")){
document.querySelector("#MEMAIL").disabled = false;
}
});
//배열키 : MPASS, MEMAIL, MHP 이거로 보내주세영 - Back-end
//개인정보수정 버튼 클릭시 AJAX 발동
document.querySelector("#modify_myinfo").addEventListener("click",function(){
/*
//Map 배열로 키를 생성하여 전달하는 방식
//이거는 Spring에서 전송 안됨! Spring-boot에서는 가능
let udata = new Map();
udata.set("MID",document.querySelector("#MID").value);
//값이 null이면 에러나기때문에 핸들링 필요
if(document.querySelector("#MPASS").value != ""){
udata.set("MPASS",document.querySelector("#MPASS").value);
}
udata.set("MHP",document.querySelector("#MHP").value);
udata.set("MEMAIL",document.querySelector("#MEMAIL").value);
console.log(udata);
*/
fetch("./myinfo_modify.do/mykey",{
method : "PATCH",
//headers : {"content-type":"application/json"},
body : JSON.stringify({
"MID" : document.querySelector("#MID").value,
"MPASS" : document.querySelector("#MPASS").value,
"MHP" : document.querySelector("#MHP").value,
"MEMAIL" : document.querySelector("#MEMAIL").value
})
}).then(function(result){
return result.text();
}).then(function(data){
if(data=="ok"){
alert("정상적으로 변경 완료");
location.reload();
}else{
alert("정보 수정 실패");
}
console.log(data);
}).catch(function(error){
console.log(error);
});
});