20220510 복습

2022 - 0510 - 복습


package com.jslhrd.sample;

import org.springframework.stereotype.Component;

import lombok.Data;

@Component //스프링에게 해당 클래스가 스프링에서 관리해야 하는 대상임을 표시
@Data //Lombok(setter,생성자,toString()등)을 자동 생성하는 어노테이션
public class Chef {
     
}


package com.jslhrd.sample;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import lombok.Data;
import lombok.Setter;

@Component //스프링에게 해당 클래스가 스프링에서 관리해야 하는 대상임을 표시
@Data //Lombok(setter,생성자,toString()등)을 자동 생성하는 어노테이션
public class Restaurant {

     @Setter(onMethod_ = @Autowired) // 의존성
     private Chef chef;
}


package com.jslhrd.sample;

import static org.junit.Assert.assertNotNull;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import lombok.Setter;
import lombok.extern.log4j.Log4j;

@RunWith(SpringJUnit4ClassRunner.class) //현재 테스트 코드가 스프링을 실행하는 역할을 할 것이다.
@ContextConfiguration("file:src/main/webapp/WEB-INF/spring/root-context.xml") //필요한 객체들을 스프링 내에 객체로 등록(Spring's Bean)
@Log4j //Lombok을 이용하여 로그기록하는 Logger를 변수로 생성.
public class SampleTests {

     @Setter(onMethod_ = @Autowired) //@Autowired = 해당 인스턴스 변수가 스프링으로부터 자동으로 주입해 달라는 표시.
     private Restaurant restaurant;

     @Test
     public void testExist() {

          assertNotNull(restaurant); //restaurant변수가 null이 아니어야만 테스트가 성공한다는 뜻.

          log.info(restaurant);
          log.info("------------------");
          log.info(restaurant.getChef());
     }
}


package com.jslhrd.persistence;

import static org.junit.Assert.fail;
import java.sql.Connection;
import java.sql.DriverManager;

import org.junit.Test;

import lombok.extern.log4j.Log4j;

@Log4j
public class JDBCTests {

     static {
          try {
               Class.forName("oracle.jdbc.driver.OracleDriver");
          } catch (Exception e) {
               e.printStackTrace();
          }
     }

     @Test
     public void testConnection() {
          try {
               Connection con = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:XE","system","123456");
               log.info(con);
               log.info("성공");
               Class.forName("oracle.jdbc.driver.OracleDriver");
          } catch (Exception e) {
               log.info("실패");
               e.printStackTrace(); //
               fail(e.getMessage());
          }
     }

}


import static org.junit.Assert.fail;

import java.sql.Connection;

import javax.sql.DataSource;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import lombok.Setter;
import lombok.extern.log4j.Log4j;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("file:src/main/webapp/WEB-INF/spring/root-context.xml")
@Log4j
public class DataSourceTests {

     @Setter(onMethod_ = @Autowired)
     private DataSource ds;

     @Test
     public void testConnection(){

          try(Connection con = ds.getConnection()) {

               log.info(con);
               log.info("success!!!");

          } catch (Exception e) {
               e.printStackTrace();
               fail(e.getMessage());
          }
     }
}


package com.jslhrd.domain;

import java.sql.Date;

import lombok.Data;

@Data
//Lombok(setter,생성자,toString()등)을 자동 생성하는 어노테이션
public class BoardVO {

     private long bno;
     private String title;
     private String content;
     private String writer;
     private Long hit;
     private Date regdate;
     private Date updatedate;
}


package com.jslhrd.mapper;
import java.util.List;
import com.jslhrd.domain.BoardVO;

public interface BoardMapper {

     public List<BoardVO> getList();

     public void insert(BoardVO board);

     public void insertSelectKey(BoardVO board);

     public BoardVO read(Long bno);

     public int update(BoardVO board);

     public int delete(Long bno);

}


package com.jslhrd.mapper;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import com.jslhrd.domain.BoardVO;

import lombok.Setter;
import lombok.extern.log4j.Log4j;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("file:src/main/webapp/WEB-INF/spring/root-context.xml")
@Log4j
public class BoardMapperTests {

     @Setter(onMethod_ = @Autowired)
     private BoardMapper mapper;

     @Test
     public void testGetList() {
          mapper.getList().forEach(board -> log.info(board));
     }

     @Test
     public void testInsert() {
          BoardVO board = new BoardVO();
           board.setTitle("insert");
          board.setContent("insert");
           board.setWriter("insert");
          mapper.insert(board);
           log.info("-------------------insert result-----------------------");
          log.info(board);
          log.info("------------------------------------------");
     }

     @Test
     public void testInsertSelectKey() {
          BoardVO board = new BoardVO();
          board.setTitle("insert K");
          board.setContent("insert K");
          board.setWriter("insert K");
          mapper.insertSelectKey(board);
          log.info("-------------------insert Select Key result-----------------------");
          log.info(board);
          log.info("------------------------------------------");
     }

     @Test
     public void testRead() {
          BoardVO board = mapper.read(16L);
          log.info("-------------------read result-----------------------");
          log.info(board);
          log.info("------------------------------------------");
     }

     @Test
     public void testUpdate() {
          BoardVO board = new BoardVO();
          board.setBno(16L);
          board.setTitle("update");
          board.setContent("update");
          board.setWriter("update");
          log.info("UPDATE RESULT !!! : " + mapper.update(board));

     }
     @Test
     public void testDelete() {
          int count = mapper.delete(31L);
          log.info("DELETE RESULT !!! : "+count);
     }


}


package com.jslhrd.service;
import java.util.List;
import com.jslhrd.domain.BoardVO;
public interface BoardService {

     public List<BoardVO> getList();

     public BoardVO get(Long bno);

     public void insert(BoardVO board);

     public boolean update(BoardVO board);

     public boolean delete(Long bno);

}


package com.jslhrd.service;
import java.util.List;
import org.springframework.stereotype.Service;
import com.jslhrd.domain.BoardVO;
import com.jslhrd.mapper.BoardMapper;
import lombok.AllArgsConstructor;
import lombok.extern.log4j.Log4j;

@Service // 계층 구조상 주로 비즈니스 영역을 담당하는 객체임을 표시하기 위해 사용함.
@Log4j
@AllArgsConstructor // 생성자를 만들고 자동으로 주입함. (생성자를 만들지 않을 경우에는 @setter()를 이용해서 처리함)
public class BoardServiceImpl implements BoardService{

     // @Setter(onMethod_ = @Autowired)
     private BoardMapper mapper;

     @Override
     public List<BoardVO> getList(){
          log.info("GET LIST ----------------------------");
          return mapper.getList();
     }

     @Override
     public BoardVO get(Long bno) {
          log.info("GET : " + bno);
          return mapper.read(bno);
     }

     @Override
     public void insert(BoardVO board) {
          log.info("INSERT : " + board);
          mapper.insertSelectKey(board);
     }

     @Override
     public boolean update(BoardVO board) {
          log.info("UPDATE : " + board);
          return mapper.update(board) == 1;
     }

     @Override
     public boolean delete(Long bno) {
          log.info("DELETE : " + bno);
          return mapper.delete(bno) == 1;
     }

}


package com.jslhrd.service;

import static org.junit.Assert.assertNotNull;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.jslhrd.domain.BoardVO;
import lombok.Setter;
import lombok.extern.log4j.Log4j;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("file:src/main/webapp/WEB-INF/spring/root-context.xml")
@Log4j
public class BoardServiceTests {

     @Setter(onMethod_ = @Autowired)
     private BoardService service;

     @Test
     public void testExist() {
          log.info(service);
          assertNotNull(service);
     }

     @Test
     public void testGetList() {
          service.getList().forEach(board -> log.info(board));
     }

     @Test
     public void testGet() {
          log.info("GET ---------------------------------------");
          log.info(service.get(17L));
     }
     @Test
     public void testInsert() {
          log.info("INSERT --------------------------------------");
          BoardVO board = new BoardVO();
          board.setTitle("insert");
          board.setContent("insert");
          board.setWriter("insert");
          service.insert(board);
     }

     @Test
     public void testUpdate() {
          BoardVO board = service.get(17L);
          if(board == null) {
               return;
          }
          board.setTitle("update");
          board.setContent("update");
          board.setWriter("update");
          log.info("UPDATE RESULT : " + service.update(board));
     }

     @Test
     public void testDelete() {
          log.info("DELETE RESULT : " + service.delete(30L));
     }

}

< Spring 기초 >




>>> pom.xml
12라인 -> 5.0.7
64라인 -> 1.2.17
116라인 -> 4.12
139라인 -> 3.5.1
141라인 -> 1.8
142라인 -> 1.8
-----------------------------------------------------------------------------------------------------
>>> root-context.xml

<bean id="hikariConfig" class="com.zaxxer.hikari.HikariConfig">

     <property name="driverClassName"
          value="net.sf.log4jdbc.sql.jdbcapi.DriverSpy"></property>
     <property name="jdbcUrl"
          value="jdbc:log4jdbc:oracle:thin:@localhost:1521:XE"></property>
     <property name="username" value="db53"></property>
     <property name="password" value="123456"></property>

</bean>

<!-- HikariCP configuration -->
<bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource"
     destroy-method="close">
          <constructor-arg ref="hikariConfig" />
</bean>

<bean id="sqlSessionFactory"
     class="org.mybatis.spring.SqlSessionFactoryBean">
          <property name="dataSource" ref="dataSource">
</bean>

<mybatis-spring:scan
     base-package="com.jslhrd.mapper" />

<context:component-scan
     base-package="com.jslhrd.service">

-----------------------------------------------------------------------------------------------------
>>> buildpath
mysql-connector-java-8.0.28.jar
ojdbc8.jar
-----------------------------------------------------------------------------------------------------
>>>src/main/resources
log4jdbc.log4j2.properties 파일 생성
log4jdbc.spylogdelegator.name=net.sf.log4jdbc.log.slf4j.Slf4jSpyLogDelegator 내용입력
-----------------------------------------------------------------------------------------------------
>>>
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("file:src/main/webapp/WEB-INF/spring/root-context.xml")
@Log4j

@Setter(onMethod_ = @Autowired)
@Select("select sysdate from dual")

@Service
@Log4j
@AllArgsConstructor // 생성자를 만들고 자동으로 주입함.

>>>Tomcat 더블클릭 - Modules - Edit - controller 부분 지우기
-----------------------------------------------------------------------------------------------------
P.173
>>>Oracle 테이블

사용자 추가 후

system/123456

db53/123456


create user db53 identified by 123456;
grant connect,resource to db53;
grant create view to db53;

create sequence seq_board;

create table tbl_board(
bno number(10,0),
title varchar2(200) not null,
content varchar2(2000) not null,
writer varchar2(50) not null,
regdate date default sysdate,
updatedate date default sysdate
);

alter table tbl_board add constraint pk_board primary key(bno);

insert into tbl_board(bno,title,content,writer) values(seq_board.nextval,'테스트 제목','테스트 내용','user00');
insert into tbl_board(bno,title,content,writer) values(seq_board.nextval,'테스트 제목','테스트 내용','user01');
insert into tbl_board(bno,title,content,writer) values(seq_board.nextval,'테스트 제목','테스트 내용','user02');
insert into tbl_board(bno,title,content,writer) values(seq_board.nextval,'테스트 제목','테스트 내용','user03');
insert into tbl_board(bno,title,content,writer) values(seq_board.nextval,'테스트 제목','테스트 내용','user04');
insert into tbl_board(bno,title,content,writer) values(seq_board.nextval,'테스트 제목','테스트 내용','user05');
insert into tbl_board(bno,title,content,writer) values(seq_board.nextval,'테스트 제목','테스트 내용','user06');
insert into tbl_board(bno,title,content,writer) values(seq_board.nextval,'테스트 제목','테스트 내용','user07');
insert into tbl_board(bno,title,content,writer) values(seq_board.nextval,'테스트 제목','테스트 내용','user08');
insert into tbl_board(bno,title,content,writer) values(seq_board.nextval,'테스트 제목','테스트 내용','user09');
insert into tbl_board(bno,title,content,writer) values(seq_board.nextval,'테스트 제목','테스트 내용','user10');

-----------------------------------------------------------------------------------------------------
>>> BoardMapper.xml (@Select 어노테이션을 써도 되지만, 쿼리문이 복잡해질 경우 xml 파일로 관리하는게 유리하다 !!!)

src/main/resources -> com 폴더 -> jslhrd 폴더 -> mapper 폴더 생성 후, 그 안에 BoardMapper.xml 파일 생성
(com.jslhrd.mapper 패키지 명과 동일한 틀로)

<?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="com.jslhrd.mapper.BoardMapper">

     <!-- 부등호 들어가면 CDATA 처리 !!! -->

     <select id="getList" resultType="com.jslhrd.domain.BoardVO">
          <![CDATA[
               select * from tbl_board where bno > 0
          ]]>
     </select>

     <insert id="insert">
          insert into tbl_board(bno,title,content,writer) values(seq_board.nextval, #{title}, #{content}, #{writer})
     </insert>

     <insert id="insertSelectKey">
          <selectKey keyProperty="bno" order="BEFORE" resultType="long">
               select seq_board.nextval from dual
          </selectKey>
          insert into tbl_board(bno,title,content,writer) values(#{bno}, #{title}, #{content}, #{writer})
     </insert>

     <select id="read" resultType="com.jslhrd.domain.BoardVO">
          select * from tbl_board where bno = #{bno}
     </select>

     <update id="update">
          update tbl_board
          set title=#{title},
          content=#{content},
          writer=#{writer},
           updateDate=sysdate
          where bno=#{bno}
     </update>

     <delete id="delete">
          delete from tbl_board where bno=#{bno}
     </delete>

</mapper>

-----------------------------------------------------------------------------------------------------
src/main/resources -> com 폴더 -> jslhrd 폴더 -> mapper 폴더 생성 후, 그 안에 TimeMapper.xml 파일 생성
(com.jslhrd.mapper 패키지 명과 동일한 틀로)

<?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="com.jslhrd.mapper.TimeMapper">
     <select id="getTime2" resultType="string">
          select sysdate from dual
     </select>
</mapper>


https://mvnrepository.com/ <- dependency 검색
https://start.spring.io/ <- Spring Start Page

- 세팅이 반이다 !
- Test 중요 !
- build path (mysql-connector-java-8.0.28.jar , ojdbc8.jar)
- pom.xml 계속 수정

MVC

   (Model View Controller)

   Presentation - Client의 요청을 받아 Business에게 처리를 전달.
   Business - 실제 요청에 대한 처리를 담당. (Service)
   Persistence - Business의 처리에 따라 데이터베이스에 접근. 저장,조회,삭제 등 수행.

root-context.xml


Spring의 컨텍스트

root-context.xml
Spring의 컨텍스트
Restaurant
Chef
Spring의 컨텍스트
Restaurant
Chef

   1. 스프링 프레임워크 시작시 메모리 영역을 만듦. 스프링에서는 ApplicationContext라는 객체가 생성됨.
   2. 스프링은 생성,관리해야 하는 객체들에 대한 설정이 필요. 이를 root-context.xml 파일에서 관리.
   3. root-context.xml에 설정된 <context:component-scan> 태그의 내용을 통해서 패키지를 스캔.
   4. 패캐지의 클래스들 중, 스프링이 사용하는 @Component라는 어노테이션이 존재하는 클래스의 인스턴스를 생성.
   5. Restaurant 객체는 Chef 객체가 필요하다는 @Autowierd 설정이 있으므로,
      스프링은 Chef 객체의 레퍼런스를 Restaurant 객체에 주입 !

Mybatis

   Mybatis - Java의 관계형 Database 프로그래밍을 쉽게 할 수 있도록 도와주는 개발프레임워크.
   ( 복잡한 쿼리에 유리. 유지보수성 향상 )
   ( SQL쿼리들을 한 구성파일에 분리하여 관리하는 장점. )

   JDBC - Java에서 Database에 접속할 수 있도록 하는 API. 쿼리 및 업데이트 수행.

Mybatis with Oracle

   root-context.xml 의 value="net.sf.log4jdbc.sql.jdbcapi.DriverSpy" 사용을 위해서,
   src/main/resources 에 log4jdbc.log4j2.properties 파일을 만들고,
   log4jdbc.spylogdelegator.name=net.sf.log4jdbc.log.slf4j.Slf4jSpyLogDelegator 내용 입력.

   src/main/resource 에 com jslhrd mapper BoardMapper.xml 파일 생성.
   @어노테이션 대신 xml파일을 사용하여 sql문 활용.

   자세한 Oracle 사용법은 본 페이지의 매뉴얼 참조.

상위 폴더 패키지 클래스



src/main/java
com.jslhrd.sample Chef.java
Restaurant.java
com.jslhrd.mapper BoardMapper.java
TimeMapper.java
com.jslhrd.domain BoardVO.java
com.jslhrd.service BoardService.java
BoardServiceImpl.java



src/test/java
com.jslhrd.sample SmapleTests.java

com.jslhrd.persistence
DataSourceTests.java
JDBCTests.java
TimeMapperTests.java
com.jslhrd.mapper BoardMapperTests.java
com.jslhrd.service BoardServiceTests.java

src/main/resources
com/jslhrd/mapper BoardMapper.xml
TimeMapper.xml
. log4jdbc.log4j2.properties

tbl_board
필드명 타입 설명
BNO NUMBER(10) 게시글 번호
TITLE VARCHAR(200) 제목
CONTENT VARCHAR(2000) 내용
WRITER VARCHAR(50) 작성자
HIT NUMBER(10) 조회수
REGDATE DATE 작성일
UPDATEDATE DATE 수정일