파일 관리 같은 경우 이 내용이 적용될 수 있습니다.
사원의 프로필을 관리할 때, 프로필 사진을 올리지 않을 경우도 있습니다.
이 때, DB에서 사원 테이블에 프로필 사진 관련 컬럼을 올리면 컬럼에 Null
값이 들어가 DB의 스토리지 자원을 낭비할 수 있습니다.
이런 경우에, 테이블을 분리하여 1:1 관계로 만들어 JOIN 을 통해 데이터를 가져오는 것이 좋을 것입니다.
표준 ( I/F, 공통 ) - 구현체 ( 구현체, 확장 )의 관계
JPA를 구현한 대표적인 프레임워크가 Hibernate
Hibernate : JPA 표준을 따르면서도, 자체적으로 추가 기능을 제공해줍니다.
객체-관계 매핑(ORM)해 SQL 쿼리 자동 생성
HQL (Hibernate Query Language): 객체 지향 쿼리 언어로, SQL과 유사하지만 객체를 대상으로 쿼리 작성
자동 데이터베이스 스키마 생성 및 업데이트 : hibernate.hbm2ddl.auto 속성 지정
캐싱 (Caching): : 1차캐시(Session 캐시)와 2차캐시 지원
자주 사용하는 데이터를 메모리에 저장하여 데이터베이스 접근 횟수를 줄임으로써 성능 향상
지연 로딩 (Lazy Loading) : 메모리 절약(필요할 때까지 데이터를 로드하지 않음)
자동 Dirty Checking : 객체 상태 변화를 자동으로 감지하여 데이터베이스에 반영
---------------------------------------
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.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
-->
@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;
...
|
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>
<mapping package="com.lec11.orm.jpa"/>
servlet-context.xml
설정 파일에 Entity를 스캔할 패키지를 지정해줄 수도 있다. (packagesToScan
프로퍼티 속성 )<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<property name="packagesToScan" value="com.lec11.orm.jpa"/>
application-properties
에서 하거나 @Configuration
을 통해 자바 클래스로 등록할 수도 있다.MyBatis는 Mapper를 사용한 인터페이스로 DB에 접근하여 사용하는 방식이고, Hibernate는 VO(Entity)를 테이블과 매핑하여 객체를 다룸으로써 DB에 접근합니다.
MyBatis는 map.xml에 SQL문을 꾸겨넣어 쓸 수 있기 때문에, 자유롭게 설정을 커스터마이징 할 수 있습니다.
Facade = 대문
인터페이스를 묶는 통합된 인터페이스
MyBats의 log-remix와 같은 라이브러리도 SL4FJ의 Facade에 맞게 통과하여 넘어가야 함.
각자의 패턴들을 규격화한 하나의 통일된 규격형태로 제공 ( Sl4fj )
인터페이스를 통합하기 위한 상향된 인터페이스
고사양 인터페이스, 다양한 형태로 사용하기 위한 상위 인터페이스
RequestFacade도, Client의 다양한 Request를 규격화해놓은 것
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("로그인-----");
}
}
}
<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>
psersistence.xml
)메서드 이름의 일부를 사용한 자동 쿼리 생성
메서드 접두사:
*findBy: 특정 조건에 맞는 엔티티를 검색
readBy: findBy와 동일한 기능
queryBy: findBy와 동일한 기능
countBy: 특정 조건에 맞는 엔티티의 개수를 카운트
getBy: 특정 조건에 맞는 엔티티를 검색
*deleteBy: 특정 조건에 맞는 엔티티를 삭제
removeBy: deleteBy와 동일한 기능
조건 키워드:
And: 여러 조건을 연결 (AND 연산)
Or: 여러 조건을 연결 (OR 연산)
Between, LessThan, GreaterThan, Like, NotLike, In, NotIn, True, False, OrderBy 등
JPA는 EntityManager를 쓴다.
EntityManager한테 맡긴다. ( JPQL 도 씀 )
@PersistenceContext
entityManager.createQuery(hql);
어찌되었던.. 자바 파일 안에 SQL을 넣는게 마음에 안듬
어노테이션, 골뱅이 써도 되지만, 자바 코드 안에 SQL 써도 되지만..
별로 복잡하지 않은 쿼리에 대해서는 메서드로 처리할 수 있지 않겠냐?
라는 느낌
그럼 이렇게 간단하게 쓸 수 있는 쿼리가 몇개가 있을까?
준비된 SQL이 있으면, MyBatis에게 꽃으면 그만인데..
기술력, 메모리 캐싱, 트랜잭션 관리 등에 대해서는 JPA가 편한게 사실
개발자가