728x90
300x250

[Spring-Framework] 7. Maven, Hibernate 5.4, Servlet, MySQL 8 연동(CRUD) - (2)


2부 글을 이어서 작성하고자 한다.


[1부] [Spring-Framework] 6. Maven, Hibernate 5.4, Servlet, MySQL 8 연동(CRUD) - (1) , 2020-09-21 14:36
https://yyman.tistory.com/1404



7. 서블렛 만들기


패키지: com.hibernateMaven.web.controller

서블릿명(클래스명):

1. SampleServlet

2. StudentServlet


두 개를 만들어준다.


세부적인 내용은 지금하진 않는다.



8. Model 정의(Entity)


OR-M(Object Relational-Mapping)의 특징을 가지는 Hibernate에서 사용할 수 있도록 DTO 또는 VO(Value Object)를 정의해줘야 한다.


패키지: com.hibernateMaven.web.model

클래스명: 

1. Emptable

2. Student


클래스에 Persistence를 잘 정의해줘야 한다.

@Entity, @Table 등에 대한 Mapping을 클래스에서도 할 수 있다.


package com.hibernateMaven.web.model;


import java.sql.Date;


import javax.persistence.*;


@Entity

@Table(name = "emptable")

public class Emptable

{


@Id

@GeneratedValue(strategy = GenerationType.AUTO)

private int empno;


@Column(name="name")

private String name;


@Column(name="address")

private String address;


@Column(name="createdate")

private Date createdate;

public int getEmpno() {

return empno;

}

public void setEmpno(int empno) {

this.empno = empno;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public String getAddress() {

return address;

}

public void setAddress(String address) {

this.address = address;

}

public Date getCreatedate() {

return createdate;

}

public void setCreatedate(Date createdate) {

this.createdate = createdate;

}

}


코드 1. Emptable.java


package com.hibernateMaven.web.model;


import java.sql.Date;


import javax.persistence.Column;

import javax.persistence.Entity;

import javax.persistence.GeneratedValue;

import javax.persistence.GenerationType;

import javax.persistence.Id;

import javax.persistence.Table;


@Entity

@Table(name = "student")

public class Student {


@Id

@GeneratedValue(strategy = GenerationType.AUTO)

private int studentno;


@Column(name="name")

private String name;


@Column(name="address")

private String address;


@Column(name="createdate")

private Date createdate;

public int getStudentno() {

return studentno;

}

public void setStudentno(int studentno) {

this.studentno = studentno;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public String getAddress() {

return address;

}

public void setAddress(String address) {

this.address = address;

}

public Date getCreatedate() {

return createdate;

}

public void setCreatedate(Date createdate) {

this.createdate = createdate;

}

}


코드 2. Student.java


이전의 Hibernate 개발을 보면, xml으로 hibernate.cfg.xml에 resource-mapping을 시켜주었다.

물론 현재 XML-Mapping 방법을 사용해도 무방하나, 굳이 번거롭게 2개 이상 수정 작업을 만들어서 일을 크게 만들 필요는 없다고 본다.


<?xml version = "1.0" encoding = "utf-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name = "com.hibernateMaven2.web.model.Emptable" table = "emptable"> <meta attribute = "class-description"> This class contains the employee detail. </meta> <id name = "empno" type = "int" column = "empno"> <generator class="native"/> </id> <property name = "name" column = "name" type = "string"/> <property name = "address" column = "address" type = "string"/> <property name = "createdate" column = "createdate" type = "date"/> </class>  </hibernate-mapping>

예1) Emptable.hbm.xml


[첨부(Attachments)]

Emptable.hbm-xml.zip


Xml-Mapping 관련 파일이 필요한 이유는 JBoss-Hibernate에서 현재 생성이 되지 않고 있다.
(JBoss의 업데이트 등의 문제) - [2020-09-21 기준]


충분히 태스트를 해보았다. JBoss 기능에도 클래스로 맵핑하는 기능이 있다.



그림 14. Mapping 추가 기능 - STS 4의 JBoss(Hibernate 기능)





9. Hibernate.cfg.xml 파일 수정하기


그림 14의 Add-Mapping 작업을 해줘야 한다.

1부의 그림 9에 있는 첨부 파일의 내용이다.


<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN"

                                         "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>

 <session-factory name="">

  <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>

  <property name="hibernate.connection.username">사용자계정</property>

  <property name="hibernate.connection.password">비밀번호</property>

  <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/web?serverTimezone=UTC&amp;characterEncoding=utf8</property>

  <property name="hibernate.dialect">org.hibernate.dialect.MySQL8Dialect</property>

  <property name="hibernate.show_sql">true</property>

  <property name="hibernate.hbm2ddl.auto">update</property>

  <property name="hibernate.default_entity_mode">pojo</property>

  <property name="hibernate.current_session_context_class">thread</property>

  

  <mapping class="com.hibernateMaven.web.model.Emptable"/>    <!-- empTable 클래스 맵핑-->

  <mapping class="com.hibernateMaven.web.model.Student"/>

 </session-factory>

</hibernate-configuration>


코드 3) 클래스 맵핑 방법


[첨부(Attachments)]

hibernate.cfg-class-mapping.zip



예1의 형태로도 맵핑을 시도해볼 수 있다.


<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN"

                                         "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>

 <session-factory name="">

  <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>

  <property name="hibernate.connection.username">사용자명</property>

  <property name="hibernate.connection.password">비밀번호</property>

  <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/web?serverTimezone=UTC&amp;characterEncoding=utf8</property>

  <property name="hibernate.dialect">org.hibernate.dialect.MySQL8Dialect</property>

  <property name="hibernate.show_sql">true</property>

  <property name="hibernate.hbm2ddl.auto">update</property>

  <property name="hibernate.default_entity_mode">pojo</property>

  <property name="hibernate.current_session_context_class">thread</property>

  <mapping class="com.hibernateMaven.web.model.Student"/>


  <!-- XML Resource 자원으로 맵핑 -->

  <mapping resource="com/hibernateMaven/web/model/Emptable.hbm.xml"/>

 </session-factory>

</hibernate-configuration>


코드 4) 클래스, XML 맵핑 방법


[첨부(Attachments)]

hibernate.cfg-xml-mapping.zip



코드 3과 코드 4를 언급한 것은 시중 시판되는 책이나 검색 자료 등에서 언급되고 있는 소스코드의 고정관념을 깨라는 이야기이다.

자유롭게 해도 된다.


 

 

그림 15) 코드 3방식의 클래스 맵핑으로만 구성

그림 16. 코드 4방식을 채택하였을 때의 구조
         (XML-Mapping이라고 흔히 정의함)



10. HibernateUtil.java (이해보다는 복사, 붙여넣기할 것)


HibernateUtil이라는 클래스에 정의된 원형들은 DB의 연결과 종료에 해당되는 부분들이다.

연결 한번 하려고 이걸 다 외우고 작성할 수 없으니 Copy해서 사용하는 걸 추천한다.


package com.hibernateMaven.web.factory;


import org.hibernate.SessionFactory;

import org.hibernate.boot.Metadata;

import org.hibernate.boot.MetadataSources;

import org.hibernate.boot.registry.StandardServiceRegistry;

import org.hibernate.boot.registry.StandardServiceRegistryBuilder;



public class HibernateUtil

{


    private static StandardServiceRegistry registry;

    private static SessionFactory sessionFactory;


    public static SessionFactory getSessionFactory() {

        if (sessionFactory == null) {

            try {

                // Create registry

                registry = new StandardServiceRegistryBuilder().configure().build();


                // Create MetadataSources

                MetadataSources sources = new MetadataSources(registry);


                // Create Metadata

                Metadata metadata = sources.getMetadataBuilder().build();


                // Create SessionFactory

                sessionFactory = metadata.getSessionFactoryBuilder().build();

                

            } catch (Exception e) {

                e.printStackTrace();

                if (registry != null) {

                    StandardServiceRegistryBuilder.destroy(registry);

                }

            }

        }

        return sessionFactory;

    }


    public static void shutdown() {

        if (registry != null) {

            StandardServiceRegistryBuilder.destroy(registry);

        }

    }


}


코드 5) HibernateUtil.java 코드


[첨부(Attachments)]

HibernateUtil.zip



11. Interface 설계


이 글에서는 select, select where cause, insert, update, delete를 위주의 기능을 확인할 수 있도록 작성되었다.


package com.hibernateMaven.web.service;


import java.util.List;


import com.hibernateMaven.web.model.Emptable;


public interface IEmpTable {


public List<Emptable> allList(); // Select * FROM empTable

public Emptable getList(Integer num); // Select * from emptable where empno = ?

public void save(Emptable emptable); // insert into emptable

public int update(Emptable emptable); // update emptable set cause where emp = ? 

public int delete(Integer num); // delete from emptable where empno = ?

public Emptable searchName(Integer num, String name); // 두 가지 조건 동시 만족 조회

}



코드 6) IEmpTable.java (인터페이스 파일)


[첨부(Attachments)]

IEmpTable.zip



package com.hibernateMaven.web.service;


import java.util.List;


import com.hibernateMaven.web.model.Student;


public interface IStudent {


public List<Student> allList(); // Select * FROM student

public Student getList(Integer num); // Select * from student where studentno = ?

}



코드 7) IStudent.java (인터페이스 파일)


[첨부(Attachments)]

IStudent.zip




12. Class 구현


IEmpTable을 바탕으로 EmpTableService.java, StudentService.java 파일을 작성해보았다.


package com.hibernateMaven.web.service;


import java.util.List;


import org.hibernate.query.*;

import org.hibernate.Session;

import org.hibernate.Transaction;


import com.hibernateMaven.web.factory.HibernateUtil;

import com.hibernateMaven.web.model.Emptable;


public class EmpTableService implements IEmpTable {


@Override

public List<Emptable> allList() {


Transaction transaction = null;

List<Emptable> list = null;

try (Session session = HibernateUtil.getSessionFactory().openSession()) {

// start a transaction

transaction = session.beginTransaction();

// get an user object

list = session.createQuery("from Emptable").getResultList();

System.out.println("연습:" + list.get(0).getName());

// commit transaction

transaction.commit();

} catch (Exception e) {

if (transaction != null) {

transaction.rollback();

}

e.printStackTrace();

}

        return list;

}


@Override

public Emptable getList(Integer num) {

Transaction transaction = null;

Emptable emptable = null;

try (Session session = HibernateUtil.getSessionFactory().openSession()) {

transaction = session.beginTransaction();

emptable = session.get(Emptable.class, num);

            

System.out.println("특정 조회:" + emptable.getName());

transaction.commit();


return emptable;

        } catch (Exception e) {

            if (transaction != null) {

                transaction.rollback();

            }

            e.printStackTrace();

            

            return null;

        }

}



@Override

public void save(Emptable emptable) {

Transaction transaction = null;

try (Session session = HibernateUtil.getSessionFactory().openSession()) {

// start a transaction

transaction = session.beginTransaction();

// save the student object

session.save(emptable);

// commit transaction

transaction.commit();

} catch (Exception e) {

if (transaction != null) {

transaction.rollback();

}

e.printStackTrace();

}

}


@Override

public int update(Emptable emptable) {


Transaction transaction = null;

String hql = null;

int result = -1;

try (Session session = HibernateUtil.getSessionFactory().openSession()) {

// start a transaction

transaction = session.beginTransaction();

// save the student object

hql = "UPDATE Emptable set name = :name, "  +

"address = :address, createdate = :createdate " +

             "WHERE empno = :empno";

Query query = session.createQuery(hql);

query.setParameter("name", emptable.getName());

query.setParameter("address", emptable.getAddress());

query.setParameter("createdate", emptable.getCreatedate());

query.setParameter("empno", emptable.getEmpno());

result = query.executeUpdate();


System.out.println("수정결과:" + result);

// commit transaction

transaction.commit();

} catch (Exception e) {

if (transaction != null) {

transaction.rollback();

}

e.printStackTrace();

}

return result;

}


@Override

public int delete(Integer num) {

Transaction transaction = null;

String hql = null;

int result = -1;

try (Session session = HibernateUtil.getSessionFactory().openSession()) {

// start a transaction

transaction = session.beginTransaction();

// save the student object

hql = "Delete from Emptable " +

             "WHERE empno = :empno";

Query query = session.createQuery(hql);

query.setParameter("empno",  num);

result = query.executeUpdate();


System.out.println("삭제결과:" + result);

// commit transaction

transaction.commit();

} catch (Exception e) {

if (transaction != null) {

transaction.rollback();

}

e.printStackTrace();

}

return result;

}


@Override

public Emptable searchName(Integer num, String name) {


Transaction transaction = null;

String hql = null;

Emptable emp = null;

try (Session session = HibernateUtil.getSessionFactory().openSession()) {

// start a transaction

transaction = session.beginTransaction();

// save the student object

hql = "from Emptable " +

             "WHERE empno = :empno and name = :name";

Query query = session.createQuery(hql);

query.setParameter("empno", num);

query.setParameter("name",  name);

emp = (Emptable) query.list().get(0);


System.out.println("번호, 이름 검색");

// commit transaction

transaction.commit();

return emp;

} catch (Exception e) {

if (transaction != null) {

transaction.rollback();

}

e.printStackTrace();

return null;

}

}


}



코드 8) EmpTableService.java


[첨부(Attachments)]

EmpTableService.zip


package com.hibernateMaven.web.service;


import java.util.List;


import org.hibernate.query.*;

import org.hibernate.Session;

import org.hibernate.Transaction;


import com.hibernateMaven.web.factory.HibernateUtil;

import com.hibernateMaven.web.model.Student;


public class StudentService implements IStudent {


@Override

public List<Student> allList() {

return null;

}


@Override

public Student getList(Integer num) {

Student student;

Transaction transaction = null;

        Session session= HibernateUtil.getSessionFactory().openSession();

         try

         {

  transaction = session.beginTransaction();

             student=(Student)session.get(Student.class,num); 

 

             System.out.println("특정 조회:" + student.getName());

             transaction.commit();

             return student;

         }

         catch (Exception e) 

         {

        e.printStackTrace();

            return null;

         }

         finally 

         {

             session.close(); 

         }

         

         /*

Student student = null;

try (Session session = HibernateUtil.getSessionFactory().openSession()) {

transaction = session.beginTransaction();

student = session.get(Student.class, num);

            

System.out.println("특정 조회:" + student.getName());

        } catch (Exception e) {

            if (transaction != null) {

                transaction.rollback();

            }

            e.printStackTrace();

        }

*/

}


}



코드 9) StudentService.java


[첨부(Attachments)]

StudentService.zip




13. Servlet - 완성하기


1부에서 생성한 서블렛의 내용을 구현하였다.


package com.hibernateMaven.web.controller;


import java.io.IOException;

import java.io.PrintWriter;

import java.sql.Date;

import java.util.List;


import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;


import com.hibernateMaven.web.model.Emptable;

import com.hibernateMaven.web.service.EmpTableService;

import com.hibernateMaven.web.service.StudentService;


public class SampleServlet extends HttpServlet {

private static final long serialVersionUID = 1L;

       

    public SampleServlet() {

        super();

    }


/**

* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)

*/

protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {


res.setContentType("text/html;charset=UTF-8");

PrintWriter out = res.getWriter();

// HTML 스타일 정의

out.println("<html><head><title>Hibernate Maven - MySQL 8 실험</title></head><body>");

EmpTableService service = new EmpTableService();


// 1. 전체 조회

List<Emptable> emp1 = service.allList();


// 2. 특정 ID 조회

Emptable emp2 = service.getList(1);

// 3. 삽입 구현

Emptable createEmp = new Emptable();

createEmp.setName("홍길동");

createEmp.setAddress("행복구 행복시");

java.sql.Date sqlDate = java.sql.Date.valueOf("2020-05-20");

createEmp.setCreatedate(sqlDate);

service.save(createEmp);

// 4. 수정

Emptable updateEmp = new Emptable();

updateEmp.setName("동길홍");

updateEmp.setAddress("시복행 구복행");

sqlDate = java.sql.Date.valueOf("1990-09-01");

updateEmp.setCreatedate(sqlDate);

updateEmp.setEmpno(3);

service.update(updateEmp);

// 5. 삭제

service.delete(4);

// 6. 특정 이름, 번호 조회

Emptable query1 = service.searchName(18, "홍길동");

out.println("주소:" + query1.getAddress() + "<br/>" );

out.println("</body></html>");

out.close();

}


/**

* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)

*/

protected void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {

}


}



코드 10) SampleServlet.java


[첨부(Attachments)]

SampleServlet.zip



package com.hibernateMaven.web.controller;


import java.io.IOException;

import java.io.PrintWriter;

import java.util.List;


import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;


import com.hibernateMaven.web.model.Student;

import com.hibernateMaven.web.service.StudentService;



public class StudentServlet extends HttpServlet {

private static final long serialVersionUID = 1L;

       

    public StudentServlet() {

        super();

    }


/**

* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)

*/

protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {


res.setContentType("text/html;charset=UTF-8");

PrintWriter out = res.getWriter();

// HTML 스타일 정의

out.println("<html><head><title>Hibernate Maven - MySQL 8 실험(Table:Student)</title></head><body>");

StudentService service2 = new StudentService();


// 1. 전체 조회

//List<Student> student1 = service.allList();

service2.getList(1);

out.println("</body></html>");

out.close();

}


/**

* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)

*/

protected void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {

doGet(req, res);

}


}



코드 11) StudentServlet.java


[첨부(Attachments)]

StudentServlet.zip



15. 맺음글(Conclusion)


OR-M 프레임워크 중 하나인 Hibernate 5.4 Final 버전을 사용하는 방법에 대해서 소개하였다.


추가적으로 알아보면 도움되는 것: Hibernate HQL
-> SQL언어가 사라진 것이 아니라, 또 Hibernate가 제공하는 HQL이 탄생하게 되었다.
ORM을 맹신하면 안 되는 이유가 있는 것이다.

* Link1: https://howtodoinjava.com/hibernate/complete-hibernate-query-language-hql-tutorial/ (영어), 2014-10-30

  Link2: https://www.tutorialspoint.com/hibernate/hibernate_query_language.htm, (영어)


* 공식 사이트: https://docs.jboss.org/hibernate/orm/5.4/userguide/html_single/Hibernate_User_Guide.html#hql, Hibernate 5.4 Final 메뉴얼

  (조금 공부할 양이 많다.) - 2020-08-27 10:35:21


제대로 사용하기 위해서는 이 밖에도 Hibernate 프레임워크 하나에만 많은 공부가 필요한 것 같다.

물론 전부 학습 할 수는 없다.



* 참고자료(References)


[Hibernate - Example Project]


5. GitHub - RameshMF/Hibernate-ORM-Tutorials: 40+ source code Examples/Tutorials/Guides of Hibernate ORM Framework, https://github.com/RameshMF/Hibernate-ORM-Tutorials, Accessed by 2020-09-21, Last Modified .


-> 추천(43점): 구현하는 예제가 다양하게 이클립스 버전으로 작성되어 있다. 물론 100% 돌아가는 건 아니다. 구현할 때 많은 참고가 된다.


6. Hibernate 5 XML Configuration Example - DZone Java, https://dzone.com/articles/hibernate-5-xml-configuration-example, Accessed by 2020-09-21, Last Modified 2018-11-29.


-> 추천(55점): Web 프로젝트는 아니었지만, 구현에 있어서 큰 도움을 주었다.


[Hibernate HQL]


7. Hibernate HQL - Hibernate Query Language Examples - - HowToDoInJava, https://howtodoinjava.com/hibernate/complete-hibernate-query-language-hql-tutorial/, Accessed by 2020-09-21, Last Modified 2014-10-30.


-> 추천(40점): 기본적인 부분에 대해서 잘 작성되었다.


8. Hibernate ORM 5.4.21.Final User Guide, https://docs.jboss.org/hibernate/orm/5.4/userguide/html_single/Hibernate_User_Guide.html, Accessed by 2020-09-21, Last Modified 2020-08-27.


-> 추천(40점): 조금 어렵긴 해도 알면 도움이 될 거 같다. 다 활용하진 못할 거 같다는 생각도 든다.


9. Hibernate - Query Language - Tutorialspoint, https://www.tutorialspoint.com/hibernate/hibernate_query_language.htm, Accessed by 2020-09-21, Last Modified .


-> 추천(40점): 기본적인 부분에 대해서 잘 작성되었다.


[Hibernate - XML]


10. java - [Hibernate]Error: entity class not found: - Stack Overflow, https://stackoverflow.com/questions/6692882/hibernateerror-entity-class-not-found/38801518, Accessed by 2020-09-21, Last Modified 2016.


-> XML-Mapping 시연할 때, "[Hibernate]Error: entity class not found:"를 해결하기 위해서 찾아본 것이다.


11. Brain to Blog :: 하이버네이트(Hibernate) 사용하기, https://antop.tistory.com/entry/%ED%95%98%EC%9D%B4%EB%B2%84%EB%84%A4%EC%9D%B4%ED%8A%B8Hibernate-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0, Accessed by 2020-09-21, Last Modified 2009-08-24.

반응형
728x90
300x250

[JSP] 8. 영속프레임워크 MyBatis를 활용한 CRUD 구현 - JSP와 Oracle(XML 방식)


조금 알기 쉽게 작성하였다.

"영속 프레임워크"라고 보면 된다.

영속 프레임워크라는 것은 DAO 객체에서 데이터베이스 데이터의 처리 기능을 제공하는 프레임워크이다.


대표적인 것: myBatis, Hibernate가 있다.


* 사용되는 언어: JSP / Servlet,
* 데이터베이스: Oracle 12 이상 (Oracle 18g에서 태스트 완료 하였음.)

* 프레임워크: mybatis-3.5.5

[첨부(Attachments)]

mybatis-3.5.5.jar

mybatis-3.5.5(원본).7z



1. 최소한 관련 프레임워크에 대해서 이해해보기


프레임워크의 특징에 대해서 간단하게 작성해보았다.


[특징]


myBatis란 그나마 학습하기 쉽고, 사용방법이 간단함.

초기 셋팅을 조금한 후에 나머지는 SQL명령문과 간단한 자바 소스코드로 구현하여 사용할 수 있음.

(iBatis 프로젝트로 시작해서 현재는 Apache Foundation에서 관리하는 자바 오픈소스 프레임워크)


http://www.mybatis.org


hibernate란 ORM(Object-Relational Mapping) 프레임워크라는 영속 프레임워크로서 자바와 객체와 데이터베이스를 매핑하여 데이터를 처리하므로 엔터프라이즈 환경에 적합한 특징을 가지고 있음.

(배우기 어려움. - 객체 모델링 경험이 요구됨.)


http://hibernate.org 



[생각해보기]


생각을 조금해본다면, 꼭 반드시 웹 프로젝트에만 MyBatis를 활용할 필요가 없음.
일반적인 Swing 프로젝트 연습 등에서도 사용해볼 수도 있겠음.

- 프레임워크 사용하기 전에 고민해야 할 점

1. 기본적으로 제공하는 JDBC 구현에 대해서도 생각해보기

(이유: 자바에서 자체적으로 제공하는 jdbc 구현(예: ResultSet, prepareStatement 등)에 대해서 이해하고 있으면 좋음.)


2. 프레임워크를 사용하는 것이 만능인지, 고민하기

3. SQL Injection 등의 보안 문제에 대해서 생각하기

   (프레임워크를 사용하면, SQL Injection 문제는 간단하게 해소된다.)


결론은 좋긴 좋다. 프레임워크!!!


[코드 비교하기] 


 Mybatis 사용전 코드 방식

 Mybatis 사용후 코드 방식

 

public Entity selectFAQList(UserConnection conn, Entity param)  throws SQLException 

{

    UserStatement stmt = null; //stmt 초기값 선언
    ResultSet rslt = null; //rslt 초기값 선언
    StringBuffer sql = new StringBuffer();
    sql.append("\n SELECT *"); //
    sql.append("\n FROM"); //코드 추가
    sql.append("\n TABLE1");
    stmt = conn.prepareStatement(sql.toString());
    rslt = stmt.executeQuery();
    Entity _DATA = new Entity();
    _DATA.put("_DATA", EntityUtil.ResultSetToClobList(rslt));
    return _DATA;
}

 <?xml version="1.0" encoding="UTF-8"?>

  <ENTITY id="table.getTable1List" type="SQL" return="List">
    <![CDATA[
        SELECT *
            FROM
            TABLE1
    ]]>
    <PARAMS>    
    </PARAMS>
  </ENTITY>

// xml로 빼내서 쿼리문을 작성하면 내부적 처리는 Mybatis에서 // 모두 처리해주므로
// Entity ID값을 java에서 호출만하면 된다.




2. 초기 환경설정 셋팅하기


시중 블로그를 다수 검색하고, 교제등을 참고하였으나 왕초보 수준으로 알기 쉽게 적용하는 방법은 나오지 않은 거 같아서 작성해보려고 한다.



그림 1. 초기 셋팅해줘야 하는 프로젝트 파일


최소 못해도 기본적으로 갖춰줘야 하는 소스 파일들을 몇 개 찝어보았다.


"Address_****.파일확장자명"으로 구성된 파일은 사용자에 따라 임의적으로 구성해봐도 무방하다.


ojdbc8_g.jar은 어디에 있는가?

오라클 설치파일이 있는 폴더에 보면 jdbc 폴더가 있는데 해당 위치에 있다.



그림 2. 오라클 설치 파일이 있는 폴더



그림 3. jdbc 폴더에 있는 readme.txt



그림 4. jdbc/lib 폴더 내에 있음.



[첨부(Attachments)]

oracle12lib.z01

oracle12lib.z02

oracle12lib.zip


(참고로 반디집을 통해서 압축을 풀 수 있음.)


소스코드를 통해서 살펴보는 것이 조금 빠를 수 있다고 주장해 본다.



3. 데이터베이스 설계하기


예제 데이터베이스를 설계하도록 하겠다.


tableName(테이블명): addressbook


 키

 항목명

 속성 

 PK(기본키)

num

인덱스(ID)

 

name

nvarchar

 

address

nvarchar

 

birthdate

date




그림 5. 테이블 만들기(오라클)


그림 5는 SQL Developer를 통해서 테이블을 생성한 모습이다. 

원래 복잡하게 쿼리라는 것을 통해서 작성해야 하는데, 세상이 시간이 지나다보니 편리해진 것도 있다고 주장한다.


CREATE TABLE "C##USER"."ADDRESSBOOK" 

   ( "NUM" NUMBER(*,0) NOT NULL ENABLE, 

"NAME" NVARCHAR2(20), 

"ADDRESS" NVARCHAR2(100), 

"BIRTHDATE" DATE, 

CONSTRAINT "ADDRESSBOOK_PK" PRIMARY KEY ("NUM")



  USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 

  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645

...............................

(중략)


ALTER TRIGGER "C##USER"."ADDRESSBOOK_TRG" ENABLE;



그림 6. SQL문으로 Create Table 구성하기


그림 6은 흔히 CRUD(Create Read Update Delete)에서의 Create를 의미하는 작업이다.

예를 들면 원래는 이렇게 복잡하게 작성해야 하는데 지금은 훨씬 편하게 만들 수 있다고 보면 된다.




4. 프로젝트 구성하기 - 과정 소개 (소스코드를 통해서 살펴보는 프로젝트 구성)


1단계 설계

SQL - 테이블 작성


2단계 기본 환경설정 작성(준비)

web.xml을 먼저 작성한다.              (암기가 되는 부분인가? 불가능. 이거 외우는 거 불가능.)

mybatis-config.xml                     (암기가 되는 부분인가? 불가능. 이거 외우는 거 불가능.)

SqlMapSessionFactory.java           (암기가 되는 부분인가? 불가능. 이거 외우는 거 불가능.)

AddressDto.java 

addressMapper.xml                    (암기가 되는 부분인가? 불가능. 이거 외우는 거 불가능.)


3단계(간단한 CRUD 템플릿 준비)

addressDao.java                       (암기가 되는 부분인가? 코드는 간단하나 2단계 셋팅이 안 되어 있으면 의미 없음.)


4단계(인터페이스 설계 및 구현부 작성)

address.java 

addressImpl.java


5단계(뷰 페이지 구성하기)

web.xml (수정 - 작업)

servlet 페이지로 진행 또는 jsp파일로 진행해도 무방




5. 소스코드


소스코드는 순서대로 소개하겠다.


(2단계 - 소스코드)


<?xml version="1.0" encoding="UTF-8"?>


<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"

version="3.1">


<display-name>edu-mybatis</display-name>

<welcome-file-list>

<welcome-file>index.html</welcome-file>

<welcome-file>index.htm</welcome-file>

<welcome-file>index.jsp</welcome-file>

<welcome-file>default.html</welcome-file>

<welcome-file>default.htm</welcome-file>

<welcome-file>default.jsp</welcome-file>

</welcome-file-list>

<!-- Board List -->

<servlet>

<servlet-name>boardList</servlet-name>

<servlet-class>com.edu.view.BoardListServlet</servlet-class>

</servlet>

<servlet-mapping>

<servlet-name>boardList</servlet-name>

<url-pattern>/board/list.do</url-pattern>

</servlet-mapping>

<!-- Board Insert -->

<servlet>

<servlet-name>boardInsert</servlet-name>

<servlet-class>com.edu.view.BoardInsertServlet</servlet-class>

</servlet>

<servlet-mapping>

<servlet-name>boardInsert</servlet-name>

<url-pattern>/board/insert.do</url-pattern>

</servlet-mapping>

<!-- Board Delete -->

<servlet>

<servlet-name>boardDelete</servlet-name>

<servlet-class>com.edu.view.BoardDeleteServlet</servlet-class>

</servlet>

<servlet-mapping>

<servlet-name>boardDelete</servlet-name>

<url-pattern>/board/delete.do</url-pattern>

</servlet-mapping>

</web-app>


* 파일명: web.xml


[첨부(Attachments)]

web.zip



예를 들면, 이런 형태로 구성해서 사용할 수 있다.

크게 어렵게 작성하진 않았으니 참고하면 도움이 될 것 같다.


<?xml version="1.0" encoding="UTF-8"?>


<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" 

"http://mybatis.org/dtd/mybatis-3-config.dtd">


<configuration>


<environments default="development">

    <environment id="development">

      <transactionManager type="JDBC"/>

      <dataSource type="POOLED">

        <property name="driver" value="oracle.jdbc.driver.OracleDriver" />

        <property name="url" value="jdbc:oracle:thin:@127.0.0.1:1521:orcl"/>

        <property name="username" value="사용자 계정"/>

        <property name="password" value="비밀번호"/>

      </dataSource>

    </environment>

  </environments>


  <mappers>

    <mapper resource="com/edu/db/addressMapper.xml"/>              // 리소스 증가시 추가해서 사용해보기

  </mappers>


</configuration>


* 파일명: mybatis-config.xml



[첨부(Attachments)]

mybatis-config.zip



package com.edu.db;


import java.io.IOException;

import java.io.InputStream;

import org.apache.ibatis.io.Resources;

import org.apache.ibatis.session.SqlSessionFactory;

import org.apache.ibatis.session.SqlSessionFactoryBuilder;


public class SqlMapSessionFactory {

public static SqlSessionFactory ssf;


    static{


        String resource = "com/edu/db/mybatis-config.xml";

        InputStream inputStream = null;


        try {

            inputStream = Resources.getResourceAsStream(resource);

        } catch (IOException e) {

            e.printStackTrace();

        }


        ssf = new SqlSessionFactoryBuilder().build(inputStream);


    }

    

    public static SqlSessionFactory getSqlSessionFactory(){

        return ssf;

    }

    

}



* 파일명: SqlMapSessionFactory.java


[첨부(Attachments)]

SqlMapSessionFactory.zip


package com.edu.db;


import java.sql.Timestamp;


public class AddressDto {

private int num;

private String name;

private String address;

private Timestamp birthdate;

public int getNum() {

return num;

}

public void setNum(int num) {

this.num = num;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public String getAddress() {

return address;

}

public void setAddress(String address) {

this.address = address;

}

public Timestamp getBirthdate() {

return birthdate;

}

public void setBirthdate(Timestamp birthdate) {

this.birthdate = birthdate;

}

}



* 파일명: AddressDto.java


[첨부(Attachments)]

AddressDto.zip


<?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.edu.db.mappers.addressMapper">

<select id="allAddress" resultType="com.edu.db.AddressDto">

select * from addressbook

</select>


<select id="selectAddress" parameterType="Integer" resultType="com.edu.db.AddressDto">

select NUM, NAME, ADDRESS, BIRTHDATE

from addressbook

  where num=#{num}

</select>


<insert id="insertAddress" parameterType="com.edu.db.AddressDto">

insert into

addressbook(NAME, ADDRESS, BIRTHDATE)

values

(#{name},#{address},#{birthdate})

</insert>


<delete id="deleteAddress" parameterType="Integer">

DELETE FROM AddressBook

WHERE NUM = #{num}

</delete>

<update id="updateAddress" parameterType="com.edu.db.AddressDto" >

update addressbook

set birthdate = #{birthdate}, name = #{name}, address =#{address}

where num = #{num}

</update>

</mapper>


* 파일명: addressMappper.xml


[첨부(Attachments)]

addressMapper.zip


(3단계 - 소스코드)


package com.edu.db;

import java.io.*;

import java.util.*;

import org.apache.ibatis.io.*;

import org.apache.ibatis.session.*;


public class AddressDao {

private AddressDao() {}

    private static AddressDao dao;


    public static AddressDao getInstance(){


        if(dao == null){

            dao = new AddressDao();

        }


        return dao;

    }

    

    // SQL 세션 열기

    SqlSessionFactory factory = SqlMapSessionFactory.getSqlSessionFactory();


    public AddressDto selectAddress(Integer num) {


        SqlSession session = factory.openSession();


        AddressDto addressDTO = session.selectOne("com.edu.db.mappers.addressMapper.selectAddress", num);

        session.close();


        return addressDTO;


    }


 


    public int updateAddress(AddressDto addressDTO) {


        SqlSession session = factory.openSession();


        int update = session.update("com.edu.db.mappers.addressMapper.updateAddress", addressDTO);


        // update나 delete의 경우 반드시 커밋 필요.

        // session.commit();을 해주거나 factory.openSession(true);로 설정하면 자동 커밋된다.

        session.commit(); 

        session.close();


        return update;


    }

    

    

    public int insertAddress(AddressDto addressDTO) {

   

    SqlSession session = factory.openSession();

    int insert = session.insert("com.edu.db.mappers.addressMapper.insertAddress", addressDTO);

   

    session.commit();

    session.close();

   

    return insert;

   

    }

    

    public int deleteAddress(Integer num) {

   

    SqlSession session = factory.openSession();

    int delete = session.delete("com.edu.db.mappers.addressMapper.deleteAddress", num);

   

    session.commit();

    session.close();

   

    return delete;

    }


}


* 파일명: AddressDao.java


특징: Singleton 패턴을 적용함.


[첨부(Attachments)]

AddressDao.zip



(4단계 - 소스코드)


package com.edu.db;


public interface Address {


public AddressDto getAddress(Integer num);

public int updateAddress(AddressDto addressDTO);

public int insertAddress(AddressDto addressDTO); 

public int deleteAddress(Integer num);

}


* 파일명: Address.java


특징: Interface 파일


[첨부(Attachments)]

Address.zip


package com.edu.db;


public class AddressImpl implements Address {


AddressDao dao = AddressDao.getInstance();

@Override

public AddressDto getAddress(Integer num) {

return dao.selectAddress(num);

}


@Override

public int updateAddress(AddressDto addressDTO) {

return dao.updateAddress(addressDTO);

}

@Override

public int insertAddress(AddressDto addressDTO) {

return dao.insertAddress(addressDTO);

}

@Override

public int deleteAddress(Integer num) {

return dao.deleteAddress(num);

}


}


* 파일명: AddressImpl.java


특징: Address 인터페이스 구현파일


[첨부(Attachments)]

AddressImpl.zip


(5단계 - Servlet 파일 예)


package com.edu.view;


import java.io.IOException;

import java.io.PrintWriter;

import java.sql.Timestamp;

import java.text.SimpleDateFormat;


import javax.servlet.ServletException;

import javax.servlet.annotation.WebServlet;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;


import com.edu.db.Address;

import com.edu.db.AddressDto;

import com.edu.db.AddressImpl;


/**

 * Servlet implementation class boardListServlet

 */

public class BoardListServlet extends HttpServlet {

private static final long serialVersionUID = 1L;

       

    /**

     * @see HttpServlet#HttpServlet()

     */

    public BoardListServlet() {

        super();

    }


/**

* @see HttpServlet#doGet(HttpServletRequest req, HttpServletResponse res)

*/

protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {

res.setContentType("text/html;charset=UTF-8");

PrintWriter out = res.getWriter();

out.print("<br/>");

AddressImpl address = new AddressImpl();

AddressDto addressDto = address.getAddress(1);

out.println("<html><head><title>CRUD - List2</title></head>");

out.println("<body><h2>MyBatis - List</h2>");

SimpleDateFormat format1 = new SimpleDateFormat ( "yyyy-MM-dd" );

String birthdate = format1.format(addressDto.getBirthdate());

out.print(addressDto.getNum() + "/" + addressDto.getName() + "/");

out.print(addressDto.getAddress() + "/" + birthdate);

out.print("<br/>");

out.println("</body></html>");

out.close();

}

/**

* @see HttpServlet#doPost(HttpServletRequest req, HttpServletResponse res)

*/

protected void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {

doGet(req, res);

}


}



* 파일명: boardListServlet.java


어노테이션으로 맵핑하지 않고, web.xml에 URL 맵핑하였음.


[첨부(Attachments)]

BoardListServlet.zip


package com.edu.view;


import java.io.IOException;

import java.io.PrintWriter;

import java.sql.Timestamp;


import javax.servlet.ServletException;

import javax.servlet.annotation.WebServlet;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;


import com.edu.db.Address;

import com.edu.db.AddressDto;

import com.edu.db.AddressImpl;


/**

 * Servlet implementation class boardInsertServlet

 */

public class BoardInsertServlet extends HttpServlet {

private static final long serialVersionUID = 1L;

       

    /**

     * @see HttpServlet#HttpServlet()

     */

    public BoardInsertServlet() {

        super();

    }


/**

* @see HttpServlet#doGet(HttpServletRequest req, HttpServletResponse res)

*/

protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {

res.setContentType("text/html;charset=UTF-8");

PrintWriter out = res.getWriter();

out.print("<br/>");

AddressImpl address = new AddressImpl();

AddressDto dbNode = new AddressDto(); 

dbNode.setName("도도" + serialVersionUID);

dbNode.setAddress("행복시 행복동");

// 버그1: new Date() 사용안됨. (2020을 3920으로 인식함.) 

// 버그2: new Timestamp() 사용안됨. (2020을 3920으로 인식함.)

String userDate = "2020-02-01";

java.sql.Timestamp sqlDate = java.sql.Timestamp.valueOf(userDate);

dbNode.setBirthdate(sqlDate);

int result = address.insertAddress(dbNode);

AddressDto addressDto = address.getAddress(1);

out.println("<html><head><title>CRUD - Insert</title></head>");

out.println("<body><h2>MyBatis - Insert</h2>");

out.print("<br/>");

out.print("등록여부:" + result + "</br>");

out.print("<br/>");

out.print(addressDto.getNum() + "/" + addressDto.getName() + "/");

out.print(addressDto.getAddress() + "/" + addressDto.getBirthdate());

out.println("</body></html>");

out.close();

}

/**

* @see HttpServlet#doPost(HttpServletRequest req, HttpServletResponse res)

*/

protected void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {

doGet(req, res);

}


}


* 파일명: boardInsertServlet.java


[첨부(Attachments)]

BoardInsertServlet.zip



package com.edu.view;


import java.io.IOException;

import java.io.PrintWriter;

import java.sql.Timestamp;


import javax.servlet.ServletException;

import javax.servlet.annotation.WebServlet;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;


import com.edu.db.Address;

import com.edu.db.AddressDto;

import com.edu.db.AddressImpl;


/**

 * Servlet implementation class boardInsertServlet

 */

public class BoardDeleteServlet extends HttpServlet {

private static final long serialVersionUID = 1L;

       

    /**

     * @see HttpServlet#HttpServlet()

     */

    public BoardDeleteServlet() {

        super();

    }


/**

* @see HttpServlet#doGet(HttpServletRequest req, HttpServletResponse res)

*/

protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {

res.setContentType("text/html;charset=UTF-8");

PrintWriter out = res.getWriter();

out.print("<br/>");

AddressImpl address = new AddressImpl();

int result = address.deleteAddress(5);

AddressDto addressDto = address.getAddress(5);

out.println("<html><head><title>CRUD - Delete</title></head>");

out.println("<body><h2>MyBatis - Delete</h2>");

out.print("<br/>");

out.print("삭제여부:" + result + "</br>");

out.print("<br/>");

if ( addressDto != null ) {

out.print(addressDto.getNum() + "/" + addressDto.getName() + "/");

out.print(addressDto.getAddress() + "/" + addressDto.getBirthdate());

}

out.println("</body></html>");

out.close();

}


/**

* @see HttpServlet#doPost(HttpServletRequest req, HttpServletResponse res)

*/

protected void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {

doGet(req, res);

}


}



* 파일명: BoardDeleteServlet.java


[첨부(Attachments)]

BoardDeleteServlet.zip



package com.edu.view;


import java.io.IOException;

import java.io.PrintWriter;

import java.sql.Timestamp;


import javax.servlet.ServletException;

import javax.servlet.annotation.WebServlet;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;


import com.edu.db.AddressDto;

import com.edu.db.AddressImpl;


@WebServlet("/board/update.do")

public class BoardUpdateServlet extends HttpServlet {

private static final long serialVersionUID = 1L;

       

    /**

     * @see HttpServlet#HttpServlet()

     */

    public BoardUpdateServlet() {

        super();

    }


/**

* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)

*/

protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {

res.setContentType("text/html;charset=UTF-8");

PrintWriter out = res.getWriter();

out.print("<br/>");

AddressImpl address = new AddressImpl();

AddressDto dbNode = new AddressDto();

dbNode.setNum(3);

dbNode.setName("도도수정" + serialVersionUID);

dbNode.setAddress("행복시 행복동");


// 버그1: new Date() 사용안됨. (2020을 3920으로 인식함.) 

// 버그2: new Timestamp() 사용안됨. (2020을 3920으로 인식함.)

String userDate = "2020-07-01";

java.sql.Timestamp sqlDate = java.sql.Timestamp.valueOf(userDate);

dbNode.setBirthdate(sqlDate);

int result = address.updateAddress(dbNode);

AddressDto addressDto = address.getAddress(3);

out.println("<html><head><title>CRUD - Update</title></head>");

out.println("<body><h2>MyBatis - Update</h2>");

out.print("<br/>");

out.print("수정여부:" + result + "</br>");

out.print("<br/>");

out.print(addressDto.getNum() + "/" + addressDto.getName() + "/");

out.print(addressDto.getAddress() + "/" + addressDto.getBirthdate());

out.println("</body></html>");

out.close();

}


/**

* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)

*/

protected void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {

doGet(req, res);

}


}



* 파일명: BoardUpdateServlet.java


특징: web.xml으로 맵핑하지 않고, @WebServlet으로 어노테이션을 사용하여 매핑처리함.


[첨부(Attachments)]

BoardUpdateServlet.zip




6. 맺음글


순수한 JSP 기반의 MyBatis 프레임워크 사용방법에 대해서 소개해보았다.

많은 도움이 되었으면 좋겠다.


1. [JSP] 19. MyBatis-3.5.5 와 Maven / Servlet 연동하기 (Oracle 19g) - Java 방식, 2020-10-01

https://yyman.tistory.com/1434



[참고 자료(Reference)]


1. [Java, OpenJDK] Timestamp 형식 변환, https://infotake.tistory.com/16, Accessed by 2020-09-18, Last Modified 2018-09-13.

-> 참고 이유: Timestamp 명령 사용방법 참고함.


2. 내가 그리는 세상  DB(mysql)에 timestamp로 저장된 값 java에서 불러오기_getTimestamp(), https://yoonka.tistory.com/450, Accessed by 2020-09-18, Last Modified 2013-10-28.


3. [JSP] Mybatis 사용하기  또리야 개발하자, https://ddoriya.tistory.com/entry/JSP-Mybatis-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0, Accessed by 2020-09-17, Last Modified 2014-11-18.

-> 추천(60점 이상): 이 사이트의 글만 가지고 따라하면, 완벽하게 동작이 되진 않음. 몇 가지 보충을 해줘야 해서 추가적으로 검색하였음.
그래도 순수한 MyBatis 원리에 대해서 많은 영감을 얻었음.


4. Oracle와 mybatis 연동 실습, https://dlgkstjq623.tistory.com/228, Accessed by 2020-09-18, Last Modified 2019-06-05.

-> 추천(40점 이상): 이 사이트의 글을 이해하려면, Spring Framework 지식과 JSTL 지식이 있어야 함.

   기본적인 흐름 정도 파악하는데 참고하였음. (이론적인 느낌을 얻었음.)


5. MyBatis – 마이바티스 3 | 소개, https://mybatis.org/mybatis-3/ko/index.html, Accessed by 2020-09-18, Last Modified 2020-06-05.

-> 추천(20점 이상): 설명서가 조금 어렵게 되어 있음. 셋팅 파일을 가지고 셋팅한 후 설명서를 참고하면 도움이 될 수도 있음.


6. 4. Spring Boot Oracle DB 연동(JSP, MyBatis), https://dotheright.tistory.com/173, Accessed by 2020-09-18, Last Modified 2020-07-15.

-> 삽질하여 실패와 탐구 등의 횟수 기록이 담겨져 있음. ("삽질을 하게 된다.??" 이런 느낌을 보여줌.)

-> Spring Framework 기반으로 만든 소스코드를 소개하고 있음. (이 게시글 작성에 있어서 크게 영향을 주지 못함.)


7. [JSP] JSP에 MyBatis 연결하기, https://yuja-kong.tistory.com/8, Accessed by 2020-09-18, Last Modified 2018-04-17.

-> 추천(50점 이상): 순수한 JSP와 MyBatis 연결에 대해서 소개하고 있는데, 이 글을 작성할 수 있는 가능성을 만들어 줌.


8. JSP 서블릿 한글 세팅(한글 깨짐 해결 하기), https://developsd.tistory.com/100, Accessed by 2020-09-18, Last Modified 2019-05-18.

-> 추천(20점): 오라클DB(이하 "UTF-8 셋팅한 오라클")로 데이터를 불러오려고 했을 때, ?????라고 한글을 인식하지 못했음.

   간단한 명령어 하나로 해결하는 데 도움을 받았음. (가끔은 쉬운 게 어렵고, 어려운 게 쉬울 때도 있다는 생각이 듬.)


1. 파일의 인코딩 속성을 "UTF-8"으로 변경

2. response.setContentType("text/html;charset=UTF-8");


반응형

+ Recent posts