[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&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&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 프레임워크 하나에만 많은 공부가 필요한 것 같다.
물론 전부 학습 할 수는 없다.
* 참고자료(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.