|
Algorithm/자료구조와 알고리즘 2019. 6. 14. 23:18
자바는 List 인터페이스의 구현 클래스로 ArrayList와 LinkedList 클래스를 제공합니다.
응용 프로그램에 따라 LinkedList 클래스가 빠를때가 있고, ArrayList 클래스가 빠를때가 있다.
어떤 응용 프로그램에 어느 클래스가 더 좋을지 결정하는 한 가지 방법은 둘 다 시도해 보고 각각 얼마나 걸리는지 알아보는 것입니다.
이러한 접근법을 프로파일링이라고 합니다.
프로파일링의 문제점
1. 알고리즘을 비교하려면 사전에 그것을 모두 구현해봐야 합니다.
2. 결과는 사용하는 컴퓨터의 성능에 의존하기 때문에 한 알고리즘이 어떤 컴퓨터에서는 더 좋고, 나쁠 수가 있다.
3. 결과는 문제의 크기나 입력으로 사용하는 데이터에 의존하기도 합니다.
|
문제점의 해결 방법 : 알고리즘 분석
알고리즘 분석의 정의 : 그것을 구현하지 않고도 알고리즘을 비교할 수 있게 합니다.
알고리즘 분석을 하기위한 가정
1. 컴퓨터 하드웨어의 세부사항을 다루지 않기 위해 보통 알고리즘을 이루는 더하기와 곱하기, 숫자 비교 등의 기본 연산을 식별합니다. 그리고 각 알고리즘에 필요한 연산 수를 셉니다.
2. 입력 데이터의 세부사항을 다루지 않으려면 가장 좋은 선택은 기대하는 입력 데이터에 대한 평균 성능을 분석하는 것입니다. 이것이 가능하지 않을 때는 일반적인 대안으로 최악의 시나리오를 분석하기도 합니다.
3. 마지막으로, 한 알고리즘이 작은 문제에서는 최상의 성능을 보이지만 큰 문제에서는 다른 알고리즘이 더 좋을 수 있다는 가능성을 배제하면 안됩니다. 이 때는 보통 큰 문제에 초점을 맞춥니다. 작은 문제에서는 알고리즘의 차이가 크지 않지만, 큰 문제에서는 그 차이가 훨씬 거대해질수 있기 때문입니다.
|
이러한 종류의 분석은 간단한 알고리즘 분류에 적합합니다.
-간단한 알고리즘의 범주-
1. 상수 시간
실행 시간이 입력크기에 의존하지 않으면 알고리즘은 상수 시간을 따른다고 합니다. 예를 들어, n개의 배열에서 브래킷 연산 ([ ])을 사용하여 요소 중 하나에 접근할 때 이 연산은 배열의 크기와 관계없이 같은 수의 동작을 수행합니다. (즉, 어떤 문제를 풀때 필요한 풀이 시간이 내가 풀고있는 문제의 난이도와 상관없이 일정하다는 의미)
2. 선형
실행시간이 입력의 크기에 비례하면 알고리즘은 선형이라고 합니다. 예를 들어, 배열에 있는 요소를 더한다면 n개 요소에 접근하여 n-1번 더하기 연산을 해야 합니다. 연산 (요소 접근과 더하기)의 총 횟수는 2n-1이고 n에 비례합니다. (즉, 어떤 문제를 풀때 필요한 풀이 시간은 내가 풀고 있는 문제에 난이도에 따라 달라진다는 의미, 어려운 문제일수록 풀이 시간이 증가)
3. 아차
실행시간이 n2에 비례하면 알고리즘은 이차라고 합니다. 예를 들어, 리스트에 있는 어떤 요소가 두 번 이상 나타나는지를 알고 싶다고 가정합시다. 간단한 알고리즘은 각 요소를 다른 모든 요소와 비교하는 것입니다. n개의 요소가 있고 각각 n-1 개의 다른 요소와 비교하면 총 비교 횟수는 n2-n이 되어 n이 커지면서 n2에 비례하게 됩니다.
|
-선택 정렬-
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | public class SelectionSort { // i와 j의 위치에 있는 값을 바꿉니다. // 즉 요소를 읽고 쓰는 것은 상수 시간 연산입니다. // 요소의 크기와 첫 번째 위치를 알고 있다면 어떤 요소의 위치라도 // 알 수 있기 때문입니다. // swapElements 메소드에 있는 모든 연산이 상수 시간이므로 전체 // 메소드는 상수 시간이 됩니다.
public static void swapElements(int [] array, int i, int j) { int temp = array[i]; array[i] = array[j]; array[j] = temp;
// start로 부터 시작하는 최솟값의 위치를 찾고 (start 포함) // 배열의 마지막 위치로 갑니다. // 두 번째 메소드 indexLowest는 주어진 위치인 start에서 시작하여 // 배열에 있는 가장 작은 요소인 인덱스를 찾습니다. // 반복문을 돌 때마다 배열의 두 요소에 접근하고 한 번의 비교 연산을 합니다. // 이들은 모두 상수 시간 연산이므로 어느 것을 세든지 중요하지 않습니다.
public static int indexLowest(int[] array, int start) { int lowIndex = start; for (int i = start; i < array.length; i++) { if(array[i] < array[lowindex]) { lowIndex = i; } } return lowIndex; } //선택 정렬을 사용하여 요소를 정렬합니다. //selection메소드는 배열을 정렬합니다. // 0 에서 n-1까지 반복하므로 n번 실행됩니다. // 매번 indexLowest 메소드를 호출한 후 상수 시간 연산인 // swapElements 메소드를 실행합니다. //indexLowest 메소드가 처음 호출되면 n번 비교 연산을 합니다. // 두번째는 n-1번 비교연산을 합니다. // 이렇게 하였을 때 총 비교 횟수는 n + n -1 + n -2 + ... + 1 + 0 입니다. // 이 수열의 합은 n(n+1) 이고 , n2에 비례합니다. 이것은 selection 메소드가 // 이차라는 것을 의미합니다. public static void selectionSort(int[] array) { for (int i = 0; i < array.length; i++) { int j = indexLowest(array, i); swapElemts(array, i, j);
} } } } | cs |
-빅오 표기법-
모든 상수 시간 알고리즘은 O(1) 이라는 집합에 속합니다. 따라서 어떤 알고리즘이 상수 시간임을 다르게 말하고 싶다면 그것이 O(1)에 있다고 말하면 됩니다. 마찬가지로 모든 선형 알고리즘은 O(n)에 속하며 모든 이차 알고리즘은 O(n2)에 속합니다. 이렇게 알고리즘을 분류하는 방식을 빅오 표기법 (big O notation)이라고 합니다.
이 표기법은 알고리즘을 작성할 때 알고리즘이 어떻게 동작하는지에 관한 일반적인 법칙을 표현하는 간편한 방법을 제공합니다. 예를 들어, 상수 시간 알고리즘에 이어 선형 시간 알고리즘을 수행하면 총 실행시간은 선형이 됩니다.
이를 '~의 요소' 라는 의미의 ∈ 기호를 사용하여 표현하면 f∈O(n) 고 g∈O(1) 이면 f+g∈O(n) 가 됩니다.
두개의 선형 연산을 수행하면 합은 여전히 선형입니다. 이를 빅오 표기법으로 표현하면 f∈O(n) 이고 g∈O(n) 면 f+g∈O(n) 가 됩니다.
사실 k가 n에 의존하지 않는 상수인 한 선형 연산을 k번 수행하면 합은 선형입니다. 이를 빅오 표기법으로 표현하면 f∈O(n) 고 k가 상수라면 kf∈O(n)가 됩니다.
하지만 선형 연산을 n번 반복하면 결과는 이차가됩니다. 이를 빅오 표기법으로 표현하면 f∈O(n) 이면 nf∈O(n2) 가 됩니다.
일반적으로 n의 가장 큰 지수만 신경 쓰기 때문에 총 연산 횟수가 2n+1이라면 실행시간은 O(n)입니다. 선행 상수 2와 덧셈 항 1은 이러한 종류의 분석에서 중요하지 않습니다. 마찬가지로 n2 + 100n + 1000도 O(n2)이 됩니다.
증가차수는 같은 개념의 다른 이름입니다. 증가 차수는 실행시간이 같은 빅오 범주에 해당하는 알고리즘 집합니다. 예를 들어, 모든 선형 알고리즘은 실행시간이 O(n)에 있으므로 같은 증가 차수에 속합니다.
이 문맥에서 차수는 집단의 의미로, 원탁의 기사단처럼 기사들의 집단을 가리키지 그들의 순서를 말하는 것이 아닙니다. 따라서 선형 알고리즘 차수는 용감하고 예의 바르고 특히 효율적인 알고리즘 집합이라고 생각하면 된다.
================================================================================================ 미완성
Back-End/Spring 2019. 6. 14. 23:11
-장바구니 기능 구현-
데이터베이스에서 cart 테이블을 생성
|
create table cart(
cart_id number not null primary key, //cart_id를 null값이 오지못하게 하고 기본키로 설정함
userid varchar2(50) not null, //userid를 null값이 오지못하게 설정
product_id number not null, //product_id를 null값이 오지못하게 설정
amount number default 0 //amount속성을 기본값을 0으로 설정
);
|
cs |
cart테이블에 제약조건을 추가한다.
(cart테이블에 cart_userid_fk라는 이름의 제약조건을 cart테이블에 있는 userid에 추가하고,
userid를 다른 테이블의 기본키를 참조하는 외래키로 설정하고, member테이블의 userid를 참조하도록 설정한다.)
(즉, member테이블의 userid가 변경되면 cart테이블에 있는 userid도 같이 변경된다는 뜻이다.)
만약에 cart테이블에 "insert into cart values (2,'kim',2,10)" 쿼리를 실행시켰을 때,
member테이블에 id (kim)이라는 id값이 없기 때문에 자료를 넣을 수 없어 오류가 발생한다.
즉, member 테이블에 존재하는 id값만 cart 테이블에 넣을 수 있다는 뜻이다.
(이렇게 하는 이유는 id값이 서로 일치하지 않아서 오류가 발생할 수 있기 때문에 제약조건을 설정하는 것이다.)
|
alter table cart add constraint cart_userid_fk
foreign key(userid) references member(userid);
|
cs |
아래 3개의 테이블을 참조해서 서로 join한다.
select name, product_name,price,amount,price*amount money
//회원의 이름과, 상품의 이름,물건 한개의 가격, 장바구니에 담은 개수, 총 물건의 가격을 검색한다.
from member m, product p, cart c
//member테이블과, product테이블과, cart테이블로부터 검색
where m.userid=c.userid and p.product_id=c.product_id;
//member의 userid와 cart의 userid가 같고, product의 product_id와 cart의 product_id가 같을때
//즉, 회원의 아이디와 상품을 사려는 회원이 같고, 상품의 번호와 카트의 번호가 같을때
|
장바구니 테이블을 만들었으므로 테이블에 있는 데이터를 저장할 클래스가 필요하다.
DTO 클래스를 생성
CartDTO.java (테이블 3개를 join할 것을 대비해서 필드와 getter, setter을 생성한다)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
|
package com.example.spring02.model.shop.dto;
public class CartDTO {
private int cart_id;
private String userid;
private String name;
private int product_id;
private String product_name;
private int price;
private int money;
private int amount;
public int getCart_id() {
return cart_id;
}
public void setCart_id(int cart_id) {
this.cart_id = cart_id;
}
public String getUserid() {
return userid;
}
public void setUserid(String userid) {
this.userid = userid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getProduct_id() {
return product_id;
}
public void setProduct_id(int product_id) {
this.product_id = product_id;
}
public String getProduct_name() {
return product_name;
}
public void setProduct_name(String product_name) {
this.product_name = product_name;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public int getMoney() {
return money;
}
public void setMoney(int money) {
this.money = money;
}
public int getAmount() {
return amount;
}
public void setAmount(int amount) {
this.amount = amount;
}
@Override
public String toString() {
return "CartDTO [cart_id=" + cart_id + ", userid=" + userid + ", name=" + name + ", product_id=" + product_id
+ ", product_name=" + product_name + ", price=" + price + ", money=" + money + ", amount=" + amount + "]";
}
}
|
cs |
CartDAO 인터페이스를 생성
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
package com.example.spring02.model.shop.dao;
import java.util.List;
import com.example.spring02.model.shop.dto.CartDTO;
public interface CartDAO {
List<CartDTO> cartMoney();
void insert(CartDTO dto); //장바구니 추가
List<CartDTO> listCart(String userid); //장바구니 목록
void delete(int cart_id); //장바구니 개별 삭제
void deleteAll(String userid); //장바구니 비우기
void update(int cart_id);
int sumMoney(String userid); //장바구니 금액 합계
int countCart(String userid, int product_id); //장바구니 상품 갯수
void updateCart(CartDTO dto); //장바구니 수정
void modifyCart(CartDTO dto);
}
|
cs |
CartDAOImpl.java (DAO 인터페이스 구현 클래스)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
|
package com.example.spring02.model.shop.dao;
import java.util.List;
import javax.inject.Inject;
import org.apache.ibatis.session.SqlSession;
import org.springframework.stereotype.Repository;
import com.example.spring02.model.shop.dto.CartDTO;
@Repository
public class CartDAOImpl implements CartDAO {
//MyBatis를 호출하므로 sqlsession에 의존성을 주입해야한다.
@Inject
SqlSession sqlSession;
@Override
public List<CartDTO> cartMoney() {
// TODO Auto-generated method stub
return null;
}
//장바구니에 담기
@Override
public void insert(CartDTO dto) {
//dto에 저장된 값을 받아서 sql세션에 저장하고 cart.insert로 넘어감 mapper로.
sqlSession.insert("cart.insert", dto);
}
@Override
public List<CartDTO> listCart(String userid) {
return sqlSession.selectList("cart.listCart", userid);
}
@Override
public void delete(int cart_id) {
sqlSession.delete("cart.delete", cart_id);
}
@Override
public void deleteAll(String userid) {
sqlSession.delete("cart.deleteAll", userid);
}
@Override
public void update(int cart_id) {
// TODO Auto-generated method stub
}
@Override
public int sumMoney(String userid) {
return sqlSession.selectOne("cart.sumMoney", userid);
}
@Override
public int countCart(String userid, int product_id) {
// TODO Auto-generated method stub
return 0;
}
@Override
public void updateCart(CartDTO dto) {
// TODO Auto-generated method stub
}
@Override
public void modifyCart(CartDTO dto) {
sqlSession.update("cart.modify", dto);
}
}
|
cs |
sql세션에 dto에서 받은 값을 저장한 다음 mapper로 넘어간다.
cartMapper.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
|
<?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와 중복되지 않도록 네임스페이스 기재 -->
<mapper namespace="cart">
<!-- 장바구니에 담기 -->
<insert id="insert">
insert into cart (cart_id, userid, product_id, amount)
values
(seq_cart.nextval, #{userid}, #{product_id}, #{amount} )
//장바구니 담기 버튼을 누를때 실행되는 쿼리문
//cart_id와 userid, product_id, amount 값을 저장한다.
//cart_id는 하나씩 증가되어야하기때문에 시퀀스값으로 지정한다.
</insert>
|
cs |
CART 테이블에 시퀀스를 생성
(시퀀스를 생성하고 그 시퀀스의 시작값은 1로 하고 1씩 증가한다.)
|
create sequence seq_cart
start with 1
increment by 1;
|
cs |
Service 생성
CartService.java (서비스 인터페이스 생성)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
package com.example.spring02.service.shop;
import java.util.List;
import com.example.spring02.model.shop.dto.CartDTO;
public interface CartService {
List<CartDTO> cartMoney();
void insert(CartDTO dto);
List<CartDTO> listCart(String userid);
void delete(int cart_id);
void deleteAll(String userid);
void update(int cart_id);
int sumMoney(String userid);
int countCart(String userid, int product_id);
void updateCart(CartDTO dto);
void modifyCart(CartDTO dto);
}
|
cs |
CartServiceImpl.java (서비스 인터페이스 구현 클래스 생성)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
|
package com.example.spring02.service.shop;
import java.util.List;
import javax.inject.Inject;
import org.springframework.stereotype.Service;
import com.example.spring02.model.shop.dao.CartDAO;
import com.example.spring02.model.shop.dto.CartDTO;
@Service //Service 단이라는 것을 표시
public class CartServiceImpl implements CartService {
@Inject //dao를 사용해야하기 때문에 @Inject로 의존성 부여
CartDAO cartDao;
@Override
public List<CartDTO> cartMoney() {
return null;
}
@Override
public void insert(CartDTO dto) {
cartDao.insert(dto);
}
@Override
public List<CartDTO> listCart(String userid) {
return cartDao.listCart(userid);
}
@Override
public void delete(int cart_id) {
cartDao.delete(cart_id);
}
@Override
public void deleteAll(String userid) {
cartDao.deleteAll(userid);
}
@Override
public void update(int cart_id) {
// TODO Auto-generated method stub
}
@Override
public int sumMoney(String userid) {
return cartDao.sumMoney(userid);
}
@Override
public int countCart(String userid, int product_id) {
// TODO Auto-generated method stub
return 0;
}
@Override
public void updateCart(CartDTO dto) {
// TODO Auto-generated method stub
}
@Override
public void modifyCart(CartDTO dto) {
cartDao.modifyCart(dto);
}
}
|
cs |
CartController.java (장바구니 컨트롤러)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
//컨트롤러에서 메소드의 파라미터들은 갯수제한이 없고, 순서가 상관이 없다.
@RequestMapping("insert.do") //세부적인 url mapping
public String insert(@ModelAttribute CartDTO dto,
HttpSession session) {
//@ModelAttribute는 sumit된 form의 내용을 저장해서 전달받거나, 다시 뷰로 넘겨서 출력하기 위해 사용되는 오브젝트 이다.
//도메인 오브젝트나 DTO의 프로퍼티에 요청 파라미터를 바인딩해서 한번에 받으면 @ModelAttribute 라고 볼 수 있다.
//@ModelAttribute는 컨트롤러가 리턴하는 모델에 파라미터로 전달한 오브젝트를 자동으로 추가해준다.
//로그인 여부를 체크하기 위해 세션에 저장된 아이디 확인
String userid=(String)session.getAttribute("userid");
if(userid==null) {
//로그인하지 않은 상태이면 로그인 화면으로 이동
return "redirect:/member/login.do";
}
dto.setUserid(userid);
cartService.insert(dto); //장바구니 테이블에 저장됨
return "redirect:/shop/cart/list.do"; //장바구니 목록으로 이동
}
|
cs |
CartController.java 중 일부 (장바구니 리스트 관련 메소드)
cartlist.jsp 페이지와 맵핑됨
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
//cart_list페이지와 맵핑되는 메소드
@RequestMapping("list.do")
public ModelAndView list(HttpSession session, ModelAndView mav) {
Map<String, Object> map=new HashMap<>();
//hashmap은 map(key,value)로 이뤄져 있고,
//key값은 중복이 불가능 하고 value는 중복이 가능하다.
//value에 null값도 사용이 가능하다.
//전달할 정보가 많을 경우에는 HashMap<>을 사용하는 것이 좋다.
//장바구니에 담을 값들이 많기 때문에 여기선 HashMap<>를 사용한다.
String userid=(String)session.getAttribute("userid");
//session에 저장된 userid를 getAttribute()메소드를 사용해서 얻어오고 오브젝트 타입이기 때문에
//String 타입으로 타입변환한다.
if(userid!=null) {
//로그인한 상태이면 실행
List<CartDTO> list=cartService.listCart(userid);//장바구니 목록
int sumMoney=cartService.sumMoney(userid);//금액 합계
int fee=sumMoney >= 30000 ? 0 : 2500;
//배송료 계산
//30000원이 넘으면 배송료가 0원, 안넘으면 2500원
//hasp map에 장바구니에 넣을 각종 값들을 저장함
map.put("sumMoney", sumMoney);
map.put("fee", fee); //배송료
map.put("sum", sumMoney+fee); //전체 금액
map.put("list", list); //장바구니 목록
map.put("count", list.size()); //레코드 갯수
//ModelAndView mav에 이동할 페이지의 이름과 데이터를 저장한다.
mav.setViewName("shop/cart_list"); //이동할 페이지의 이름
mav.addObject("map", map); //데이터 저장
return mav; //화면 이동
}else { //로그인하지 않은 상태
return new ModelAndView("member/login", "", null);
//로그인을 하지 않았으면 로그인 페이지로 이동시킨다.
}
}
|
cs |
컨트롤러에서 로그인 여부를 알아야하고, 로그인한 상태이면 서비스와 DAO를 경유해서 mapper에서 "ListCart" id에 대한 쿼리를 실행시킨다.
CartServiceImpl.java (장바구니 서비스 구현 클래스) 중 일부
|
@Override
public List<CartDTO> listCart(String userid) {
return cartDao.listCart(userid);
}
|
cs |
CartDAOImpl.java (장바구니 DAO 구현 클래스) 중 일부
(ListCart태그가 호출된다)
|
@Override
public List<CartDTO> listCart(String userid) {
return sqlSession.selectList("cart.listCart", userid);
}
|
cs |
cartMapper.xml 중 일부
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
<select id="listCart" resultType="com.example.spring02.model.shop.dto.CartDTO">
<!-- DAO에서 listCart라는 태그로 인해 실행되고 결과타입은 DTO타입으로 한다. (다른계층으로 보내기 위해서) -->
select cart_id, p.product_id, c.userid, name, product_name, amount, price, (price*amount) money
<!-- 장바구니의 번호, 상품 번호, 회원번호, 회원이름, 상품이름, 상품의양, 상품1개의 가격, 상품의 전체가격을 검색한다.-->
<!--양쪽 테이블에 다 있는 속성이면 어떤 테이블의 속성인지 정확히 표기해주어야 한다.--!>
from member m, cart c, product p
<!-- 회원테이블과, 장바구니 테이블과, 상품테이블로 부터 -->
where m.userid=c.userid and c.product_id=p.product_id and c.userid=#{userid} order by cart_id
<!--회원테이블의 회원id와 장바구니테이블의 회원id가 같고, 장바구니의 상품id와 상품테이블의 상품id가 같고, 장바구니테이블의 회원id가 장바구니에 저장되있는 회원id와 같을때-->
<!-- 장바구니에 관한 정보를 담은 sql문이다. -->
</select>
|
cs |
Mapper에서 SQL을 사용해서 검색한 목록을 list로 받아서 컨트롤러로 전달을 하고, 그 데이터를 바탕으로
sumMoney(총금액, 서비스와 DAO를 거쳐서 받고, 다시 Mapper을 거쳐서 컨트롤러로 받게됨)
CartServiceImpl.java (서비스 인터페이스 구현 클래스) 중 일부
|
@Override
public int sumMoney(String userid) {
return cartDao.sumMoney(userid);
}
|
cs |
CartDAOImpl.java (DAO 인터페이스 구현 클래스) 중 일부
|
@Override
public int sumMoney(String userid) {
return sqlSession.selectOne("cart.sumMoney", userid);
}
|
cs
|
cartMapper.xml 중 일부
(조인을 하는 이유는 장바구니 테이블에는 가격이 없기때문에 가격이 있는 다른 테이블과 join을 해야한다.)
|
<select id="sumMoney" resultType="int">
select nvl(sum(price*amount),0)
<!--금액과 상품갯수를 곱한값과 0을더해서 0이 나오는 것을 검색한다. -->
<!--그러니까 아무것도 담지 않았을때를 확인하는 것이다. -->
<!--빈값이 null이면 안되기 때문에 대체값으로 0이 출력되게끔 만들었다--!>
from cart c,product p
<!-- 장바구니 테이블과 상품 테이블로 부터 -->
where c.product_id=p.product_id and userid=#{userid}
<!--조건 : 장바구니테이블의 상품 id가 상품테이블의 상품 id와 같고, 요청하는 회원의 id와 같은 경우 -->
</select>
|
cs |
cart_list.jsp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
|
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<%@ include file="../include/header.jsp" %>
<script>
$(function(){
$("#btnList").click(function(){
location.href="${path}/shop/product/list.do";
});
// 아래쪽에서 btnlist를 호출해서 실행되는 function() 함수 구문.
// list로 가는 링크를 만든다.
$("#btnDelete").click(function(){
if(confirm("장바구니를 비우시겠습니까?")){
location.href="${path}/shop/cart/deleteAll.do";
}
});
});
</script>
</head>
<body>
<%@ include file="../include/menu.jsp" %>
<h2>장바구니</h2>
<c:choose>
<c:when test="${map.count == 0 }">
<!-- when은 ~~일때 라는 뜻 그러니까 map의 count가 0일때... -->
<!-- xml파일에서 hashmap에 list를 넣어놓았기 때문에 현재 map에 자료가 들어있다. -->
<!-- map에 자료가 아무것도 없다면 -->
장바구니가 비었습니다.
</c:when>
<c:otherwise>
<!-- map.count가 0이 아닐때, 즉 자료가 있을때 -->
<!-- form을 실행한다. -->
<!-- form의 id를 form1로 하고, method 방식을 post로 한다. 그리고 update.do페이지로 이동시킨다. -->
<form id="form1" name="form1" method="post"
action="${path}/shop/cart/update.do">
<table border="1" width="400px">
<tr>
<th>상품명</th>
<th>단가</th>
<th>수량</th>
<th>금액</th>
<th> </th>
</tr>
<!-- map에 있는 list출력하기 위해 forEach문을 사용해 row라는 변수에 넣는다. -->
<c:forEach var="row" items="${map.list}">
<tr align="center">
<td>${row.product_name}</td>
<td><fmt:formatNumber value="${row.price}"
pattern="#,###,###" /></td>
<!-- fmt:formatNumber 태그는 숫자를 양식에 맞춰서 문자열로 변환해주는 태그이다 -->
<!-- 여기서는 금액을 표현할 때 사용 -->
<!-- ex) 5,000 / 10,000 등등등-->
<td><input type="number" name="amount"
style="width:30px;"
value="<fmt:formatNumber value="${row.amount}"
pattern="#,###,###" />">
<!-- 물건의 개수 (amount)를 fmt태그를 사용해서 패턴의 형식에 맞춰서 문자열로 변환함 -->
<!--1,000 / 5,000 등등~ -->
<input type="hidden" name="cart_id"
value="${row.cart_id}">
</td>
<td><fmt:formatNumber value="${row.money}"
pattern="#,###,###" /></td>
<td><a href=
"${path}/shop/cart/delete.do?cart_id=${row.cart_id}">[삭제]</a>
<!-- 삭제 버튼을 누르면 delete.do로 장바구니 개별 id (삭제하길원하는 장바구니 id)를 보내서 삭제한다. -->
</td>
</tr>
</c:forEach>
<tr>
<td colspan="5" align="right">
장바구니 금액 합계 :
<fmt:formatNumber value="${map.sumMoney}"
pattern="#,###,###" /><br>
배송료 : ${map.fee}<br>
총합계 : <fmt:formatNumber value="${map.sum}"
pattern="#,###,###" />
</td>
</tr>
</table>
<button id="btnUpdate">수정</button>
<button type="button" id="btnDelete">장바구니 비우기</button>
//btnUpdate와 btnDelete id는 위쪽에 있는 자바스크립트가 처리한다.
</form>
</c:otherwise>
</c:choose>
<button type="button" id="btnList">상품목록</button>
</body>
</html>
|
cs |
-장바구니 삭제-
( 뷰 => 컨트롤러 => 서비스 => 모델(DAO) => mapper => 컨트롤러 => 뷰) cart_list.jsp에 있는 delete을 호출하면
컨트롤러로 이동해 delete.do와 맵핑하고 서비스에 장바구니 id를 넘겨준다.
서비스에서는 넘겨받은 id를 DAO에 저장하고, DAO에서는 태그 아이디가 delete인 태그를 mapper에 전달하고, id도 전달한다.
mapper에서는 userid가 특정 id (사용자가 선택한 id)를 다 지우게끔 한다.
그리고 장바구니를 삭제한 후에 다시 컨트롤러로 돌아와 list.jsp 파일로 이동한다.
|
cart_list.jsp (View) 중 일부
|
<td>
<a href= "${path}/shop/cart/delete.do?cart_id=${row.cart_id}">[삭제]</a>
</td>
|
cs |
cartController.java 중 일부
|
@RequestMapping("delete.do")
public String delete(@RequestParam int cart_id) {
cartService.delete(cart_id);
return "redirect:/shop/cart/list.do";
}
|
cs |
cartServiceImpl.java 중 일부
|
@Override
public void delete(int cart_id) {
cartDao.delete(cart_id);
}
|
cs |
cartDAOImpl.java 중 일부
|
@Override
public void delete(int cart_id) {
sqlSession.delete("cart.delete", cart_id);
}
|
cs |
cartMapper.xml 중 일부
|
<!-- 장바구니 개별 상품 삭제 -->
<delete id="delete">
delete from cart where cart_id=#{cart_id}
</delete>
|
cs |
-장바구니 비우기-
( 뷰 => 컨트롤러 => 서비스 => 모델(DAO) => mapper => 컨트롤러 => 뷰 )
cart_list.jsp에 있는 javascript구문에서 deleteAll을 호출하면
컨트롤러로 이동해 deleteAll.do와 맵핑하고 세션에서 유저의아이디를 가져와서 null이 아닐경우에 서비스로 아이디를 넘긴다.
서비스에서는 넘겨받은 id로 DAO를 호출하고, DAO에서는 태그 아이디가 deleteAll인 태그를 mapper에 전달하고, id도 전달한다.
mapper에서는 userid가 특정 id (사용자가 선택한 id)를 다 지우게끔 한다.
그리고 장바구니를 전부다 비운 후에 다시 컨트롤러로 돌아와 list.jsp 파일로 이동한다.
|
cart_list.jsp (view)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
<script>
$(function(){
$("#btnList").click(function(){
location.href="${path}/shop/product/list.do";
});
$("#btnDelete").click(function(){
if(confirm("장바구니를 비우시겠습니까?")){
location.href="${path}/shop/cart/deleteAll.do";
}
});
});
</script>
======================================================================
<button type="button" id="btnDelete">장바구니 비우기</button>
|
cs |
CartController.java (controller)
|
@RequestMapping("deleteAll.do")
public String deleteAll(HttpSession session) {
String userid=(String)session.getAttribute("userid");
if(userid!=null) {
cartService.deleteAll(userid);
}
return "redirect:/shop/cart/list.do";
}
|
cs |
CartServiceImpl.java (Service)
|
@Override
public void deleteAll(String userid) {
cartDao.deleteAll(userid);
}
|
cs |
CartDAOImpl.java (model-DAO)
|
@Override
public void deleteAll(String userid) {
cartDao.deleteAll(userid);
}
|
cs |
cartMapper.xml
|
<!-- 장바구니 비우기 -->
<delete id="deleteAll">
delete from cart where userid=#{userid}
<!-- 장바구니테이블로부터 회원의 아이디와 삭제하고자하는 회원의 아이디가 같으면 장바구니에 있는 자료를 전부다 삭제 -->
</delete>
|
cs |
아래 책은 제가 공부할때 활용했던 책으로 추천드리는 책이니 한번씩 읽어보시는것을 추천드립니다!! ㅎㅎ

이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.
-장바구니 수정-
위의 삭제나 비우기와 구조가 거의 동일
Back-End/Problems 2019. 6. 13. 13:42
HTTP Status 500 – Internal Server Error
Type Exception Report Message Request processing failed; nested exception is org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.exceptions.PersistenceException: Description The server encountered an unexpected condition that prevented it from fulfilling the request. Exception org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.exceptions.PersistenceException:
### Error querying database. Cause: java.lang.IllegalArgumentException: Mapped Statements collection does not contain value for member.login_check
### Cause: java.lang.IllegalArgumentException: Mapped Statements collection does not contain value for member.login_check
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1013)
org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:908)
javax.servlet.http.HttpServlet.service(HttpServlet.java:661)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882)
javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
Root Cause org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.exceptions.PersistenceException:
### Error querying database. Cause: java.lang.IllegalArgumentException: Mapped Statements collection does not contain value for member.login_check
### Cause: java.lang.IllegalArgumentException: Mapped Statements collection does not contain value for member.login_check
org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:77)
org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:446)
com.sun.proxy.$Proxy10.selectOne(Unknown Source)
org.mybatis.spring.SqlSessionTemplate.selectOne(SqlSessionTemplate.java:166)
com.example.spring02.model.member.dao.MemberDAOImpl.loginCheck(MemberDAOImpl.java:20)
com.example.spring02.service.member.MemberServiceImpl.loginCheck(MemberServiceImpl.java:26)
com.example.spring02.controller.member.MemberController.login_check(MemberController.java:41)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:498)
org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:189)
org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:800)
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1038)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:942)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005)
org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:908)
javax.servlet.http.HttpServlet.service(HttpServlet.java:661)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882)
javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
Root Cause org.apache.ibatis.exceptions.PersistenceException:
### Error querying database. Cause: java.lang.IllegalArgumentException: Mapped Statements collection does not contain value for member.login_check
### Cause: java.lang.IllegalArgumentException: Mapped Statements collection does not contain value for member.login_check
org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30)
org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:150)
org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:141)
org.apache.ibatis.session.defaults.DefaultSqlSession.selectOne(DefaultSqlSession.java:77)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:498)
org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:433)
com.sun.proxy.$Proxy10.selectOne(Unknown Source)
org.mybatis.spring.SqlSessionTemplate.selectOne(SqlSessionTemplate.java:166)
com.example.spring02.model.member.dao.MemberDAOImpl.loginCheck(MemberDAOImpl.java:20)
com.example.spring02.service.member.MemberServiceImpl.loginCheck(MemberServiceImpl.java:26)
com.example.spring02.controller.member.MemberController.login_check(MemberController.java:41)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:498)
org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:189)
org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:800)
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1038)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:942)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005)
org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:908)
javax.servlet.http.HttpServlet.service(HttpServlet.java:661)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882)
javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
Root Cause java.lang.IllegalArgumentException: Mapped Statements collection does not contain value for member.login_check
org.apache.ibatis.session.Configuration$StrictMap.get(Configuration.java:888)
org.apache.ibatis.session.Configuration.getMappedStatement(Configuration.java:721)
org.apache.ibatis.session.Configuration.getMappedStatement(Configuration.java:714)
org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:147)
org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:141)
org.apache.ibatis.session.defaults.DefaultSqlSession.selectOne(DefaultSqlSession.java:77)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:498)
org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:433)
com.sun.proxy.$Proxy10.selectOne(Unknown Source)
org.mybatis.spring.SqlSessionTemplate.selectOne(SqlSessionTemplate.java:166)
com.example.spring02.model.member.dao.MemberDAOImpl.loginCheck(MemberDAOImpl.java:20)
com.example.spring02.service.member.MemberServiceImpl.loginCheck(MemberServiceImpl.java:26)
com.example.spring02.controller.member.MemberController.login_check(MemberController.java:41)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:498)
org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:189)
org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:800)
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1038)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:942)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005)
org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:908)
javax.servlet.http.HttpServlet.service(HttpServlet.java:661)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882)
javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
Note The full stack trace of the root cause is available in the server logs.
Apache Tomcat/8.5.41
6월 13, 2019 11:57:14 오전 org.apache.catalina.core.StandardWrapperValve invoke 심각: Servlet.service() for servlet [appServlet] in context with path [/spring02] threw exception [Request processing failed; nested exception is org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.exceptions.PersistenceException: ### Error querying database. Cause: java.lang.IllegalArgumentException: Mapped Statements collection does not contain value for member.login_check ### Cause: java.lang.IllegalArgumentException: Mapped Statements collection does not contain value for member.login_check] with root cause java.lang.IllegalArgumentException: Mapped Statements collection does not contain value for member.login_check
Front-End/javascript 2019. 6. 12. 22:34
javascript에서는 함수도 객체이다.
다시 말해서 일종의 값이고, javascript의 함수가 다른 언어의 함수와 다른 점은 함수가 값이 될 수 있다는 점이다.
-예시-
var a = function( ){ } // a라는 변수안에 함수function( )을 넣을 수 있다. |
또한 함수는 객체의 값으로 포함될 수 있다.
이렇게 객체의 속성 값으로 담겨진 함수를 메소드(method) 라고 부른다.
-예시-
a = { // a라는 변수 안에 객체를 생성 b : function( ) { // 객체 안에 b라는 키(key)값에 function( ) 함수를 생성한다. 이러한 함수를 메소드라고 부른다. } };
|
참고 : key는 속성이나 property 라고 부르기도 한다.
함수는 값이기 때문에 다른 함수의 인자(매개값) 으로 전달 될수도 있다.
-예시-
|
function a (cal, num){
return cal(num) //a라는 함수는 cal과 num을 매개값으로 받고 cal이라는 함수에 num을 매개값으로 준 값을 리턴
}
function increase (num){
return num*2 //increase이라는 함수는 num을 매개값으로 받고 num*2를 리턴한다.
}
console.log(a(increase,5)); //함수 a의 매개값으로 increase함수와 5를 매개값으로 주고, increase함수가 실행되서 num*2의 값인 10이 리턴된다.
10
|
cs |
변수, 매개변수, 리턴값과 같이 다양한 용도로 사용될 수 있는 데이터를 first-class citizen (object)라고 한다.
javascript에서 function(함수)는 first-class에 해당이 된다.
함수는 함수의 리턴 값으로도 사용할 수 있다.
-예제-
|
function cal (mode) {
var funcs = {
'plus' : function(left,right){return left + right},
'minus' : function(left,right){return left - right}
}
return funcs[mode];
}
alert(cal('plus')(2,1)); //cal함수에 'plus'값을 메소드로 주면 funcs의 객체중 'plus'와 맞는 키가 실행되고 그 안에 있는 함수가 실행되서 3이 리턴된다.
alert(cal('minus')(2,1)); //cal함수에 'minus'값을 메소드로 주면 funcs의 객체중 'minus'와 맞는 키가 실행되고 그 안에 있는 함수가 실행되서 1이 리턴된다.
|
cs |
또한 함수는 배열의 값으로도 사용할 수 있다.
-예제-
1
2
3
4
5
6
7
8
9
10
11
12
|
var process = [
function(input) {return input + 10;} //input가 1이므로 11이 리턴
function(input) {return input * input;}, //input가 11이므로 121이 리턴
function(input) {return input / 2;} //input가 121이므로 60.5가 리턴
];
var input = 1;
for (var i = 0; i < process.length; i++){ 배열의 길이는 0~2까지 이므로 length=0,1,2까지
input = process[i](input); //함수가 한번 호출될때마다 input값이 변화됨
}
alert(input);
|
cs |
콜백
처리의 위임
값으로 사용될 수 있는 특성을 이용하면 함수의 인자로 함수를 전달할 수 있다.
값으로 전달된 함수는 호출될 수 있기 때문에 이를 이용하면 함수의 동작을 완전히 바꿀 수 있다.
인자로 전달된 함수 sortNumber의 구현에 따라서 sort의 동작방법이 완전히 바뀌게 된다.
아래 책은 제가 공부할때 활용했던 책으로 추천드리는 책이니 한번씩 읽어보시는것을 추천드립니다!! ㅎㅎ

이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.
Back-End/Spring 2019. 6. 12. 18:23
- 상품관리 (로그인 / 로그아웃 기능 구현) -
세션을 사용해서 세션이 아이디와 비밀번호를 저장한 후 페이지를 이동해도 로그인 정보가 그대로 넘어가게 할 예정
뷰 => 컨트롤러 => 서비스 => 모델 => 뷰
-로그인-
menu.jsp 페이지에서 로그인 링크를 누르면 login.do( login.jsp 페이지 ) 로 이동.
login.jsp 페이지에서 아이디와 비밀번호를 입력하고 로그인 버튼을 누르면 id 값 (btnLogin) 이 위쪽에 있는 javaScript 구문으로 넘겨받아서
아이디와 비밀번호가 DTO와 DAO를 거쳐서 컨트롤러에 맵핑된 login_check로 넘어간다.
name값이 null값이 아니면 (로그인이 성공하면) home페이지로 이동하고, 로그인이 실패하면 login 페이지로 되돌아간다.
|
menu.jsp (로그인과 로그아웃 페이지로 이동하는 태그를 추가) | <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix = "c" uri = "http://java.sun.com/jsp/jstl/core" %> <!-- 다른페이지에 include되는 페이지 --> <a href = "${path }/memo/list.do">한줄메모장</a> ㅣ <a href = "${path }/upload/uploadForm">업로드 테스트</a> ㅣ <a href = "${path }/shop/product/list.do">상품목록</a> ㅣ <div style = "text-align: right;"> <a href = "${path }/member/login.do">로그인</a> //login.do로 이동하는 링크를 만듬
<a href = "${path }/member/logout.do">로그아웃</a> //logout.do로 이동하는 링크를 만듬 </div> | cs |
회원테이블은 기존에 만들어놓은 테이블을 사용한다. (member 테이블)
MemberDTO.java (계층별 데이터 교환 클래스) member테이블에 있는 속성명과 맞춰서 만든다. (데이터를 넣고 빼고가 자유롭게...) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | package com.example.spring02.model.member.dto; import java.util.Date; public class MemberDTO { private String userid; private String passwd; private String name; private String email; private Date join_date; public String getUserid() { return userid; } public void setUserid(String userid) { this.userid = userid; } public String getPasswd() { return passwd; } public void setPasswd(String passwd) { this.passwd = passwd; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public Date getJoin_date() { return join_date; } public void setJoin_date(Date join_date) { this.join_date = join_date; } @Override public String toString() { return "MemberDTO [userid=" + userid + ", passwd=" + passwd + ", name=" + name + ", email=" + email + ", join_date=" + join_date + "]"; } } | cs |
MemberDAO.java (DB연결 클래스) | package com.example.spring02.model.member.dao; import com.example.spring02.model.member.dto.MemberDTO; public interface MemberDAO { public String loginCheck(MemberDTO dto); //DTO에서 값을 받아 로그인을 체크하는 메소드 } | cs |
MemberDAOImpl.java (DB연결 구현 클래스) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | package com.example.spring02.model.member.dao; import javax.inject.Inject; import org.apache.ibatis.session.SqlSession; import org.springframework.stereotype.Repository; import com.example.spring02.model.member.dto.MemberDTO; @Repository public class MemberDAOImpl implements MemberDAO { //mybatis를 호출하기 때문에 Inject을 받아야한다 (의존성 주입) @Inject SqlSession sqlSession; @Override public String loginCheck(MemberDTO dto) { //loginCheck메소드를 구현 return sqlSession.selectOne("member.login_check", dto);
//sqlsession의 selectOne메소드에 한가지 값(dto)를 담아서 리턴함 //mapper을 호출하기 위해 mapper id와 저장할 값을 지정 } }
| cs |
memberMapper.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와 중복되지 않도록 네임스페이스 기재 -->
<mapper namespace="member">
<select id = "Login_check" resultType = "com.example.spring02.model.member.dto.MemberDTO"> <!-- id 속성에는 해당 sql문을 참조하는 이름 (파일)을 적고 => Login_check resultType는 검색결과의 레코드를 어떤 형태로 변환시킬건지 작성한다. -->
<!-- 즉 Login_check파일에서 밑에 있는 sql문을 참조하고 (실행하고) 그 결과를 MemberDTO 타입으로 변환 (다른 계층으로 자료를 이동시키기 위해) 한다. --> select * from member where userid = #{userid} and passwd = #{passwd} <!-- 회원의 아이디와 비밀번호가 모두 일치하는 회원의 모든 정보를 검색하는 sql문 -->
</select> </mapper> | cs |
MemberService.java (회원 서비스 인터페이스) | package com.example.spring02.service.member; import javax.servlet.http.HttpSession; import com.example.spring02.model.member.dto.MemberDTO; public interface MemberService { //HttpSession은 사용자 인증정보를 처리하는 클래스 public String loginCheck(MemberDTO dto, HttpSession session); //로그인 체크 메소드 public void logout(HttpSession session); //로그아웃 체크 메소드 } | cs |
MemberServiceImpl.java (회원 서비스 인터페이스 구현 클래스) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | package com.example.spring02.service.member; import javax.inject.Inject; import javax.servlet.http.HttpSession; import org.springframework.stereotype.Service; import com.example.spring02.model.member.dao.MemberDAO; import com.example.spring02.model.member.dto.MemberDTO; //서비스 계층에서 서비스를 처리하는 어노테이션이므로 서비스 어노테이션을 반드시 붙여야 한다. @Service public class MemberServiceImpl implements MemberService { // 서비스는 dao를 호출하기 때문에 의존성을 주입해야한다. @Inject MemberDAO memberDao; @Override public String loginCheck(MemberDTO dto, HttpSession session) { // 로그인 체크 메소드 // 그러니까 DTO => DAO 로 넘어가는 과정 // 아이디와 비밀번호가 맞으면 이름이 넘어오고 틀리면 null이 넘어온다. // dao 클래스에 로그인 체크 메소드에 매개값으로 주어진 이름을 name변수에 저장 String name = memberDao.loginCheck(dto); if (name != null) {// 맞으면 // 세션변수 등록 session.setAttribute("userid", dto.getUserid()); // DTO에 저장된 회원의 아이디를 userid라는 이름으로 세션에 저장 session.setAttribute("name", name); // 위에서 로그인체크를 할때 받은 name를 세션에 저장하고 이 이름을 name라고 저장한다. } return name; } @Override public void logout(HttpSession session) { // 세션을 모두 초기화시킴 (로그아웃이므로 세션에 저장된 회원정보를 없애야 한다.) // invalidate( )메소드를 사용하면 사용자의 id까지 바뀌어버린다. session.invalidate(); } } | cs |
MemberController.java (회원정보 컨트롤러) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | package com.example.spring02.controller.member; import javax.inject.Inject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import com.example.spring02.service.member.MemberService; @Controller @RequestMapping("/member/*") // 클래스 전체에서 사용하는 공통적인 url 매핑, 매핑을 할때 공통적인 코드를 줄이기 위해서 사용한다. public class MemberController { private static final Logger logger = LoggerFactory.getLogger(MemberController.class); // MemberController의 로그를 출력하기 위해 getLogger 메소드를 사용해서 LoggewrFactory 에 담고 logger 변수에 저장 // 컨트롤러에서 서비스를 호출하기 때문에 어노테이션을 사용해서 의존성을 주입해야한다. // 객체 생성과 소멸을 스프링에서 관리하게끔 하기 위해 @Inject MemberService memberService; @RequestMapping("login.do") // 이쪽에 있는건 세부적인 매핑 // login.do로 요청을 하면 member 폴더의 login.jsp 파일로 이동해서 로그인 할 수 있는 화면을 만들어주게끔 한다. public String login() { return "member/login"; } } | cs |
login.jsp 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> <%@ include file="../include/header.jsp"%> <script> //아래쪽에서 id값을 받아서 데이터를 전송한다. //click 메소드 안에 있는 함수를 실행해서 id와 비밀번호를 저장하고 //빈 값(공백값) 이면 경고창을 출력하고, 커서를 이동시킨다. // val () 메소드는 form (양식)의 값을 가져오거나 값을 설정하는 메소드 // focus () 메소드는 해당 요소에 포커스를 부여하고, 텍스트 창의 경우 커서를 위치시켜 바로 입력이 가능하도록 하던가 // 버튼의 경우, 엔터키를 눌렀을때 클릭 효과를 낸다. $(function(){ $("#btnLogin").click(function(){ var userid = $("#userid").val(); var passwd = $("#passwd").val(); if(userid==""){ alert("아이디를 입력하세요."); $("#userid").focus(); return; } if(passwd==""){ alert("비밀번호를 입력하세요."); $("#passwd").focus(); return; } //아이디와 비밀번호가 맞으면 login_check페이지로 넘어간다. document.form1.action = "${path}/member/login_check.do"; document.form1.submit(); }); }); </script> </head> <body> <%@ include file="../include/menu.jsp"%> <h2>로그인</h2> <form name="form1" method="post"> <table border="1" width="400px"> <tr> <td>아이디</td> <td><input id="userid" name="userid"></td> </tr> <tr> <td>비밀번호</td> <td><input type="password" id="passwd" name="passwd"></td> </tr> <tr> <td colspan="2" align="center"> <!-- type가 button타입이기 때문에 데이터 전송기능이 없다. --> <!-- 그래서 id값을 javascript에 줘서 자바스크립트에서 데이터를 전송할 수 있게끔 한다. --> <button type="button" id="btnLogin">로그인</button> <!-- param(파라미터)를 사용해서 값이 다시 넘어오는 경우 로그인이 안되어있으면 (nologin) --> <!-- 먼저 로그인 하라는 메시지를 출력한다. --> <c:if test="${param.message == 'nologin' }"> <div style="color: red;">먼저 로그인 하세요.</div> </c:if> <!-- param(파라미터)를 사용해서 값이 넘어오는 경우에 아이디와 비밀번호가 틀려서 'error'과 같으면 --> <!-- 아이디 또는 비밀번호가 일치하지 않는다는 메시지를 출력함 --> <c:if test="${param.message == 'error' }"> <div style="color: red;">아이디 또는 비밀번호가 일치하지 않습니다.</div> </c:if> <!-- 또한 로그아웃틀 하게되면 로그아웃이 되었다는 메시지를 출력함 --> <c:if test="${param.message == 'logout' }"> <div style="color: red;">로그아웃 되었습니다.</div> </c:if> </table> </form> </body> </html> | cs |
login 페이지에서 로그인 정보를 쓰고 로그인 버튼을 누르면 컨트롤러의 logincheck 로 넘어감.
MemberController.java 중 일부
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | //View (login 페이지에서 아이디와 비밀번호를 쓰게 되면 컨트롤러에서 이 메소드를 거쳐서 logincheck페이지로 이동함) @RequestMapping("login_check.do") public ModelAndView login_check(@ModelAttribute MemberDTO dto, HttpSession session) { //login페이지에서 넘어와서 DTO에 저장된 아이디와 비밀번호를 @ModeAttribute어노테이션을 사용해서 한꺼번에 2개를 다 받는다. //사용자가 로그인한 정보를 계속 가지고 있게 하기 위해서 세션도 받는다. //로그인 성공 => 이름이 넘어옴, 실패 => NULL이 넘어옴 String name = memberService.loginCheck(dto, session); //서비스 계층에 loginCheck메소드의 매개값으로 dto (아이디, 비밀번호, 세션) 변수 name에 저장 ModelAndView mav = new ModelAndView(); // 데이터를 보낼 뷰와 데이터를 동시에 설정하기 위해 ModelAndView타입의 객체를 생성한다. if (name != null) { //로그인이 성공하면 시작페이지로 이동함. mav.setViewName("home"); }else {//로그인이 실패하면 login 페이지로 다시 돌아감 mav.setViewName("member/login"); mav.addObject("message", "error"); //로그인 페이지에 에러라는 값을 준다. 그러면 그 에러메시지를 값으로 받아서 경고메시지 출력 } return mav; } | cs |
-로그아웃-
MemberController.java 중 일부 | @RequestMapping("logout.do") //logout.do에 매핑 public ModelAndView logout( HttpSession session, ModelAndView mav) { memberService.logout(session); //세션 초기화 작업 mav.setViewName("member/login"); //이동할 페이지의 이름 mav.addObject("message","logout"); //변수 저장 return mav; //페이지로 이동 } | cs |
login.jsp 중 일부 mav에 있는 logout 메시지가 아래 구문에서 걸려서 "로그아웃 되었습니다" 메시지를 출력한다. | <c:if test="${message == 'logout' }"> <div style="color:red;"> 로그아웃되었습니다. </div> </c:if> | cs |
Back-End/Spring 2019. 6. 12. 12:29
상품관리 (상품 상세 보기 구현)
상품이름에 링크를 걸어 상품 상세정보를 출력하고, 장바구니 기능을 사용할수있게 한다.
-상품 상세 보기-
1. list 파일에서 "상품상세보기" 링크를 클릭 하면 URL을 컨트롤러로 보낸다.
2. 그리고 끝에 들어가는 상품 번호는 URL에 포함된 변수이므로 @PathVariable로 저장이 된다.
3. list파일에서 보낸 URL을 컨트롤러에서 받고, 그 URL에 맞는 @RequestMapping된 메소드를 실행한다.
4. 매핑된 메소드 안에는 데이터를 보낼 뷰를 설정하고, 보낼 데이터를 동시에 설정하기 위해 ModelAndView 타입을 사용하고,
5. setViewName( ) 메소드 (데이터를 보낼 뷰의 위치) , addObject( ) 메소드 (보낼 데이터와 보낼 데이터의 이름을 지정) Product을 사용해 ModelAndView 타입으로 리턴한다. (즉, 상품번호를 리턴함)
6. DAO 구현 클래스에서 sqlsession의 selectone( ) 메소드를 사용해서 sqlsession에 저장된 값 중 하나 (상품번호) 를 리턴한다. (단, namespace와 id를 맞게 입력을 해야 mapper과 매핑이 되니 주의)
7. mapper에서 select id에 namespace 이름을 적고, 조건을 설정해서 sql구문을 사용하기 위해 id에 인터페이스에서 구현한 product_id (상품번호)를 넣는다.
1. product_list 중 일부 (상품 상세보기를 하기 위해 상품이름에 링크를 거는 코드 추가) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <tr> <th>상품ID</th> <th>상품사진</th> <th>상품명</th> <th>가격</th> </tr> <c:forEach var="row" items="${list }"> <tr align = "center"> <td>${row.product_id }</td> <td><img src="${path }/images/${row.picture_url}" width="100" height = "100"></td> <td> <a href = "${path }/shop/product/detail/${row.product_id}"> ${row.product_name }</a> //끝에 상품 코드가 들어간다. 그리고 끝에 들어가는 상품 번호는 //URL에 포함된 변수이므로 @PathVariable로 저장이 된다. </td> | cs |
이 URL을 컨트롤러로 받아서 처리
2. ProductController.java 중 일부 (url 매핑 처리 코드 추가) |
//상세정보 페이지에서 URL이 매핑되서 실행
@RequestMapping("/detail/{product_id}")
public ModelAndView detail(
//아까 product_list 페이지에서 보낸 id와, @PathVariable("product_id") //URL에 포함된 변수이기 때문에 반드시 @PathVariable를 사용한다.
int product_id, ModelAndView mav) {
//데이터를 보낼 뷰를 설정하고, 보낼 데이터를 동시에 설정하기 위해 ModelAndView를 사용 //ModelAndView에 데이터를 보낼 뷰의 위치를 설정하고, //보낼 데이터를 설정하고, ModelAndView타입으로 리턴한다.
mav.setViewName("/shop/product_detail"); mav.addObject("dto", productService.detailProduct(product_id));
return mav; }
| cs |
3. ProductServiceImpl.java (서비스 인터페이스 구현 클래스) 중 일부 | @Override public ProductDTO detailProduct(int product_id) { return productDao.detailProduct(product_id); //상품아이디를 매개변수로 받아서 Dao에 있는 상품의 정보를 리턴 } | cs |
4. ProductDAOImpl.java (DAO 인터페이스 구현 클래스) 중 일부 | @Override public ProductDTO detailProduct(int product_id) { return sqlSession.selectOne(//sqlsession에 저장된 값중에 하나를 리턴한다 (상품번호) "product.detail_product",product_id); //앞쪽에 namespace와 뒤쪽에 id를 적는다. 이렇게 해야 Mapper와 매핑이 된다. } | cs |
1. selectOne : 쿼리 결과가 없으면 null을 반환한다. 쿼리 결과로 레코드가 하나만 나와야 한다. DB에 레코드가 하나만 있는 경우에 사용 => 다수의 레코드가 있을 시 TooManyResultsException 에러가 발생
2. selectList : 쿼리 결과를 List<E>로 반환한다. 결과가 없을 시에는 빈 List를 반환한다 (null을 반환한다,)
|
5. productMapper.xml 중 일부
하나의 데이터가 DTO에 저장이 되서 계속 넘어가는 구조 | <select id = "detail_product" resultType = "com.example.spring02.model.shop.dto.ProductDTO" >
<!-- 상품 상세정보 확인 id -->
select * from product where product_id=#{product_id} //select id에 namespace 이름을 적고, 조건을 설정해서 sql구문을 사용하기 위해 </select> //id에 인터페이스에서 구현한 product_id (상품번호)를 넣는다. | cs |
6. product_detail.jsp 파일 작성 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <%@include file="../include/header.jsp"%> </head> <body> <%@ include file="../include/menu.jsp"%> <h2>상품 정보</h2> <table> <tr> <!-- 이미지를 불러오기위한 url 작성 --> <td><img src="${path}/images/${dto.picture_url}" width="300px" height="300px"></td> <td align="center"> <table> <tr> <td>상품명</td> <td>${dto.product_name }</td> </tr> <tr> <td>가격</td> <td>${dto.price }</td> </tr> <tr> <td> </td> <td>${dto.description }</td> <!-- 상품 설명을 가져옴 --> </tr> <tr> <td colspan="2"> * 장바구니에 담기 기능 *
<form name="form1" method="post" action="${path }/shop/cart/insert.do"> <input type="hidden" name="product_id" value="${dto.product_id }"> <!-- 상품코드를 히든타입으로 넘김 --> <select name="amount"> <c:forEach begin="1" end="10" var="i"> <option value="${i}">${i}</option> <!-- 장바구니에 10개 까지 담을수 있다.--> </c:forEach> </select> 개 <input type="submit" value="장바구니에 담기"> </form> <a href="${path}/shop/product/list.do">상품목록</a> </td> </tr> </table> </table> </body> </html> | cs |
Back-End/Spring 2019. 6. 12. 11:48
- 상품관리 실습 파일 목록 -
ProductDTO.java (계층별 데이터 이동)
ProductDAO.java (상품관리 DB연결 인터페이스)
ProductDAOImpl.java (상품관리 DB연결 구현 클래스)
ProductMapper.xml (SQL 매핑 어노테이션을 가진 자바 클래스)
ProductService.java (상품 서비스 계층 인터페이스)
ProductServiceImpl.java (상품 서비스 계층 구현 클래스)
product_list.jsp (상품 리스트)
product_detail.jsp (상품 정보)
|
기본적으로 컨트롤러 => 서비스 호출 서비스 => 모델 호출
참고 https://abn-abn.tistory.com/211
-상품 목록보기 구현-
1. 메인페이지에서 컨트롤러(list.do) URL이 매핑되어 있는 메소드를 호출
2. 그 메소드에서는 ProductService에서 상품 리스트를 받아와서 list라는 이름으로 저장하고, product_list페이지로 이동.
3. product_list 페이지에서는 ProductDAO (ProductDAOImpl로 구현한 클래스) 에서 DB에 저장된 ID, NAME, PRICE, PICTURE_URL 값을 DTO를 거쳐서 불러온다.
4. ProductMapper.xml에서 SQL 상품 정보를 정렬해주는 SQL문을 실행하고, 그 상품 정보(DTO에 담긴 정보)들을 arraylist에 저장한다.
5. product_list파일에선 그 저장한 리스트를 불러와서 하나씩 출력한다.
ProductDTO.java 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | package com.example.spring02.model.shop.dto; import org.springframework.web.multipart.MultipartFile; public class ProductDTO { private int product_id; private String product_name; private int price; private String description; private String picture_url; private MultipartFile file1; //첨부파일은 MultipartFile타입으로 저장한다. public int getProduct_id() { return product_id; } public void setProduct_id(int product_id) { this.product_id = product_id; } public String getProduct_name() { return product_name; } public void setProduct_name(String product_name) { this.product_name = product_name; } public int getPrice() { return price; } public void setPrice(int price) { this.price = price; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public String getPicture_url() { return picture_url; } public void setPrcture_url(String picture_url) { this.picture_url = picture_url; } public MultipartFile getFile1() { return file1; } public void setFile1(MultipartFile file1) { this.file1 = file1; } @Override public String toString() { return "ProductDTO [product_id=" + product_id + ", product_name=" + picture_name + ", price=" + price + ", description=" + description + ", prcture_url=" + picture_url + ", file1=" + file1 + "]"; } } | cs |
ProductDAO.java (DAO 인터페이스) | package com.example.spring02.model.shop.dao; import java.util.List; import com.example.spring02.model.shop.dto.ProductDTO; public interface ProductDAO { List<ProductDTO> listProduct(); ProductDTO detailProduct(int product_id); void updateProduct(ProductDTO dto); void deleteProduct(int product_id); void insertProduct(ProductDTO dto); String fileInfo(int product_id); }
| cs |
ProductDAOImpl.java 중 일부 (DAO 인터페이스 구현) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | package com.example.spring02.model.shop.dao; import java.util.List; import javax.inject.Inject; import org.apache.ibatis.session.SqlSession; import org.springframework.stereotype.Repository; import com.example.spring02.model.shop.dto.ProductDTO; @Repository //DB관련 객체를 스프링에서 대신 관리해주게하는 어노테이션 public class ProductDAOImpl implements ProductDAO { @Inject //sqlSession을 의존성을 주입해서 스프링 자체에서 객체를 생성하고 소멸시키게끔 한다. SqlSession sqlSession; @Override public List<ProductDTO> listProduct() { return sqlSession.selectList("product.list_product"); //mapper을 호출하게 한다.
"product.list_product"
product가 namespace의 이름
list_product가 id의 이름
productMapper.xml 파일과 맵핑 된다. (단, 맵핑 되려면 namespace이름과 id의 이름이 같아야함) } | cs |
root-context.xml (실행할 수있는 mapper의 경로가 작성되어 있다.) | <!-- SqlSessionFactory 객체 주입 --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="configLocation" value="classpath:/mybatis-config.xml"></property> <property name="mapperLocations" value="classpath:mappers/**/*Mapper.xml"></property> </bean> | cs |
productMapper.java 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <?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와 중복되지 않도록 네임스페이스 기재 --> <!-- 목록을 뽑아야되므로 select SQL 구문을 추가한다. --> <mapper namespace="product"> <select id = "list_product" resultType = "com.example.spring02.model.shop.dto.ProductDTO"> <!-- 코드의 자료형을 알려준다 DTO타입으로 받아야 되므로 DTO파일의 경로를 입력. --> <!-- 이 코드가 호출되면 ProductDTO가 arraylist로 저장됨 --> select * from product order by product_id <!-- id의 내림차순으로 검색한다. (id의 오름차순으로 검색 - 1,2,3,4,.....10) --> </select> </mapper> | cs |
ProductService.java | package com.example.spring02.service.shop; import java.util.List; import com.example.spring02.model.shop.dto.ProductDTO; public interface ProductService { List<ProductDTO> listProduct(); ProductDTO detailProduct(int product_id); String fileInfo(int product_id); void updateProduct(ProductDTO dto); void deleteProduct(int product_id); void insertProduct(ProductDTO dto); } | cs |
ProductServiceImpl.java 중 일부 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | package com.example.spring02.service.shop; import java.util.List; import javax.inject.Inject; import org.springframework.stereotype.Service; import com.example.spring02.model.shop.dao.ProductDAO; import com.example.spring02.model.shop.dto.ProductDTO; @Service public class ProductServiceImpl implements ProductService { //Service에서는 model(DAO)를 받으므로 의존성을 주입해야한다. @Inject ProductDAO productDao; @Override public List<ProductDTO> listProduct() { return productDao.listProduct(); //데이터베이스에 저장된 상품 리스트를 리턴한다. }
| cs |
ProductController.java 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | package com.example.spring02.controller.shop; import javax.inject.Inject; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; import com.example.spring02.service.shop.ProductService; @Controller //현재 클래스를 스프링에서 관리하는 Controller Bean으로 설정함 @RequestMapping("/shop/product/*") //공통적인 url 맵핑 public class ProductController { @Inject //의존관계 주입 (DI) ProductService productService; //스프링에서 만든 서비스 객체를 연결시킴 @RequestMapping("list.do") //세부적인 url mapping public ModelAndView list(ModelAndView mav) { mav.setViewName("/shop/product_list"); //이동할 페이지 이름 (product_list.jsp 파일로 이동) mav.addObject("list", productService.listProduct()); //데이터 저장 //서비스에서 상품 리스트를 받아와 list라는 이름의 변수에 저장 //service -> model -> mybatis -> 리스트를 받아옴 return mav; //페이지 이동 } } | cs |
menu.jsp (상품목록으로 이동하는 하이퍼링크 추가) | <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix = "c" uri = "http://java.sun.com/jsp/jstl/core" %>
<!-- 다른페이지에 include되는 페이지 -->
<a href = "${path }/memo/list.do">한줄메모장</a> ㅣ <a href = "${path }/upload/uploadForm">업로드 테스트</a> ㅣ <a href = "${path }/shop/product_list.do">상품목록</a> ㅣ
| cs |
product_list.jsp (상품리스트 출력 jsp 파일) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta http-equiv = "Content=Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> <%@ include file = "../include/header.jsp" %> <script>
$(function(){ //자바스크립트 태그안쪽에 $("#btnAdd").click(function(){ location.href = "${path}/shop/product/write.do"; }); });
</script> </head> <body> <%@ include file = "../include/menu.jsp" %> <h2>상품목록</h2> <button type = "button" id = "btnAdd">상품등록</button> <table border = "1" width = "500px"> <tr> <th>상품ID</th> <th>상품사진</th> <th>상품명</th> <th>가격</th> </tr> <c:forEach var="row" items="${list }"> //컨트롤러의 list변수와 같다. <tr align = "center"> <td>${row.product_id }</td> <td><img src="${path }/images/${row.picture_url}" width="100" height = "100"></td> <td>${row.product_name }</td> <td> <fmt:formatNumber value="${row.price}" pattern="#,###" /> </td> <!-- 가격을 표시하기 위해서 사용함. 0이 3개 있을 때마다 ,를 하나씩 찍게 한다. --> </tr> </c:forEach> </table> </body> </html> | cs |
Front-End/javascript 2019. 6. 11. 23:49
-유효범위-
유효범위 (Scope)는 변수의 수명을 의미한다.
-전역변수와 지역변수-
(c언어나 java에서의 의미와 동일)
전역변수
함수 바깥쪽에 선언되어서 모든 함수에서 접근이 가능한 변수
지역변수
함수 안쪽에 선언되어서 그 함수내에서만 사용할 수 있는 변수
|
참고
함수 안쪽에서 변수 앞에 var(데이터타입) 이 붙으면 함수 안쪽에 있으면 지역변수, 함수 바깥쪽에 있으면 전역변수이다.
|
-예제-
|
var a = 'korea';
function f(){
a = 'corea'; //여기서 a는 전역변수인 a를 가리키고 전역변수의 값을 'corea'로 변경
}
f();
alert(a); //위에서 바꾼 a의 값인 'corea'가 출력
|
cs |
|
var a = 'korea';
function f(){
var a = 'corea'; //여기서 a는 지역변수이다.
}
f();
alert(a); //지역변수는 함수내에서만 사용할 수 있고, 전역변수가 선언되어있기 때문에 전역변수 a의 값인 'korea'가 출력
|
cs |
전역변수의 사용
불가피하게 전역변수를 사용해야 하는 경우는 하나의 객체를 전역변수로 만들고 객체의 속성으로 변수를 관리하는 방법을 사용
-예제-
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
function(){
var MYAPP = {} //객체를 생성
MYAPP.calculator = { //객체 안에 들어있는 속성(객체안에 있는 변수) calculator에 객체를 생성하고 left와 right 값을 null로 선언
'left' : null,
'right' : null
}
MYAPP.coordinate = { //객체 안에 들어있는 속성(객체안에 있는 변수) corrdinate에 객체를 생성하고 left와 right 값을 null로 선언
'left' : null,
'right' : null
}
MYAPP.calculator.left = 10; //calculator의 left값을 10으로 설정
MYAPP.calculator.right = 20; //calculator의 right값을 20으로 설정
function sum(){
return MYAPP.calculator.left + MYAPP.calculator.right; //10과 20을 더한값 30을 sum에 리턴
}
document.write(sum()); //30이 출력됨
}
|
cs |
요약 : 위 예제는 전역변수를 함수안에 집어넣고, 전역변수의 객체를 생성해 그 객체안에 새로운 변수를 만들어서 사용하는 예제
-유효범위의 대상 (함수)-
자바스크립트는 함수에 대한 유효범위만을 제공한다.
많은 언어들이 블록 (대체로{ }) 에 대한 유효범위를 제공하는 것과는 다른 점이다.
(즉, 자바에서는 for문 안에서 변수가 선언된것도 지역변수라고 하는데,
자바스크립트에서는 오직 함수내에서만 선언된 변수를 지역변수라고 한다. (for문,while문 등은 포함하지 않는다))
-정적 유효범위-
자바스크립트는 함수가 선언된 시점에서의 유효범위를 갖는다.
이러한 유효범위의 방식을 정적 유효범위 (static scoping), 혹은 렉시컬 (lexical scoping)이라고 한다.
-예제-
|
var i = 5;
function a(){
var i = 10;
b();
}
function b(){
document.write(i);
}
a();
|
cs |
출력값은 전역변수인 i가 출력이 되서 5가 출력된다.
왜냐하면 사용될때가 아니고 정의될때의 전역변수가 사용이 되기때문에 함수 a에 있는 지역변수인 i가 아니라 함수 바깥쪽에 있는 전역변수인 i가 출력이 되는 것이다.
이런범위를 정적 유효범위라 한다.
아래 책은 제가 공부할때 활용했던 책으로 추천드리는 책이니 한번씩 읽어보시는것을 추천드립니다!! ㅎㅎ

이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.
|