본문 바로가기
Spring/이론

Hibernate with Spring

by 모스키토끼 2020. 4. 19.

※ Hibernate 적용 전 상식!

- Spring MVC 프로젝트 구조

- 각각 패키지 안에 있는 클래스에 쓰는 annotation
: @Controller @Repository @ Entity @ Service

- 클래스들은 classes 폴더에. war 파일로 패키징 돼서 디플로이 된다.

 

★ Integrating Hibernate with the Spring Framework

1. Maven Dependencies

: Spring - spring-orm , Hibernate - hibernate-core

<!– Spring-->
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-orm</artifactId>
  <version>${org.springframework-version}</version>
</dependency>

<!– Hibernate ->
<dependency>
  <groupId>org.hibernate</groupId>
  <artifactId>hibernate-core</artifactId>
  <version>5.2.12.Final</version>
</dependency>

2. Hibernate configuration (dao-context.xml)

- configuring DataSource Bean

<context:property-placeholder location="/WEB-INF/props/jdbc.properties" />
<context:annotation-config></context:annotation-config>

<context:component-scan base-package="DAO 페키지명">
</context:component-scan>

<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>
  • dao 클래스는 내가 만든 Source이므로 annotation만 사용하면 dao 클래스라는 것을 Spring이 알 수 있다.
  • BasicDataSource는 라이브러리에 들어있는 소스코드 이므로 xml을 사용해서 빈으로 등록하는 것
    (굳이 소스에 들어가 보지 않아도 되기 때문에) 

- Configuring SessionFactory Bean

<bean id="sessionFactory"
	class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
  <property name="dataSource" ref="dataSource"></property>
  <property name="packagesToScan">
    <list>
      <value>Model 페키지명</value>
    </list>
  </property>

  <property name="hibernateProperties">
    <props>
      <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
      <prop key="hibernate.hbm2ddl.auto">create</prop>
      <prop key="hibernate.show_sql">true</prop>
      <prop key="hibernate.format_sql">false</prop>
    </props>
  </property>
</bean>
  • LocalSessionFacotryBean
    • dataSource: 액세스 할 데이터 소스
      (ref에 들어가는 값은 앞에서 등록한 빈(dataSource) id와 같아야 된다.)
    • packagesToScan: Hibernate가 지정된 패키지 아래에 있는 ORM annotation이 붙은 도메인 객체를 스캔한다.
  • hibernateProperties
    • Hibernate에 대한 구성 세부사항 설정
    • hbm2ddl.auto: Hibernate가 실행될 때마다 매핑 설정을 DB 스키마에 적용
      • create:
        - SessionFacotry가 실행될 때마다 스키마를 지웠다가 다시 생성 -> data가 다 날아감(개발할 때 사용)
      • create-drop:
        - SessionFactory가 내려갈 때마다 스키마를 지웠다가 다시 생성
      • update:
        - 도메인 객체 구성과 스키마를 비교해 필요한 테이블이나 칼럼을 객체에 맞춰서 스키마를 변경한다.
        -> data 쌓임!
      • validate:
        - 도메인 객체와 스키마가 같은 지 확인하고 다르면 예외로 빠진다.
    • show_sql: 말 그대로 hibernate가 만들어내는 sql를 볼 것이냐
    • format_sql: 여러 줄로 포맷해서 이쁘게 볼 것이냐를 설정.
      • true: 이쁘게 포맷!
      • false: 한 줄로 쭉 나온다.

※ hibernateProerties를 설정하고 나서 id가 sessionFactory라는 빈을 등록!

 

- Configuring TransactionManger Bean

<tx:annotation-driven transaction-manager="transactionManager" />

<bean id="transactionManager"
	class="org.springframework.orm.hibernate5.HibernateTransactionManager">
  <property name="sessionFactory" ref="sessionFactory"></property>
</bean>

 

  • HibernateTransationManager: 트랜잭션 관리
  • transaction은 begin으로 시작하고 commit으로 끝난다.
  • Spring은 AOP를 (before advice(begin) after advice(commit)) 사용
  • @Transactional을 클래스 레벨에 적용했기 때문에 그 밑에 있는 메서드에 전부 적용된다.
    -> before, after advice 자동 삽입
  • 클래스 앞부분에 springframework가 붙어있으면 springframe에서 지원해주는 클래스


3. Mapping Model Class using Annotations

- Object Tier vs Database element

Object Tier element Database Tier element
Entity class Database table
Field of entity class Database table column
Entity instance Database table row

- JPA (Java Persistence API)
: 일종의 spec(API를 이런 식으로 구현하면 좋겠다) -> Hiberante는 JPA를 실제 구현한 것.

  • JPA Annotation
    • @Entity:
      - Entity bean을 선언
      (Entity bean이란? hibernate에 의해서 DB에 저장될 수 있는 bean)
    • @Table:
      - 기본적으로 테이블 명은 클래스명으로 가져가지만 이 Annotation으로 오버 라이딩해줄 수 있다.
    • @Id
      - primary key를 설정하는 Annotation
    • @GeneratedValue
      - key를 자동 생성하는 Annotation, 디폴트 값은 Auto
      - Auto 설정: mysql에서 hibernate 4는 IDENTITYhibernate 5에서는 Table로 만들어짐
      ( IDENTITY: 자동 증가 db column을 사용한다는 뜻 )
      ( table로 만들어진다는 의미: db에 primary key를 만들기 위해 테이블을 사용한다는 뜻
      -> hibernate_sequence라는 테이블 )

    • @Column
      - 속성을 table column과 맵핑하는 데 사용.
      - Bean property에 길이, NULL 입력 가능 및 uniqueness를 지정 가능.
  • 예시 코드
@Entity
@Table(name="product")
public class Product {

@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="product_id")
private int id;

private String name;
private String category;
private double price;
private String manufacturer;
private int unitInStock;
private String description;

@Transient
private MultipartFile productImage;

private String imageFilename;
}

 

  • @Transient(persistence와 반대말)
    - 저장하지 않을 필드에 적용하는 annotation
    - 언제 사용되나...
    -> 동영상이나 이미지는 db에 저장하지 않는다(File Server에 저장) 
    -> db에는 filename만 저장 (경로만 저장)
    -> 따라서 이미지 자체는 저장하지 않으므로 이 annotation을 사용 

4. DAO

- 이전에 사용했던 JDBC는 이제 필요 x, Hibernate로 대체!!

- CRUD 구현

@Repository
@Transactional
public class ProductDao {

    @Autowired
    private SessionFactory sessionFactory;
    
    public Product getProductById(int id) {
        Session session = sessionFactory.getCurrentSession();
        Product product = (Product) session.get(Product.class, id);

        return product;
    }

  @SuppressWarnings("unchecked")
  public List<Product> getProducts() {
	Session session = sessionFactory.getCurrentSession();
        Query query = session.createQuery("from Product");
        List<Product> productList =  query.list();

        return productList;
  }

  public void addProduct(Product product) {
        Session session = sessionFactory.getCurrentSession();
        session.saveOrUpdate(product);
        session.flush();
  }

  public void deleteProduct (Product product) {
        Session session = sessionFactory.getCurrentSession();
        session.delete(product);
        session.flush();
  }


  public void editProduct(Product product) {
	 Session session = sessionFactory.getCurrentSession();
        session.saveOrUpdate(product);
        session.flush();
  }
}

 

  • SessionFactory:
    - 앞에서 bean으로 만들어 놨기 때문에 @Autowired로 주입해준다.
    (@Autowired는 타입을 보고 주입을 한다.), SessionFactory bean을 싱글톤으로 만들어 놨다.
  • @SuppressWarnings
    - List와 list()는 타입이 다르기 때문에 warning을 내지 마라(중요하지 않음)
  • flush():
    - cache에 있는 값을 db에 반영시키는 것
    (자주 flush를 하면 performance에 문제가 있다.)

 

'Spring > 이론' 카테고리의 다른 글

Restful Web Service with Spring  (0) 2020.04.20
Restful Web Service  (0) 2020.04.19
Entity Relationships  (0) 2020.04.17
Hibernate  (0) 2020.04.10
Apache Tiles  (0) 2020.04.08

댓글