[ KOSTA 교육 44일차 ] 패키지 구조 | 파일 관리 assocation 관계 | ORM Framework - Hibernate & JPA | Hibernate 특징 | MyBatis vs Hibernate(JPA) | Hibernate 설정 | Facade Design Pattern과 Sl4fj | JPA | JPA의 메서드 이름으로 SQL 자동 생성

junjun·2024년 6월 30일
0

KOSTA

목록 보기
42/48
post-thumbnail

패키지 구조 종류

  • 계층형 패키지 구조
    • AOP를 적용할 Pointcut 메서드를 작성할 때 편리하다는 장점이 있다.
    • 어플리케이션의 흐름 및 가독성이 도메인형보다 좋음.
    • 소규모 프로젝트에 적합하다.
  • 도메인형 패키지 구조
    • 대규모 서비스, Micro-Service로 운영한다면 좋은 설계이다.
    • 추후 프로젝트 코드를 떼어서 따로 배포한다면 이렇게 패키지 구조를 짜는 것이 유리하기 때문이다.

1대1 관계와 assocation 관계

  • 파일 관리 같은 경우 이 내용이 적용될 수 있습니다.

  • 사원의 프로필을 관리할 때, 프로필 사진을 올리지 않을 경우도 있습니다.

  • 이 때, DB에서 사원 테이블에 프로필 사진 관련 컬럼을 올리면 컬럼에 Null 값이 들어가 DB의 스토리지 자원을 낭비할 수 있습니다.

  • 이런 경우에, 테이블을 분리하여 1:1 관계로 만들어 JOIN 을 통해 데이터를 가져오는 것이 좋을 것입니다.

JPA ( Java Persistence API )

  • 자바 표준 ORM ( Object-Relational Mapping ) 기술을 정의한 API

JPA와 Hibernate

  • 표준 ( I/F, 공통 ) - 구현체 ( 구현체, 확장 )의 관계

  • JPA를 구현한 대표적인 프레임워크가 Hibernate

  • Hibernate : JPA 표준을 따르면서도, 자체적으로 추가 기능을 제공해줍니다.

Hibernate의 특징

  • 객체-관계 매핑(ORM)해 SQL 쿼리 자동 생성

  • HQL (Hibernate Query Language): 객체 지향 쿼리 언어로, SQL과 유사하지만 객체를 대상으로 쿼리 작성

  • 자동 데이터베이스 스키마 생성 및 업데이트 : hibernate.hbm2ddl.auto 속성 지정

  • 캐싱 (Caching): : 1차캐시(Session 캐시)와 2차캐시 지원

    자주 사용하는 데이터를 메모리에 저장하여 데이터베이스 접근 횟수를 줄임으로써 성능 향상

  • 지연 로딩 (Lazy Loading) : 메모리 절약(필요할 때까지 데이터를 로드하지 않음)

  • 자동 Dirty Checking : 객체 상태 변화를 자동으로 감지하여 데이터베이스에 반영

Hibernate를 사용하기 위한 의존성

---------------------------------------
 pom.xml
---------------------------------------
		<!-- Hibernate Core -->
	    <dependency>
		    <groupId>org.hibernate</groupId>
		    <artifactId>hibernate-core</artifactId>
		    <version>5.4.33.Final</version>
		</dependency>
	    <!-- Hibernate EntityManager -->
		<dependency>
		    <groupId>org.hibernate</groupId>
		    <artifactId>hibernate-entitymanager</artifactId>
		    <version>5.4.33.Final</version>
		</dependency>
	    <!-- Hibernate JPA API
	    <dependency>
	        <groupId>org.hibernate.javax.persistence</groupId>
	        <artifactId>hibernate-jpa-2.1-api</artifactId>
	        <version>1.0.0.Final</version>
	    </dependency>  -->
	    <!-- JPA API -->
	    <dependency>
		    <groupId>javax.persistence</groupId>
		    <artifactId>javax.persistence-api</artifactId>
		    <version>2.2</version>
		</dependency>

Hibernate 기본 구성

  • MyBatis 때와 마찬가지로, Hibernate 자체의 구성 파일(XML)을 만들어줄 수 있습니다.
    • 설정 파일 (hibernate.cfg.xml)
    • Entity 파일(UserVO.java)

1. 설정 파일 ( Hibernate.cfg.xml )

<!-- hibernate.cfg.xml -->
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
	<hibernate-configuration>
	    <session-factory>
	        <!-- DB연결정보 Database connection settings -->
	        <property name="hibernate.connection.driver_class">org.h2.Driver</property>
        	<property name="hibernate.connection.url">jdbc:h2:mem:test;DB_CLOSE_DELAY=-1</property>
        	<property name="hibernate.connection.username">sa</property>
        	<property name="hibernate.connection.password"></property>
	
	        <!-- JDBC connection pool settings ... using built-in test pool -->
	        <property name="hibernate.c3p0.min_size">5</property>
	        <property name="hibernate.c3p0.max_size">20</property>
	        <property name="hibernate.c3p0.timeout">300</property>
	        <property name="hibernate.c3p0.max_statements">50</property>
	        <property name="hibernate.c3p0.idle_test_period">3000</property>
			
			<!-- Hibernate 설정 =============================================== -->
	        <!-- SQL방언(문법,기능집합) Select our SQL dialect -->
	        <property name="hibernate.dialect">org.hibernate.dialect.H2Dialect</property>
	
	        <!-- 로그출력 Echo all executed SQL to stdout -->
	        <property name="hibernate.show_sql">true</property>
	
	        <!-- 스키마처리방식 Drop and re-create the database schema on startup -->
	        <property name="hibernate.hbm2ddl.auto">update</property>
			<!-- ============================================================= -->
			
	        <!-- 엔디티스캔범위 Names the annotated entity class -->
	        <mapping class="com.example.MyEntity"/>
	    </session-factory>
	</hibernate-configuration>


<!--
주요 Hibernate 방언 목록
H2 Database: org.hibernate.dialect.H2Dialect
MySQL: org.hibernate.dialect.MySQLDialect
MySQL 5: org.hibernate.dialect.MySQL5Dialect
MySQL 8: org.hibernate.dialect.MySQL8Dialect
Oracle 10g: org.hibernate.dialect.Oracle10gDialect
Oracle 12c: org.hibernate.dialect.Oracle12cDialect
PostgreSQL: org.hibernate.dialect.PostgreSQLDialect
SQL Server 2008: org.hibernate.dialect.SQLServer2008Dialect
SQL Server 2012: org.hibernate.dialect.SQLServer2012Dialect
-->

2. VO(Entity) 클래스 ( JPA 어노테이션 방식 ) | Entity Scan 방식

@Data  // lombok
@ToString // lombok
@Entity // Hibernate (ORM)
@Table(name="users3") // ORM, 설정 안할 경우 기본 테이블 명은 클래스 명
public class UserVO {
	
		@Id
		@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "users3_seq_gen")
		@SequenceGenerator(name = "users3_seq_gen", sequenceName = "users3_seq", allo
		@Column(name = "user_seq")
		private Long userSeq;
		
		@Column(name = "user_name", length = 20)
		private String userName;
		...
|
  • 물론 Entity에 @Data 어노테이션을 다는 것은 좋지 않다. ( = Setter )
    • Entity 자체에게 책임을 넘겨주도록 설계하는 것이 더 객체를 객체답게 사용하는 것
  • 위의 Entity 클래스를 정의해둔 뒤에, Hibernate.cfg.xml 설정 파일에 엔티티 클래스가 위치한 패키지를 지정한다. ( MyBatis의 매퍼 등록 방식과 비슷하다 )
---------------------------------------
 엔티티 스캔 방법
---------------------------------------
1) VO클래스에 @Entity 어노테이션 사용
	
	@Data
	@ToString
	@Entity
	@Table(name = "users3")
	public class UserVO {
	    
	    @Id
	    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "users3_seq_gen")
	    @SequenceGenerator(name = "users3_seq_gen", sequenceName = "users3_seq", allocationSize = 1)
	    @Column(name = "user_seq")
	    private Long userSeq;
	    ~~
	}
	
2) hibernate.cfg.xml 설정 파일에 엔티티 클래스가 위치한 패키지 지정 
        <mapping package="com.lec11.orm.jpa"/>
        
3) spring-context.xml 설정 파일에 packagesToScan 속성 사용
	 <bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
		<property name="packagesToScan" value="com.lec11.orm.jpa"/>
		~~~
	 </bean>
Hibernate 자체의 설정에 Entity 등록
<mapping package="com.lec11.orm.jpa"/>
  • 혹은 Spring의 servlet-context.xml 설정 파일에 Entity를 스캔할 패키지를 지정해줄 수도 있다. (packagesToScan 프로퍼티 속성 )
    • 설정을 중앙집중화하기 위해, hibernate의 설정 파일을 버리고 spring에 통합할 것이다. (MyBatis 때와 마찬가지)
Spring의 servlet-context.xml 설정에 Entity를 등록
<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
   <property name="packagesToScan" value="com.lec11.orm.jpa"/>
  • 이렇게 함으로써 Hibernate의 SessionFactory에게 Entity로 등록할 클래스들이 모인 패키지 정보를 넘겨줄 수 있다.
  • 이러한 설정은 Spring Legacy에서는 XML을 통해 등록할 수 있고, 스프링 부트 프로젝트에서는 application-properties에서 하거나 @Configuration을 통해 자바 클래스로 등록할 수도 있다.

ORM - MyBatis vs Hibernate(JPA)

  • MyBatis는 Mapper를 사용한 인터페이스로 DB에 접근하여 사용하는 방식이고, Hibernate는 VO(Entity)를 테이블과 매핑하여 객체를 다룸으로써 DB에 접근합니다.

  • MyBatis는 map.xml에 SQL문을 꾸겨넣어 쓸 수 있기 때문에, 자유롭게 설정을 커스터마이징 할 수 있습니다.

Facade Pattern & Slf4j

  • Facade = 대문

  • 인터페이스를 묶는 통합된 인터페이스

    • 공통된 표준들을 하나의 규격으로 묶은 것
    • 로깅 메시지들의 스펙들을 모아 규격화
  • MyBats의 log-remix와 같은 라이브러리도 SL4FJ의 Facade에 맞게 통과하여 넘어가야 함.

    • logback 또한 SL4FJ의 ㄱ현체
  • 각자의 패턴들을 규격화한 하나의 통일된 규격형태로 제공 ( Sl4fj )

  • 인터페이스를 통합하기 위한 상향된 인터페이스

  • 고사양 인터페이스, 다양한 형태로 사용하기 위한 상위 인터페이스

  • RequestFacade도, Client의 다양한 Request를 규격화해놓은 것

Spring Container의 도움없이, Hibernate 자체 구현체로 DB와 통신할 수 있다. ( MyBatis와 마찬가지 )

public class CtxHibernateCallTest {

		/**
			기능 : xml을 읽어 해당 설정에 있는 클래스들의 인스턴스 초기화
				<interface>             <class>
				BeanFactory             XmlBeanFactory
				ApplicationContext      ClassPathXmlApplicationContext
				                        FileSystemXmlApplicationContext
				WebApplicationContext   XmlWebApplicationContext
		**/
		
		public static void main(String[] args){
		
			/**
			    Hibernate는 SQL문을 자동 생성할 때, 내부적으로
			    테이블/컬럼명을 고유하게 식별하고 충돌을 방지하기 위해
			    내부적으로 생성한 고유한 식별자 Alias를 생성하여 사용한다.
					 
			Hibernate: 
			select uservo0_.user_seq as user_seq1_0_0_, 
					uservo0_.regdate as regdate2_0_0_, 
					uservo0_.user_gubun as user_gubun3_0_0_, 
					uservo0_.user_id as user_id4_0_0_, 
					uservo0_.user_name as user_name5_0_0_, 
					uservo0_.user_pw as user_pw6_0_0_ 
			from users3 uservo0_ 
					where uservo0_.user_seq=?
					 
			 **/
			 
			 // SessionFactory 생성
			 SessionFactory sessionFactory = new Configuration()
									 .configure("hibernate-context-lec10.xml")
									 .buildSessionFactory();
			 
			 Session session = sessionFactory.openSession();
		  
		   try {
			   // Begin a transaction
			   Transaction tx = session.beginTransaction();
			   
			   List<UserVO> users = session.createCriteria(UserVO.class).list();
			   for(UserVO user : users){
					  System.out.println(user);
			   }
			   
			   System.out.println("로그인-----");
		   }
		}
}

@Entity 설정을 XML을 통해 할 수도 있다.

<hibernate-mapping package="com.lec10.orm.hibernate">
 	<!-- @Entity와 같다. ( Hibernate : Mybatis 방식 및 JPA 방식 둘 다 지원 ) -->
    <!-- <class name="UserVO" table="users3">
        <id name="userSeq" column="user_seq" />
        <property name="userId" column="user_id" />
        <property name="userPw" column="user_pw" />
        <property name="userName" column="user_name" />
        <property name="userGubun" column="user_gubun" />
        <property name="regdate" column="regdate" />
    </class> -->
</hibernate-mapping>
  • MyBatis의 mapper 방식과 비슷하다.
  • 과거에 가능했는데, Hibernate 4버전 기준으로 적용되지 않는다.
  • 이렇게 XML을 통해 @Entity 클래스를 선언하는 것이 가능하다는 것을 보여주기 위한 예제이다.
  • (개인적 생각) Hibernate는 JPA와 MyBatis의 중간 어디쯤 있는 것 같은 느낌이다.

JPA

  • 객체-관계 매핑(ORM) 표준화
  • JPQL ( Java Persistence Query Language)
    • 객체지향 쿼리 언어, SQL과 유사하지만
    • JPQL ( Java Persistence Query Language ) : 객체 지향 쿼리 언어, SQL과 유사 [ cf. HQL ]
  • Hibernate : 쿼리 자동 생성, 캐싱(메모리 효율) / 처리 시간 단축 효과
  • 표준화, 독립적 ( I/F )

  • JPA 자체 설정 파일 (psersistence.xml )

JPA - 메서드 이름을 사용하여 자동 쿼리 생성


메서드 이름 규칙

메서드 이름의 일부를 사용한 자동 쿼리 생성

메서드 접두사:
*findBy: 특정 조건에 맞는 엔티티를 검색
readBy: findBy와 동일한 기능
queryBy: findBy와 동일한 기능
countBy: 특정 조건에 맞는 엔티티의 개수를 카운트
getBy: 특정 조건에 맞는 엔티티를 검색

*deleteBy: 특정 조건에 맞는 엔티티를 삭제
removeBy: deleteBy와 동일한 기능

조건 키워드:
And: 여러 조건을 연결 (AND 연산)
Or: 여러 조건을 연결 (OR 연산)
Between, LessThan, GreaterThan, Like, NotLike, In, NotIn, True, False, OrderBy 등

SessionFactory는 Hibernate의 기술이다.

JPA는 EntityManager를 쓴다.

  • EntityManager한테 맡긴다. ( JPQL 도 씀 )

    • @PersistenceContext
      • entityManager에게 좀 더 복잡한 쿼리를 맡긴다.
      • entityManager.createQuery(hql);
  • 어찌되었던.. 자바 파일 안에 SQL을 넣는게 마음에 안듬

  • 어노테이션, 골뱅이 써도 되지만, 자바 코드 안에 SQL 써도 되지만..
    별로 복잡하지 않은 쿼리에 대해서는 메서드로 처리할 수 있지 않겠냐?
    라는 느낌

  • 그럼 이렇게 간단하게 쓸 수 있는 쿼리가 몇개가 있을까?

  • 준비된 SQL이 있으면, MyBatis에게 꽃으면 그만인데..

    • 알파로 필요한 쿼리는 @Query 로 SQL 넣어야함. ( em.createQuery 를 쓰면 됨 )
  • 기술력, 메모리 캐싱, 트랜잭션 관리 등에 대해서는 JPA가 편한게 사실

  • 개발자가

JPA, Hibernate

  • 만들어진 쿼리가 있음에도 불구하고,
    Mapper와 Repository를 만드느라 좀 고생..

0개의 댓글