n <- scan()
ss <- scan(what ="") # 문자열 입력
df1 <- data.frame()
df1 <- edit(df1) # data frame 수정창 출력
2 파일 읽기
getwd() # 작업경로 확인. setwd()
list.dirs() # 작업경로의 폴더 정보
list.files() # 작업경로의 파일 정보
stud <- read.table(file = "testdata/student1.txt", header = TRUE) #테이블 read. header(defalut : FALSE)
stud1 <- read.table(file = "testdata/student2.txt", header = TRUE, sep =";") #sep : 구분자
stud2 <- read.table(file = "testdata/student3.txt", header = TRUE, sep =" ", na.strings = "-") # na.strings : 해당 값은 NA로 처리
stud3 <- read.csv(file = "testdata/student4.txt", header = TRUE, na.strings = "-") # read.csv : csv 파일 읽기 (csv 구분자 , 로 된 파일)
class(stud3) # data.frame
datas <- read.csv("https://raw.githubusercontent.com/pykwon/Test-datas-for-R/master/agedata.csv") # 웹 data 가져오기
3 출력
- console
x <- 10; y <- 20; z <- x*y
cat(x,y,z)
cat("결과는", z)
print(x)
print(x,y) # 1개만 출력에 참여
4 자료 저장
sink("output/my.txt") # 저장 선언
datas <- read.csv("https://raw.githubusercontent.com/pykwon/Test-datas-for-R/master/agedata.csv")
head(datas,5)
kbs <- 9
kbs
sink() # 저장 작업 종료
#DataFrame 저장
name <- c("관우","장비", "유비")
age <- c(35,33,20)
gender <- c("M","M","F")
myframe <- data.frame(name, age, gender)
myframe
# name age gender
# 1 관우 35 M
# 2 장비 33 M
# 3 유비 20 F
write.table(myframe, "output/my1.txt") #파일저장
write.table(myframe, "output/my2.txt", fileEncoding ="utf-8")
read.table("output/my1.txt") #파일 불러오기
year <- 2021
is.vector(year) # is.vector() : 벡터인지 확인
name <-'tom'
is.vector(name)
year
year[1] # index가 1부터 시작
seq(1,5) # seq() : 수열 생성
1:5
seq(1,10,2) # 1~10까지 2 간격으로 생성.
seq(1,10,length.out = 4) # 1~10까지 간격이 같은 4개의 수열.
rep(1:3, 3) # 1~3까지 3번 반복. 1 2 3 1 2 3 1 2 3
rep(1:3, times=3) # 동일
rep(1:3, each=3) # 1~3까지 각각 반복. 1 2 3 1 2 3 1 2 3
aa <- c(10,20,30,-10,-5)
x<- c(1,3,5)
y<- c(1:3,1:3)
2 이름 설정
age <- c(10,20,30)
names(age) <- c("홍길동", "김길동", "이길동") # names(x) <- : age에 이름을 설정
age[1] # index로 값 호출
age["홍길동"] # 이름으로 값 호출
age[10] <- 50 # 없는 값은 NA
length(age) # 길이는 10
age <- NULL # NULL값 set
3 우선순위
kk <- c(1, 3, FALSE, T, 3.5, 'hi') # 벡터는 값은 데이터 타입을 가지기 때문에 우선순위에 따라 전체 타입이 정해짐
# 우선순위 : 문자열 > 실수 > 정수 > bool
4 벡터 요소 조회(index) : 슬라이싱
v1 <-c(13,-5,20:23, 12, -2:3)
v1 <- append(v1, 60, after=5) # v1벡터의 5번째 인자 이후에 60이 들어간다.
v1[1] # 첫번째 값. index 1부터 시작
v1[c(1, 3, 6)] # 1, 3, 6 인덱스 값
v1[1:5] # 1~5 인덱스 값
v1[c(3, 5, 1, 8, 9)]
v1[-1] # 1번째 요소를 제외한 나머지를 반환
v1[-c(1, 3, 5)] # 1, 3, 5번째 요소를 제외한 나머지
5 연산
# 하나의 벡터 연산
a <-1:5
a + 5 # 각 요소에 연산적용
a ^ 2 # 제곱
a ** 2 # 제곱
sqrt(a) # 제곱근
sqrt(a) ** 2 # a
# 두 개의 벡터 연산
a <- 1:3
b <- 4:6
a + b # 각 index끼리 연산
a * b
a + 10
a[4] <-2
b[4] <-2
m2[1,] # 1행 전체
m2[,1] # 1열 전체
m2[2,3] # 2행 3열
m2[2,2:4] # 2행 2,3,4열
3 이름 설정
m2 <- matrix(1:12, 3)
colnames(m2) <- c("a", "b", "c", "d")
rownames(m2) <- c("r1", "r2", "r3")
# a b c d
# r1 1 4 7 10
# r2 2 5 8 11
# r3 3 6 9 12
4 연산
a <- matrix(c(1,2,3,4),2,2)
b <- matrix(5:8, 2)
a + b
a - b
a * b
a %*% b # 행렬 곱(내적)
diag(a) # 행, 열 인덱스가 같은 라인의 요소
diag(2)
# 1 0
# 0 1
solve(a) # 역행렬
solve(solve(a))
a %*% solve(a) %*% a
4. List : 서로 다른 타입의 자료를 기억 가능. java의 레코드형 기억장소. c: 구조체.
li <- list('1', '이순신', 70, '2', '한송이', 80)
class(li) # list
unli <- unlist(li) # list에서 되돌리기
num <- list(1:5, 6:10, c("a", "b", "c")) # 1, 2, 3 key에 값을 넣는다.
num[1]; print(class(num[1])) # list
num[[1]]; print(class(num[[1]])) # integer
num[[1]][2] # 1번 list의 index 2번의 값
num2 <- list(x=1:5, y=6:10) # x, y key에 값을 넣는다.
num2$x # num list의 x key의 데이터
num2$y
mem <- list(name='tom', age=22) # name, age key에 값을 넣는다.
a<-list(c(1:5)) # 1~5
b <- list(6:10) # 6~10
result <- lapply(c(a,b), max) # 결과 값을 list로 반환
# [[1]]
# [1] 5
#
# [[2]]
# [1] 10
5. DataFrame : DB의 테이블 구조와 유사. - vetor로 DataFrame 생성
no <- c(1,2,3)
name <- c("tom", "james", "jonh")
pay <- c(300, 400, 500)
df <- data.frame(bunho = no, irum = name, imkum = pay)
#bunho irum imkum
#1 1 tom 300
#2 2 james 400
#3 3 jonh 500
class(df) # data.frame
df[1:2]
df[c(1,3)]
df[2,2]
df[-1,]
df[,-1]
df <- data.frame(irum = c('aa', 'bb', 'cc'), nai = c(22,25,33), row.names = c("one","two", "three"))
df
nrow(df) # 행 수
ncol(df) # 열 수
str(df) # 구조
names(df) # 이름 확인
head(df, n=2) # 앞의 2개 데이터 출력
tail(df, n=2) # 뒤의 2개 데이터 출력
편집 - 전부 실행하기 ctrl + Enter : 한줄 실행 코드 블록 잡기 + ctrl + Enter : 일부분 실행 ctrl + alt + R : 전체실행
ctrl + l : console창 비우기
ctrl + shift + c : 블록영역 주석처리
# : 주석
② 변수 : R에서는 모든 참조형 변수를 사용한다.
- 대입
a <- 1
a=2
3->a
a.kor<-4; # 가능 하나 지양
a_kor<-4
- 출력
cat(a)
cat(a, a.kor) # cat() : 복수의 데이터
print(a, a.kor) # print() : 하나만 출력 - a만 출력
a
(a)
- 변수유형
k <- 9 # 숫자는 기본 double
object.size(k) # object.size() : 객체 크기 - 56 bytes
typeof(k) # typeof() : 타입 - double
k <- as.integer(k) # as.integer() : integer로 type으로 변경
typeof(k)
s <- 5L # L은 정수형 리터럴
typeof(s) # integer
ss <- 'tom' # 문자형
typeof(ss) # character
bb<-TRUE # 논리형 - T
typeof(bb) # logical
- NA, NaN, NULL
aa <- NA # 결측값 : 값으로 인식은 하나 값 자체는 없음.
typeof(aa) # logical
is.na(aa) # is.na() : na 인지 판단.
bb <- NaN # 값으로 인식은 하나 수학적으로 정의되지 않음.
typeof(bb) # double
0 * Inf # NaN
Inf + -Inf # NaN
cc <- NULL # 값으로 인식하지 않음.
typeof(cc) # NULL
sum(2, 3) # 5
sum(2, 3, NULL) # 5
sum(2, 3, NA) # NA
sum(2, 3, NaN) # NaN
- 벡터, factor
ff <-c(2,2,3,2,4) # c() : 벡터 생성.
ff # [1] 2 2 3 2 4
str(ff) # str() : data 구조 확인 num [1:5] 2 2 3 2 4
ff<-factor(ff) # factor() : 범주형 데이터 생성 (레벨을 가지는 배열)
str(ff) # Factor w/ 3 levels "2","3","4": 1 1 2 1 3
# 2,3,4의 레벨을 가지며, 각요소의 레벨 index를 인자로 가진다.
- 함수
func <- function(){ # 함수 생성
return ('good')
}
func() # 함수 호출
typeof(func) # "closure"8
- 데이터 정보 확인
k <-9
cat(k, typeof(k), class(k), mode(k)) # 9 double numeric numeric
# mode() : old type 확인.
# class() : class 확인
str(k) # num 9
is(k) # [1] "numeric" "vector"
- 메모리 clear
ls() # ls() : 메모리에 있는 객체 리턴
ls.str()
rm(kbs) # rm() : 메모리 제거
rm(list=ls()) # 모든 변수 메모리 제거
gc() # 가비지 컬렉터. 점유된 메모리 제거.
- pakage : data + 기능 + 알고리즘 꾸러미 : 라이브러리
available.packages() # available.packages() : 사용 가능한 pakage 목록 확인.
dim(available.packages()) # dim() : 객체의 차원수 확인
# R에서 제공하는 라이브러리 수 확인 (16969)
length(installed.packages()) # installed.packages() : 설치된 package 리스트 .
# 설치된 라이브러 수 확인 (480)
install.packages("plyr") # install.packages() : 라이브러리 설치
library(plyr) # library() : 라이브러리를 load. (import)
# plyr : 연습용 데이터 라이브러리
data(package='plyr') # data(package='') : 라이브러리 데이터 확인.
baseball # plyr column
ozone # plyr column
remove.packages("plyr") # remove.packages() : 라이브러리 삭제
- 데이터 확인
data()
Nile # 나일강의 데이터를 제공하는 라이브러리
head(Nile) # 첫 데이터
tail(Nile) # 마지막 데이터
hist(Nile) # 히스토그램 출력
density(Nile) # 밀도
plot(density(Nile))
- 기타
help("mean") # 도움말
x <- c(0:10, 50)
xm <- mean(x) # 표본평군
c(xm, mean(x, trim = 0.10)) # mean(x, trim = 0.1) : 절사평균. x의 데이터를 크기 순
# 나열 후 0 ~ 0.5의 trim 값에 따라 앞/뒤를 제거 후 평균을 구한다.
<configuration>
<typeAliases>
<typeAlias type="pack.model.JikwonDto" alias="dto"/>
</typeAliases>
<!-- DB 연결을 root-context.xml에서 하도록 수정.-->
<mappers>
<mapper resource="pack/mybatis/DataMapper.xml" />
</mappers>
</configuration>
- DataMapper(xml)
<mapper namespace="dev">
<select id="selectJikwonAll" resultType="dto">
select jikwon_no, jikwon_name, jikwon_jik, jikwon_gen, buser_name
from jikwon left outer join buser
on jikwon.buser_num = buser.buser_no
</select>
<select id="selectLoginData" resultType="dto" parameterType="string">
select jikwon_no, jikwon_name
from jikwon
where jikwon_no=#{no}
</select>
</mapper>
- MyDataSource
public class MyDataSource extends DriverManagerDataSource {
public MyDataSource() {
setDriverClassName("org.mariadb.jdbc.Driver");
setUrl("jdbc:mysql://127.0.0.1:3306/test");
setUsername("root");
setPassword("123");
}
}
<body>
<h2>스프링으로 xml 형태의 결과 반환연습</h2>
<a href="member">출발</a><br>
</body>
=> 요청명 member 전달.(GET방식)
- myform.jsp
<body>
<h2>자료입력</h2>
<form action="member" method="post">
name : <input type="text" name="name" value="tom"><br>
age : <input type="text" name="age" value="22"><br>
<input type="submit">
</form>
<hr>
<form action="member_xml" method="post">
name : <input type="text" name="name" value="tom"><br>
age : <input type="text" name="age" value="22"><br>
<input type="submit">
</form>
</body>
=> 상기 <form>태그 요청명 member 전달.(POST방식)
=> 하기 <form>태그요청명 member_xml 전달.(POST방식)
- MemberController
@Controller
public class MemberController {
@RequestMapping(value="member", method = RequestMethod.GET)
public String formBack() {
return "myform";
}
@RequestMapping(value="member", method = RequestMethod.POST)
@ResponseBody // 자바객체를 Http 응답객체로 클라이언트에 전송 가능.
public String submit(@RequestBody String formData) {
// @RequestBody는 요청 몸체(body)에 있는 client의 요청 값을 그대로 받아들임.
System.out.println("formData : "+formData); // name=tom&age=22
formData+="hello";
return formData; // @ResponseBody 사용 시 formData가 가진 값을 클라이언트에게 바로 송신.
}
...
}
=> @RequestBody : 요청의 Boby 값을 변수에 대입. ex) name=tom&age=22
@Controller
public class MemberController {
...
@RequestMapping(value="member_xml", method = RequestMethod.POST)
@ResponseBody
public XmlMessageList submit_xml(@RequestParam("name") String name,
@RequestParam("age") String age) {
System.out.println(name+" "+age);
return getXml(name, age);
}
public XmlMessageList getXml(String name, String age) {
List<XmlMessage> messages = Arrays.asList(
new XmlMessage(name, age),
new XmlMessage("oscar", "25"),
new XmlMessage("emma", "24")
);
return new XmlMessageList(messages);
}
}
=> 요청명 member_xml(Post방식) 일 경우 실행.
=> @ResponseBody : getXml()의 리턴값을 클라이언트에서 출력한다.
=>
- XmlMessage
@XmlAccessorType(XmlAccessType.FIELD)
//@XmlType(name="", propOrder = {"name","age"})
public class XmlMessage {
private String name;
private String age;
public XmlMessage() {
}
public XmlMessage(String name, String age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public void setName(String name) {
this.name = name;
}
}
- XmlMessageList
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "msg-list") // Root Element 이름 지정
public class XmlMessageList {
@XmlElement(name = "msg")
private List<XmlMessage> messages;
public XmlMessageList() {
}
public XmlMessageList(List<XmlMessage> messages) {
this.messages = messages;
}
public List<XmlMessage> getMessages(){
return messages;
}
}
@Controller
public class SangpumController {
@Autowired
private DataDao dataDao;
@RequestMapping("sangpum")
@ResponseBody // Body를 통채로 송부한다.
public Map<String, Object> abc(){ // JSON은 Map을 리턴해야한다.
List<Map<String, String>> dataList = new ArrayList<Map<String, String>>();
Map<String, String> data = null;
List<SangpumDto> sangList = dataDao.sangpumList(); // DB에서 데이터를 받아온다.
for(SangpumDto s : sangList) {
data = new HashMap<String, String>();
data.put("code", s.getCode()); // key, value 형식으로 DB값을 담는다.
data.put("sang", s.getSang());
data.put("su", s.getSu());
data.put("dan", s.getDan());
dataList.add(data); // List에 Record 값을 넣는다.
}
Map<String, Object> sangpumDatas = new HashMap<String, Object>();
sangpumDatas.put("datas", dataList); // Map에 List를 담아 전송한다.
return sangpumDatas; // JSON은 Map을 리턴해야한다.
}
}
- DataDao
@Repository
public class DataDao extends SqlSessionDaoSupport{
public DataDao(SqlSessionFactory factory) {
setSqlSessionFactory(factory);
}
public List<SangpumDto> sangpumList(){
List<SangpumDto> list = getSqlSession().selectList("selectAll");
return list;
}
}
- SangpumDto
public class SangpumDto {
private String code, sang, su, dan;
//getter/setter
}
@Controller
public class ListController {
@Autowired
private BoardDaoInter boardInter;
private int tot; // 전체 레코드 수
private int plist=5; // 한 페이지 당 행의 수
private int pageCount; // 전체 페이지 수
public ArrayList<BoardDto> getListData(ArrayList<BoardDto> list, int page){
ArrayList<BoardDto> result = new ArrayList<BoardDto>();
int start = (page - 1)*plist; // 해당 페이지의 첫 게시물의 index
int size = plist <= list.size() - start ? plist : list.size() - start;
// 한 페이지에 표시할 데이터가 5개 이하일 경우엔 size가 그 수에 따르도록 조건처리.
for(int i=0; i<size;i++) { // list에 한 페이지당 표시할 데이터만 담아 리턴한다.
result.add(i, list.get(start + i));
}
return result;
}
public int getPageCount() { // get 페이지 수
pageCount = tot/plist;
if(tot%plist > 0 ) pageCount+=1;
return pageCount;
}
@RequestMapping("list")
public Model process(Model model, @RequestParam("page") int page) {
tot = boardInter.totalCnt();
ArrayList<BoardDto> list = boardInter.getList();
ArrayList<BoardDto> result = getListData(list, page);
model.addAttribute("data",result);
model.addAttribute("pageCount",getPageCount());
model.addAttribute("page",page);
//model.addAttribute("data",list); // 페이징 없이 작업할 경우
return model;
}
}
=> totalCnt() :
=> getList() : 전체 List 검색하여 list 리턴.
=> getListData() : 전체 리스트에서 한 페이지 당 표시할 데이터만 리턴값으로 가진다.
=> plist : 한 페이지 당 표시할 레코드 수를 설정.
=> getPageCount() : 페이지의 개수를 리턴.
- BoardBean
public class BoardBean {
private String name,pass,mail,title,cont,bip,bdate;
private int num,readcnt,gnum,onum,nested;
private String searchName, searchValue;
//getter/setter
}
=> FormBean 작성.
- BoardDto
public class BoardDto {
private String name,pass,mail,title,cont,bip,bdate;
private int num,readcnt,gnum,onum,nested;
//getter/setter
}
@Repository
public class BoardDaoImpl extends SqlSessionDaoSupport implements BoardDaoInter {
@Autowired
public BoardDaoImpl(SqlSessionFactory factory) {
setSqlSessionFactory(factory);
}
@Override
public ArrayList<BoardDto> getList() {
return (ArrayList)getSqlSession().selectList("selectList");
}
@Override
public int totalCnt() {
return getSqlSession().selectOne("totalCnt");
}
...
}
=> getList() : board 테이블의 모든 정보 list 리턴.
=> totalCnt() : 레코드 수를 리턴.
<!-- 전체 검색 -->
<select id="selectList" resultType="dto">
select * from board order by gnum desc, onum asc
</select>
<select id="totalCnt" resultType="integer">
select count(*) from board
</select>
=> location.href : 목록버튼 누를 경우 list 출력 창 1 page로 이동.
focus() : 커서가 해당 창으로 이동.
submit() : submit 동작 진행.
- InsertController
@Controller
public class InsertController {
@Autowired
private BoardDaoInter boardInter;
...
@RequestMapping(value="insert", method = RequestMethod.POST)
public String submit(BoardBean bean) {
bean.setBdate();
int newNum = boardInter.currentNum() + 1; // 새로 작성된 글의 번호
bean.setNum(newNum);
bean.setGnum(newNum);
boolean b= boardInter.insert(bean);
if(b) {
return "redirect:/list?page=1";
}else {
return "redirect:/error";
}
}
}
=> POST방식 요청명 insert 받을 경우 실행.
=> <form>태그 데이터 FormBean에 set.
=> setBdate() : Calendar객체를 이용하여 오늘 날짜를 set한다.
=> currentNum() : 현재 테이블의 num값중 가장 큰 값을 받아와 +1하여 현재 num가 group num 값을 set한다.
=> insert() : data 추가.
=> insert 성공 시 전체 list 페이지로 이동, 실패 error 페이지로 이동.
public void setBdate() {
Calendar cal = Calendar.getInstance();
int year = cal.get(Calendar.YEAR);
int month = cal.get(Calendar.MONTH) + 1;
int day = cal.get(Calendar.DATE);
this.bdate = year + "-" + month + "-" + day;
}
- BoardDaoImpl
@Repository
public class BoardDaoImpl extends SqlSessionDaoSupport implements BoardDaoInter {
@Autowired
public BoardDaoImpl(SqlSessionFactory factory) {
setSqlSessionFactory(factory);
}
...
@Override
public boolean insert(BoardBean bean) {
int result = getSqlSession().insert("insertData",bean);
if(result>0) {
return true;
}else {
return false;
}
}
...
@Override
public int currentNum() {
//insert시 번호 자동 증가를 위해 현재 레코드 중 가장 큰 번호 얻기.
if(getSqlSession().selectOne("currentNum") == null) {
return 0;
}else {
return getSqlSession().selectOne("currentNum");
}
}
...
}
=> insert() : insert에 성공 시 true, 실패 시 false 리턴.
=> currentNum() : 레코드가 없을 경우 현재 가장 큰 num값을 0으로 리턴.
...
<!-- 추가 -->
<insert id="insertData" parameterType="formBean">
insert into board
values(#{num},#{name},#{pass},#{mail},#{title},#{cont},
#{bip},#{bdate},0,#{gnum},0,0)
</insert>
...
<!-- maxnum -->
<select id="currentNum" resultType="integer">
select max(num) from board
</select>
...
=> Data insert
=> board테이블의 num중 가장 큰 값 리턴.
- ErrorController
@Controller
public class ErrorController {
@RequestMapping("error")
public String err() {
return "error";
}
}
@Controller
public class SearchController {
@Autowired
private BoardDaoInter inter;
@RequestMapping("search")
public ModelAndView searchProcess(BoardBean bean) {
ArrayList<BoardDto> list = inter.getSearch(bean);
ModelAndView view = new ModelAndView("list", "data", list);
view.addObject("page","1");
return view;
}
}
=> list.jsp에서 검색 버튼을 누를 경우 searchName(key), searchValue(key)가 전달된다.
=> getSearch() : searchName(key), searchValue(key)에 맞는 값을 검색하여 리스트로 출력한다.
=> 리턴 값을 list.jsp에 출력.
- BoardDaoImpl
@Repository
public class BoardDaoImpl extends SqlSessionDaoSupport implements BoardDaoInter {
@Autowired
public BoardDaoImpl(SqlSessionFactory factory) {
setSqlSessionFactory(factory);
}
...
@Override
public ArrayList<BoardDto> getSearch(BoardBean bean) {
return (ArrayList)getSqlSession().selectList("searchList", bean);
}
...
}
=> getSearch() : 검색 후 ArrayList 리턴.
- DataMapper.xml
...
<!-- 카워드 검색 -->
<select id="searchList" parameterType="formBean" resultType="dto">
select * from board
where ${searchName} like concat('%',#{searchValue},'%')
order by gnum desc, onum asc
</select>
...
=> searchName의 Column에서 searchValue의 키워드가 있을 경우 리스트를 리턴한다.
@Controller
public class DetailController {
@Autowired
private BoardDaoInter inter;
@RequestMapping("detail")
public ModelAndView detailProcess(@RequestParam("num") String num,
@RequestParam("page") String page) {
// 조회수 증가 작업 선행
boolean b = inter.updateReadcnt(num);
// 상세보기 진행 후 jsp로 출력
ModelAndView view = new ModelAndView("detail");
view.addObject("data", inter.getDetail(num));
view.addObject("page", page);
return view;
}
}
=> list.jsp에서 제목을 누를 경우 요청명 detail로 num과 page 값을 전달받는다.
=> @RequestParam : request.getParameter()와 동일.
=> updateReadcnt() : 조회수를 +1한다.
=> getDetail() : 해당 num의 한 레코드 값을 리턴하여 detail.jsp 실행.
-BoardDaoImpl
@Repository
public class BoardDaoImpl extends SqlSessionDaoSupport implements BoardDaoInter {
@Autowired
public BoardDaoImpl(SqlSessionFactory factory) {
setSqlSessionFactory(factory);
}
...
@Override
public BoardDto getDetail(String num) {
// 글 내용보기, 글 수정 시 데이터 받아오기
return getSqlSession().selectOne("selectOne",num);
}
...
@Override
public boolean updateReadcnt(String num) {
//상세보기 전 조회수 증가
int result = getSqlSession().update("updateReadcnt",num);
if(result>0) {
return true;
}else {
return false;
}
}
...
}
=> getDetail() : 게시글의 내용을 받아온다.
=> updateReadcnt() : 업데이트 성공시 true, 실패 시 false 리턴
- DataMapper.xml
...
<!-- 번호로 검색 -->
<select id="selectOne" parameterType="string" resultType="dto">
select * from board where num=#{num}
</select>
...
<!-- readcnt -->
<update id="updateReadcnt" parameterType="string">
update board set readcnt=readcnt + 1
where num=#{num}
</update>
...
<mapper namespace="dev">
<select id="selectAll" resultType="dto">
select num, name, addr from mem
</select>
<select id="selectPart" parameterType="String" resultType="dto">
select num, name, addr from mem
where num=#{num}
</select>
<insert id="insertData" parameterType="formBean">
insert into mem values(#{num}, #{name}, #{addr})
</insert>
<update id="updateData" parameterType="formBean">
update mem set name=#{name}, addr=#{addr}
where num=#{num}
</update>
<delete id="deleteData" parameterType="String">
delete from mem where num=#{num}
</delete>
</mapper>
=> Login에 성공할 경우 redirect로 클라이언트에서 요청을 실행한 것과 같이 실행하여야한다. (forward를 사용하지
않음). Redirect로 list.jsp를 실행한다.
- LoginForm
@Component
public class LoginForm {
private String userid; // <form>태그의 name속성값과 동일하게 변수를 가진다.
private String passwd;
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;
}
}
=> <form>태그의 name속성값과 동일하게 변수를 가지도록 작성한다. FormBean은 client의 요청을 처리할 때 사용
한다. DTO는 DB 자료를 처리할 때 사용. (용도에 따라 관례적으로 FormBean과 DTO를 사용한다)
- ListController
@Controller
public class ListController {
@RequestMapping("list")
public ModelAndView aaa() {
ModelAndView view = new ModelAndView("list");
view.addObject("msg", "로그인 성공으로 하고 뭔가를 출력함");
return view;
}
}
@Controller // 클라이언트로 부터 요청 받을 경우 동작
public class ListController {
@Autowired
private DataDao dataDao;
@RequestMapping("testdb") // url mapping
public ModelAndView listProcess() {
ArrayList<SangpumDto> list = dataDao.getDataAll();
return new ModelAndView("list", "datas", list); // list.jsp에 연결.
}
}
=> @Controller : 클라이언트로 부터 요청 받을 경우 동작.
@Autowired : setter injection 기능 수행.
@RequestMapping("url명") : url명과 동일한 url을 받을 경우 실행.
dataDao의 getDataAll()를 실행한 list값을 "datas" key에 넣어 실행한다.
- SangpumDto
public class SangpumDto {
private String code, sang, su, dan;
//getter/setter
}
@Controller // 클라이언트로 부터 요청 받을 경우 동작
public class ListController {
@Autowired
private DataDao dataDao;
@RequestMapping("testdb") // url mapping
public ModelAndView listProcess() {
ArrayList<SangpumDto> list = dataDao.getDataAll();
return new ModelAndView("list", "datas", list); // list.jsp에 연결.
}
}
=> DataSource와 동일
- SangpumDto
public class SangpumDto {
private String code, sang, su, dan;
//getter/setter
}
=> DataSource와 동일
- DataSourceMaria
@Repository() // DB연동
//@Repository("dataSource")
public class DataSourceMaria extends DriverManagerDataSource{
public DataSourceMaria() {
setDriverClassName("org.mariadb.jdbc.Driver");
setUrl("jdbc:mysql://127.0.0.1:3306/test");
setUsername("root");
setPassword("123");
}
}
=> DataSource와 동일
- DataDao
@Repository // DB 연결.
public class DataDao extends JdbcDaoSupport{
//@Autowired
//private DataSourceMaria dataSourceMaria; // DataDao에 주입됨.
//DataSource를 JdbcDaoSupport가 가지고 있으로 생성자를 이용한다.
public DataDao(DriverManagerDataSource dataSource) {
setDataSource(dataSource);
}
public List<SangpumDto> getDataAll(){
String sql="select * from sangdata";
return getJdbcTemplate().query(sql, new ItemRowMapper());
}
class ItemRowMapper implements RowMapper{
@Override
public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
SangpumDto dto = new SangpumDto();
dto.setCode(rs.getString("code"));
dto.setSang(rs.getString("sang"));
dto.setSu(rs.getString("su"));
dto.setDan(rs.getString("dan"));
return dto;
}
}
}
=> extends JdbcDaoSupport : JdbcDaoSupport 상속 받아 기능을 수행한다.
=> @Autowird를 사용하면 DataDao객체에 dataSource가 setter injection됨으로 해당 기능이 정상동작하지않는다.
정상동작을 위해선 상속을 받고있는 JdbcDaoSupport객체에 setter injection을 하여야한다. 생성자를 이용하여
DataDao객체가 생성되면 setDataSource()가 실행되도록 하여 JdbcDaoSupport객체에 dataSource를 setter
=> 공유자원을 관리하는 root-context.xml에서 DB연결을 하도록, Sql문 mapping하는 DataMapper.xml관련 설정을
제외하고 삭제.
=> DataMapper파일과 alias를 정의한다.
- DataMapper.xml
<mapper namespace="dev">
<select id="selectAll" resultType="dto">
select * from sangdata
</select>
<select id="selectSearch" parameterType="formBean" resultType="dto">
select code, sang, su, dan from sangdata
where sang like concat('%',#{searchValue},'%')
</select>
</mapper>
=> sql문과 연결되는 Mapper 파일을 작성한다.(<mapper>태그 내부에 sql문을 형식에 맞춰 작성)
=> <select> : select문 작성 시 사용되는 태그. (id속성 - 외부에서 호출할 이름 / resultType - sql문을 실행한 결과
Type / parameterType속성 - 외부로 부터 받을 매개변수의 타입, #{변수명}에 매개변수가 대입된다.)
=> like concat('%', 검색어, '%') : 검색어가 포함된 결과 반환. ( like %검색어%)
@Controller
//@ComponentScan("pack.model")
public class ListController {
@Autowired // setter injection
private SangpumInter sangpumInter; // 다형성 사용
@RequestMapping("list")
public Model process(Model model){
model.addAttribute("data", sangpumInter.list());
// Model객체는 addAttribe(key, value) 메소드를 사용하여 값을 전달.
return model; // 받은 요청명 그대로 송부한다.
}
}
=> @Controller : Controller 기능 수행 (servlet 동작)
=> "list" url 받을 경우 동작한다. list()메소드를 실행한 결과를 "data" key에 넣어 list.jsp에 리턴한다.
- SangpumDto
public class SangpumDto {
private String code,sang, su, dan;
//setter, getter
}
=> DB연동에 사용되는 데이터는 Dto로 작성.(select)
- SangpumBean
public class SangpumBean {
// formBean : 수정, 삭제 등의 작업이 있다면 code, sang, su, dan도 처리
// 검색용
private String searchValue;
public String getSearchValue() {
return searchValue;
}
public void setSearchValue(String searchValue) {
this.searchValue = searchValue;
}
}
@Controller
//@ComponentScan("pack.model")
public class ListController {
@Autowired // setter injection
private SangpumInter sangpumInter; // 다형성 사용
@RequestMapping("list")
public Model process(Model model){
model.addAttribute("data", sangpumInter.list());
// Model객체는 addAttribe(key, value) 메소드를 사용하여 값을 전달.
return model; // 받은 요청명 그대로 송부한다.
}
}
=> xml방식과 동일
- SangpumDto
public class SangpumDto {
private String code,sang, su, dan;
//setter, getter
}
=> xml방식과 동일
- SangpumBean
public class SangpumBean {
// formBean : 수정, 삭제 등의 작업이 있다면 code, sang, su, dan도 처리
// 검색용
private String searchValue;
public String getSearchValue() {
return searchValue;
}
public void setSearchValue(String searchValue) {
this.searchValue = searchValue;
}
}
// MyBatis SQL mapping interface file
public interface SangpumAnnoInter {
@Select("select * from sangdata")
public List<SangpumDto> selectAllData();
@Select(" select code, sang, su, dan from sangdata where sang like concat('%',#{searchValue},'%')")
public List<SangpumDto> selectSearch(SangpumBean bean);
}