[Spring Boot] Spring Boot와 Mybatis 기본 구조

고운·2023년 5월 23일
0

Spring Boot

목록 보기
1/13
post-custom-banner

MVC: Model-View-Controller

Model: 데이터를 실어 보내는 역할

View: 페이지 표시

Controller: 제어

프로젝트 만들기

new-> Spring starter project
Type: Maven, Packaging: War or jar
Lombok, MyBatis Framework, Oracle Driver, Spring Web 체크 (처음에는 검색해야 함) =>jar를 일일히 다운받아서 lib 폴더에 복사하지 않아도 된다.

application.properties 설정

spring.datasource.driver-class-name=oracle.jdbc.driver.OracleDriver
spring.datasource.url=jdbc:oracle:thin:@localhost:1521:XE
spring.datasource.data-username=c##madang
spring.datasource.data-password=madang

server.port=8088 //포트번호는 디폴트가 8080
server.session.timeout=36000

spring.mvc.view.prefix=/WEB-INF/views/    //view name 쓸 때 경로를 직접 타이핑하지 않아도 되게 prefix를 설정
spring.mvc.view.suffix=.jsp   //view name 쓸 때 jsp를 타이핑하지 않아도 되게 suffix를 설정

가동

[프로젝트이름]Application.java : 서버 실행을 위한 메인. 여기서 실행 단추를 눌러서 서버를 실행한다.
서버 가동 후 localhost:(포트번호)로 들어가면 됨

포트번호는 기본 8080. 혹은 지정한 포트번호

com.example.demo 패키지 안에 들어있어야 어노테이션 자동 스캔이 된다. 자동 스캔을 위해서 demo 아래에 패키지들을 만들어 준다.

DB 데이터 이동 경로:
BoardMapper -> DBManager -> BoardDAO -> BoardController

패키지 이름은 소문자로

db:DB 관련 클래스나 파일들. dao:DAO. vo:VO. controller: Controller.

mybatis 홈페이지: https://mybatis.org/mybatis-3/
-> Getting started 가면 필요한 코드 example들이 있음

Mapper

sql문을 정의하는 xml
Mybatis 홈페이지에 있는 example(아래)을 수정해서 사용

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.mybatis.example.BlogMapper">
  <select id="selectBlog" resultType="Blog">
    select * from Blog where id = #{id}
  </select>
</mapper>

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="customer">
  <select id="findAll" resultType="customerVO">
    select * from customer
  </select>
  <select id="findByCustid" resultType="customerVO">
  	select * from customer where custid=#{custid}
  </select>
  <insert id="insert" parameterType="customerVO">
  	insert into customer(custid,name,address,phone) values(#{custid},#{name},#{address},#{phone})
  </insert>
  <update id="update" parameterType="customerVO">
  	update customer set name=#{name}, address=#{address}, phone=#{phone} where custid=#{custid}
  </update>
  <delete id="delete">
  	delete customer where custid=#{custid}
  </delete>
</mapper>

namespace: 해당 mapper의 이름 지정

<select id="" resultType="" parameterType=""></select>

id: 기능 이름을 지정 ex)findAll, findById, update, insert, ...
resultType: 리턴하는 값의 타입. (select할 때 써 준다. ResultSet에 내용이 담기는 것과 비슷함)
parameterType: 매개변수로 입력하는 값의 타입.

칼럼 이름을 변수로 지정할 경우 ${변수} (# 아님!!) (예: order by ${칼럼이름})

db.properties

driver=oracle.jdbc.driver.OracleDriver
url=jdbc:oracle:thin:@localhost:1521:XE
username=c##madang
password=madang

SqlMapConfig

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
	<properties resource="com/example/demo/db/db.properties"/>
	<typeAliases>
		<typeAlias type="com.example.demo.vo.BookVO" alias="bookVO"/>  //별칭 설정
	</typeAliases>
  <environments default="development">
    <environment id="development">
      <transactionManager type="JDBC"/>
      <dataSource type="POOLED">
        <property name="driver" value="${driver}"/>  //db.properties의 변수들이 들어감
        <property name="url" value="${url}"/>
        <property name="username" value="${username}"/>
        <property name="password" value="${password}"/>
      </dataSource>
    </environment>
  </environments>
  <mappers>
    <mapper resource="com/example/demo/db/BookMapper.xml"/>  // 만든 Mapper 경로를 써 줌
  </mappers>
</configuration>
  • Alias 설정 하지 않을 경우 Mapper 파일에서 vo 사용시 com.example.demo.vo.BookVO 처럼 패키지명까지 다 써야 한다.

DBManager

public class DBManager {
	public static SqlSessionFactory sqlSessionFactory;
	static {
		String resource = "com/example/demo/db/sqlMapConfig.xml";
		InputStream inputStream;
		try {
			inputStream = Resources.getResourceAsStream(resource);
			sqlSessionFactory =
					new SqlSessionFactoryBuilder().build(inputStream);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	public static List<BookVO> findAll(){
		List<BookVO> list=null;  //빈 리스트를 생성
		SqlSession session=sqlSessionFactory.openSession();  //sqlSessionFactory를 통해 SqlSession 객체 생성
		list=session.selectList("book.findAll");   // BookMapper에 있는 id가 findAll인 메소드를 호출
		session.close();
		return list;
	}
}
public static List<CustomerVO> findAll(){
		List<CustomerVO> list=null;
		SqlSession session=sqlSessionFactory.openSession();
		list=session.selectList("customer.findAll");
		session.close();
		return list;
	}
	
	public static CustomerVO findByCustid(int custid) {
		CustomerVO c=new CustomerVO();
		SqlSession session=sqlSessionFactory.openSession();
		c=session.selectOne("customer.findByCustid",custid);
		session.close();
		return c;
	}
	
	public static int insert(CustomerVO c) {
		SqlSession session=sqlSessionFactory.openSession();
		int re=session.insert("customer.insert",c);
		session.commit();
		session.close();
		return re;
	}

	public static int update(CustomerVO c) {
		SqlSession session=sqlSessionFactory.openSession(true);
										//autocommit true=>따로 session.commit 안 해도 됨
		int re=session.insert("customer.update", c);
		session.close();
		return re;
	}

	public static int delete(int custid) {
		SqlSession session=sqlSessionFactory.openSession(true);
		int re=session.delete("customer.delete",custid);
		session.close();
		return re;
	}
  • static block: 메인이 실행되기 전에, 클래스가 메모리에 로드될 때 맨 처음에 한 번만 실행됨

Auto commit (자동 커밋)

SqlSession session=sqlSessionFactory.openSession(true);

SqlSession 객체를 생성함과 동시에 자동으로 commit되게 하는 방법.

commit을 하지 않으면 insert나 update, delete에 성공해도 커밋이 되지 않아서 DB에 저장되지 않는다.

수동 커밋

session.commit();

VO

@Data  //lombok. Getter, Setter, ToString 등을 자동으로 만들어 줌
public class BookVO {
	private int bookid;
	private String bookname;
	private String publisher;
	private int price;
}

DAO

@Repository
public class CustomerDAO {
	public List<CustomerVO> findAll(){
		return DBManager.findAll();
	}
	public CustomerVO findByCustid(int custid) {
		return DBManager.findByCustid(custid);
	}
	public int insert(CustomerVO c) {
		return DBManager.insert(c);
	}
	public int update(CustomerVO c) {
		return DBManager.update(c);
	}
	public int delete(int custid) {
		return DBManager.delete(custid);
	}
}

Controller

Mapping

@Controller
@RequestMapping("/insertBoard")
public class InsertBoardController {

@Controller ->컨트롤러로 지정. 클래스 시작하는 부분 위에 씀
@RequestMapping("/insertBoard") -> 이 컨트롤러가 연결되는 주소. 이 컨트롤러 안의 메소드를 실행했을 때 마지막에 이동하는 뷰 주소를 설정해 줌 (메소드마다 따로 설정할 수 있다)
updateBoardController, insertBoardController 등 기능마다 controller를 따로 만들거나 하나의 컨트롤러에 모든 기능을 다 코딩할 수도 있음.
따로 만들 경우, controller 클래스 시작 전에 @RequestMapping을 하면 모두 똑같은 view가 설정된다. (메소드마다 따로 설정해도 되긴 함)

메소드마다 get방식, post 방식 지정할 때

@RequestMapping(method=RequestMethod.GET)
@RequestMapping(method=RequestMethod.POST)

혹은

@GetMapping
@PostMapping

메소드마다 view를 따로 지정할 경우:

@RequestMapping(value="/updateBoard", method=RequestMethod.GET)
@GetMapping("/updateBoard")

Controller에서 DAO 사용하기 위한 코드

public class InsertBoardController {
	@Autowired
	private BoardDAO dao;
	
	public void setDao(BoardDAO dao) {
		this.dao = dao;
	}

or

@Setter
public class InsertBoardController {
	@Autowired
	private BoardDAO dao;
	

멤버변수로 dao를 선언
setter에 의한 의존관계를 설정하기 위해서 dao의 setter를 만들어준다. (1번처럼 직접 만들어도 되고 2번처럼 lombok의 @Setter를 써도 됨)
@Autowired-> 의존관계를 자동으로 설정한다.

ModelAndView

ModelAndView를 사용하기 위해 객체를 생성한다.

ModelAndView mav = new ModelAndView();

view로 실어 보낼 객체를 mav에 add한다.

mav.addObject("object의 이름",object);

어떤 뷰로 갈지 주소를 입력. 설정하지 않으면 annotation 에서 설정한 뷰로 이동한다.

mav.setViewName("listBoard");

MAV 객체를 생성할 때 매개변수로 view 주소를 넣을 수도 있다. 빈 MAV를 생성하고 setViewName을 하는 것과 같음.

ModelAndView mav=new ModelAndView("listBoard");
ModelAndView mav=new ModelAndView("redirect:/listBoard");

updateBoard에서 데이터베이스 레코드 업데이트 성공 시 listBoard 페이지로 보내려고 한다. 이 때 redirect 없이 listBoard 를 view페이지로 설정하게 되면 빈 페이지가 나온다. 왜냐하면 listBoard 메소드에서 상태유지된 객체(addObject로 추가된 객체)가 updateBoard 메소드에는 없기 때문. 상태유지해서 이동하려면 redirect:/ 를 view name 앞에 붙여줘야 한다.

메소드 리턴타입을 ModelAndView로 설정하고 마지막에 mav를 리턴해줘야 한다.

@RequestMapping("/listBook")
	public ModelAndView list() {
		ModelAndView mav=new ModelAndView();
		mav.addObject("list", dao.findAll());
		mav.setViewName("list");
		return mav;
	}

view를 설정할 필요가 없을 경우:
ModelAndView 대신 Model을 사용해도 된다.
메소드 리턴값을 void로 설정하고 매개변수에 Model model을 넣고,
model.addAttribute()를 한다. (mav.addObject와 똑같은 기능)

@RequestMapping("/listBook")  //여기에서 지정한 view name을 바꿀 필요가 없을 경우
public void list(Model model) {
		model.addAttribute("list",dao.findAll());
}

Views

(JSP 사용 시)뷰 저장 경로

webapp/WEB-INF/views

JSTL 사용을 위한 import

<%@ taglib uri="[http://java.sun.com/jsp/jstl/core](http://java.sun.com/jsp/jstl/core)" prefix="c"%>

Model에 add 한 객체를 불러오기

<c:forEach var="b" items="${list }">  //list 안의 요소(vo) 하나하나를 b라고 정하고 forEach 반복문으로 하나씩 불러오기
	${b.bookname }<br>	//b의 bookname 속성을 출력
</c:forEach>
profile
백엔드 개발자
post-custom-banner

0개의 댓글