※ 아래 코드에 delete 시 동작 안하는 문제가 있어서 코드 수정했습니다.
[contact.xml]
<id name="id" type="long"> // int 에서 long 으로 변경
[Contact*.java]
private Long id; // 역시 int 에서 Long 으로 변경 당연히 setter/getter/param 다 변경
[ContactDAOImpl.java]
// ...delete(contact); 가 정상적으로 동작하지 않아 아래 처럼 변경.
this.sessionFactory.getCurrentSession().createQuery("delete Contact where id=:id").setLong("id", id).executeUpdate();
[수정된 Project]
proto.orm.zip
Spring MVC 에 다른 사이트의 HIbernate 예제 코드로 작성하였습니다.
- 해당 예제 코드를 그대로 사용할경우 안되는 부분이 있어서 직접 수정하여 반영합니다.
[Hibernate 예제코드]
[소스코드]
- Eclipse import 하시면 프로젝트 확인 가능 합니다.
※ import/export 방법은 아래 글 참고하세요.
http://jjeong.tistory.com/564
- 소스코드를 첨부 하였으므로 요약 정보만 기술 합니다.
[Table 생성]
Database : Mysql.protodb
CREATE TABLE CONTACTS
(
id INT PRIMARY KEY AUTO_INCREMENT,
firstname VARCHAR(30),
lastname VARCHAR(30),
telephone VARCHAR(15),
email VARCHAR(30),
created TIMESTAMP DEFAULT NOW()
);
[pom.xml]
<!-- spring framework jdbc 설정 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<!-- spring framework transaction 설정 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<!-- spring framework orm 설정 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<!-- hibernate dependency 설정 start -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>3.6.9.Final</version>
</dependency>
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.2.1</version>
</dependency>
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.15.0-GA</version>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.1</version>
</dependency>
<!-- hibernate dependency 설정 end -->
<!-- mysql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.18</version>
</dependency>
<!-- apache commons dbcp -->
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.2.2</version>
</dependency>
- dependency 관련 파일들은 이제 어느 정도 설정 하는데 무리가 없으시죠. 자세한 내용은 아래 링크에
[web.xml]
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring/root-context.xml
classpath:context/**/applicationContext*.xml
</param-value>
</context-param>
.... 중략
<filter>
<filter-name>openSessionInViewFilter</filter-name>
<filter-class>
org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>openSessionInViewFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
[applicationContext-hibernate.xml]
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jee="http://www.springframework.org/schema/jee" xmlns:lang="http://www.springframework.org/schema/lang"
xmlns:p="http://www.springframework.org/schema/p" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd
http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<bean id="messageSource"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename" value="classpath:messages/message" />
<property name="defaultEncoding" value="UTF-8" />
</bean>
<bean id="localeChangeInterceptor"
class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
<property name="paramName" value="lang" />
</bean>
<bean id="localeResolver"
class="org.springframework.web.servlet.i18n.CookieLocaleResolver">
<property name="defaultLocale" value="ko" />
</bean>
<bean id="handlerMapping"
class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<property name="interceptors">
<ref bean="localeChangeInterceptor" />
</property>
</bean>
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
p:location="classpath:configuration/hibernate/config.properties" />
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${jdbc.dialect}</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
<property name="mappingResources">
<list>
<value>/sql/hibernate/mapper/contact.xml</value>
</list>
</property>
</bean>
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="contactDAO" class="proto.orm.board.contact.dao.ContactDAOImpl">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
</beans>
- 간혹 아래와 같은 오류가 날때가 있습니다.
org.hibernate.HibernateException: No Session found for current thread
-> 이건 sessionFactory 설정을 잘못해서 나옵니다.
-> sessionFactory 를 중복 선언 하거나 (include 도니 파일 잘 찾아 보세요.)
-> web.xml 에 openSessionInViewFilter 설정이 빠져 있는지 확인 합니다.
Unable to instantiate default tuplizer
-> 이건 domain 객체에서 setter/getter 설정 오류 이거나 mapping 오류일 경우 발생 합니다.
-> domain 객체를 한번 검토해 보시고 hibernate mapping xml 에 선언한 내용과 일치 하는지도 확인해 보세요.
org.hibernate.hql.ast.QuerySyntaxException: xxxx is not mapped [FROM xxxx]
-> 이건 createQuery("FROM 도메인객체명") 으로 표기를 해야 하는데 간혹 Table 이른을 넣다 보면 오류가 납니다.
-> 본 예제에서는 Contact Object 이므로 createQuery("FROM Contact") 이라고 써줘야 합니다.
[config.properties]
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.dialect=org.hibernate.dialect.MySQLDialect
jdbc.url=jdbc:mysql://localhost:3306/protodb?autoReconnect=true
jdbc.username=root
jdbc.password=1234
[contact.xml]
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="proto.orm.board.contact.domain.Contact" table="contacts">
<id name="id" type="int">
<column name="id" />
<generator class="identity" />
</id>
<property name="firstname" type="string">
<column name="firstname" length="30" not-null="false" />
</property>
<property name="lastname" type="string">
<column name="lastname" length="30" not-null="false" />
</property>
<property name="telephone" type="string">
<column name="telephone" length="15" not-null="false" />
</property>
<property name="email" type="string">
<column name="email" length="30" not-null="false" />
</property>
<property name="created" type="timestamp">
<column name="created" not-null="false" />
</property>
</class>
</hibernate-mapping>
- 이 파일은 hibernate ref. 중 mapping 부분 참고하세요.
[ContactController.java]
더보기 접기
package proto.orm.board.contact.web;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import proto.orm.board.contact.domain.Contact;
import proto.orm.board.contact.service.ContactService;
@Controller
public class ContactController {
@Autowired
private ContactService contactService;
@RequestMapping("/index")
public String listContacts(Map<String, Object> map) {
map.put("contact", new Contact());
map.put("contactList", contactService.listContact());
return "contact";
}
@RequestMapping(value="/add", method=RequestMethod.POST)
public String addContact(@ModelAttribute("contact")
Contact contact, BindingResult result) {
contactService.addContact(contact);
return "redirect:/index";
}
@RequestMapping("/delete/{contactId}")
public String deleteContact(@PathVariable("contactId") int contactId) {
contactService.removeContact(contactId);
return "redirect:/index";
}
}
접기
[ContactServiceImpl.java]
더보기 접기
package proto.orm.board.contact.service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import proto.orm.board.contact.dao.ContactDAO;
import proto.orm.board.contact.domain.Contact;
@Transactional
@Service
public class ContactServiceImpl implements ContactService {
@Autowired
private ContactDAO contactDAO;
public void addContact(Contact contact) {
contactDAO.addContact(contact);
}
public List<Contact> listContact() {
return contactDAO.listContact();
}
public void removeContact(int id) {
contactDAO.removeContact(id);
}
}
접기
[ContactDAOImpl.java]
더보기 접기
package proto.orm.board.contact.dao;
import java.util.List;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import proto.orm.board.contact.domain.Contact;
@Repository
public class ContactDAOImpl implements ContactDAO {
private SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
public void addContact(Contact contact) {
this.sessionFactory.getCurrentSession().save(contact);
}
@SuppressWarnings("unchecked")
public List<Contact> listContact() {
System.out.println("SessionFactory is " + this.sessionFactory);
return this.sessionFactory.getCurrentSession().createQuery("FROM Contact").list();
}
public void removeContact(int id) {
Contact contact = (Contact) this.sessionFactory.getCurrentSession().load(Contact.class, id);
if ( null != contact ) {
this.sessionFactory.getCurrentSession().delete(contact);
}
}
}
접기
[Contact.java]
더보기 접기
package proto.orm.board.contact.domain;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name = "contacts")
public class Contact {
@Id
@Column(name = "ID")
@GeneratedValue
private int id;
@Column(name = "FIRSTNAME")
private String firstname;
@Column(name = "LASTNAME")
private String lastname;
@Column(name = "EMAIL")
private String email;
@Column(name = "TELEPHONE")
private String telephone;
@Column(name = "CREATED")
private Date created;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getFirstname() {
return firstname;
}
public void setFirstname(String firstname) {
this.firstname = firstname;
}
public String getLastname() {
return lastname;
}
public void setLastname(String lastname) {
this.lastname = lastname;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getTelephone() {
return telephone;
}
public void setTelephone(String telephone) {
this.telephone = telephone;
}
public Date getCreated() {
return created;
}
public void setCreated(Date created) {
this.created = created;
}
}
접기
[contact.jsp]
더보기 접기
<%@ page contentType="text/html;charset=utf-8" %>
<%@taglib uri="http://www.springframework.org/tags" prefix="spring"%>
<%@taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<html>
<head>
<title>Spring 3 MVC Series - Contact Manager | viralpatel.net</title>
</head>
<body>
<h2>Contact Manager</h2>
<form:form method="post" action="add.html" commandName="contact">
<table>
<tr>
<td><form:label path="firstname"><spring:message code="label.firstname"/></form:label></td>
<td><form:input path="firstname" /></td>
</tr>
<tr>
<td><form:label path="lastname"><spring:message code="label.lastname"/></form:label></td>
<td><form:input path="lastname" /></td>
</tr>
<tr>
<td><form:label path="email"><spring:message code="label.email"/></form:label></td>
<td><form:input path="email" /></td>
</tr>
<tr>
<td><form:label path="telephone"><spring:message code="label.telephone"/></form:label></td>
<td><form:input path="telephone" /></td>
</tr>
<tr>
<td colspan="2">
<input type="submit" value="<spring:message code="label.addcontact"/>"/>
</td>
</tr>
</table>
</form:form>
<h3>Contacts</h3>
<c:if test="${!empty contactList}">
<table class="data">
<tr>
<th>Name</th>
<th>Email</th>
<th>Telephone</th>
<th> </th>
</tr>
<c:forEach items="${contactList}" var="contact">
<tr>
<td>${contact.lastname}, ${contact.firstname} </td>
<td>${contact.email}</td>
<td>${contact.telephone}</td>
<td><a href="delete/${contact.id}">delete</a></td>
</tr>
</c:forEach>
</table>
</c:if>
</body>
</html>
접기
[참고사이트]