문서의 이전 판입니다!
@Entity : JPA가 관리함을 의미 public, protected 생성자, 기본 생성자 필수 @Table(name = "데이터베이스 테이블명") 실행 시점에 테이블 자동 생성 가능 create, create-drop, update, validate, auto, none 개발 초기 단계는 create, update 테스트 서버는 update, validate 스테이징, 운영 서버 validate, none @Column의 옵션은 JPA 로직과는 상관이 없고, 생성시 ddl에 영향을 줌 updatable = false, 업데이트시에 업데이트 하지 않음 nullable = false unique = true, 생성시 이름이 sql은 date=날짜, time=시간, tiemstamp만 있음 GeneratorType.IDENTIFY persist()하면 쿼리가 실행됨 GeneratorType.SEQUENCE 트랜잭션을 해야해야 쿼리가 실행됨 실전 예제
'객체지향 설계의 목표는 자율적인 객체들의 협력 공동체를 만드는 것이다.' - 조영호(객체지향의 사실과 오해), 오브젝트 JPA 포인터 역할 양방향 연관관계의 주인 객체와 테이블의 차이를 이해해야 됨 테이블은 외래키만으로 양방향이 모두 적용됨(조인...) 객체는 그렇지 않음 양방향, 단방향... 양방향이 좋은가? 기본적으로 단방향으로 하는게 좋다. 설계시에 단방향 매핑만으로 이미 연관관계 매핑 완료하자 개발시에 꼭 필요하면 추가 하자.
// 양쪽값 public void addMember(MemberHello member) { member.setTeam(this); members.add(member); } // 양쪽 값 public void changeTeam(Team team) { this.team = team; team.getMembers().add(this); // 연관관계 편의 메소드 }
관계형 데이터베이스는 상속관계가 없다 객체는 상속관계는 데이터 베이스에서는 조인, 단일 테이블, 각각테이블로 구현이 가능함 기본 전략은 단일 테이블 @MappedSuperclass - 자주 애용하자 테이블과 관계가 없고 단순히 엔티티가 공통으로 사용하는 매핑 정보를 모으는 역할 abstract(추상 클래스)로 사용 주로 등록일, 수정일, 등록자, 수정자 같은 전체 엔티티에서 공통으로 적용하는 정보를 모을 때 사용 @Entity 클래서는 엔티티나 @MappedSuperclass로 지정한 클래스만 상속 가능
멤버를 조회할때 팀도 함께 조회를 해야할까? em.getReference() // 프록시 클래스 실제 클래스를 상속 받아서 만들어짐 실제 클래스와 겉 모양이 같다. 특징 프록시 객체는 처음 사용할 때 한 번만 초기화(DB에서 가져와 프록시 객체를 초기화 할 때, 프록시 객체가 실제 엔티티로 바뀌는 것은 아니고, 초기화 이후 프록시 객체를 통해서 실제 엔티티에 접근 가능 프록시 객체는 원본 엔티티를 상속받음, 따라서 타입 체크시 == 대신 instanceof 사용해야 됨 영속성 컨텍스트에 엔티티가 있으면 em.getReference()를 호출해도 실제 엔티티 반환(프록시 아님) 영속성 컨텍스트의 도움을 받을 수 없는 준영속 상태일 때, 프록시를 초기화하면 문제 발생 JPA내에서는 프록시든, 객체든 항상 == true 임을 보장함 프록시 인스턴스의 초기화 여부 확인 PersistenceUnitUtil.isLoaded(Object entity) 프록시 클래스 확인 방법 entity.getClass().getName() 출력 프록시 강제 초기화, JPA는 강제 초기화가 없음 org.hibernate.Hibernate.initialize(entity); 즉시 로딩(EAGER), 지연 로딩(LAZY) 실무에서 가급적 지연 로딩만 사용 즉시 로딩은 JPQL에서 N+1 문제 발생 @ManyToOne, @OneToOne은 기본이 즉시 로딩 -> LAZY로 설정 @OneToMany, @ManyToMany는 기본이 지연 로딩 @필요하면 Fetch join, annotation, 배치 사이즈로 사용함 모든 연관관계에 지연 로딩을 사용하라 실무에서 즉시 로딩을 사용하지 마라!, JPQL fetch 조인이나, 엔티티 그래프 기능을 사용해라! 즉시 로딩은 상상하지 못한 쿼리가 나간다.
영속성 전이(CASCADE)
영속성 전이는 연관관계를 매핑하는 것과 아무 관련이 없음 다만 연관된 엔티티도 함께 영속화하는 편리함을 제공할 뿐 CASCADE.ALL or CASCADE.PERSIST를 주로 사용 게시판 - 첨부 파일의 경우 처럼 거의 라이프사이클이 같을 때 유용하게 사용 소유자가 하나일때 사용 고아 객체 orphanRemoval = true 연결고리가 없어졌을때 삭제 됨 참조하는 곳이 하나일 때 사용해야 됨 특정 엔티티가 개인 소유할 때 사용 (@OneToOne, @OneToMany만 가능)
Tip
아래 코드에서 3곳만 고치면 된다.
<property name=“dataSource” ref=“” />
<property name=“packagesToScan” value=“” >
<prop key=“hibernate.dialect”>
<?xml version="1.0" encoding="utf-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"> <!-- 컨테이너가 관리하는 EntityManager 생성, @PersistenceContext와 함께 사용 --> <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="dataSource" ref="egov.dataSource" /> <!-- 어노테이션 매핑정보 스캔 --> <property name="packagesToScan" value="com" /> <!-- 구현체별 자체 기능을 표준화 --> <property name="jpaVendorAdapter"> <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> <property name="showSql" value="true" /> <property name="generateDdl" value="true" /> </bean> </property> <!-- persistence.xml 설정정보와 함께 사용가능 --> <property name="jpaProperties"> <props> <!-- <prop key="hibernate.ejb.naming_strategy">org.hibernate.cfg.EJB3NamingStrategy</prop> --> <prop key="hibernate.ejb.naming_strategy">org.hibernate.cfg.ImprovedNamingStrategy</prop> <!-- hibernate 5 버전에서의 세팅 (4 버전은 위에껄 사용)- <prop key="hibernate.naming.implicit-strategy">org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl</prop> <prop key="hibernate.naming.physical-strategy">org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl</prop> --> <prop key="hibernate.hbm2ddl.auto">validate</prop> <prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop> <prop key="hibernate.show_sql">true</prop> <prop key="hibernate.format_sql">true</prop> <prop key="hibernate.use_sql_comments">true</prop> <prop key="hibernate.jdbc.batch_size">5</prop> </props> </property> </bean> </beans>
DB2 | org.hibernate.dialect.DB2Dialect |
DB2 AS/400 | org.hibernate.dialect.DB2400Dialect |
DB2 OS390 | org.hibernate.dialect.DB2390Dialect |
PostgreSQL | org.hibernate.dialect.PostgreSQLDialect |
MySQL5 | org.hibernate.dialect.MySQL5Dialect |
MySQL5 with InnoDB | org.hibernate.dialect.MySQL5InnoDBDialect |
MySQL with MyISAM | org.hibernate.dialect.MySQLMyISAMDialect |
Oracle (any version) | org.hibernate.dialect.OracleDialect |
Oracle 9i | org.hibernate.dialect.Oracle9iDialect |
Oracle 10g | org.hibernate.dialect.Oracle10gDialect |
Oracle 11g | org.hibernate.dialect.Oracle10gDialect |
Sybase | org.hibernate.dialect.SybaseASE15Dialect |
Sybase Anywhere | org.hibernate.dialect.SybaseAnywhereDialect |
Microsoft SQL Server 2000 | org.hibernate.dialect.SQLServerDialect |
Microsoft SQL Server 2005 | org.hibernate.dialect.SQLServer2005Dialect |
Microsoft SQL Server 2008 | org.hibernate.dialect.SQLServer2008Dialect |
SAP DB | org.hibernate.dialect.SAPDBDialect |
Informix | org.hibernate.dialect.InformixDialect |
HypersonicSQL | org.hibernate.dialect.HSQLDialect |
H2 Database | org.hibernate.dialect.H2Dialect |
Ingres | org.hibernate.dialect.IngresDialect |
Progress | org.hibernate.dialect.ProgressDialect |
Mckoi SQL | org.hibernate.dialect.MckoiDialect |
Interbase | org.hibernate.dialect.InterbaseDialect |
Pointbase | org.hibernate.dialect.PointbaseDialect |
FrontBase | org.hibernate.dialect.FrontbaseDialect |
Firebird | org.hibernate.dialect.FirebirdDialect |
Tip
아래 코드에서 한개만 고치면 된다.
<jpa:repositories base-package=“”>
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:jpa="http://www.springframework.org/schema/data/jpa" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd"> <jpa:repositories base-package="com"></jpa:repositories> </beans>
<properties> <egovframework.jpa.version>3.7.0</egovframework.jpa.version> <hibernate.version>4.3.11.Final</hibernate.version> </properties> <dependencies> <dependency> <groupId>egovframework.rte</groupId> <artifactId>egovframework.rte.psl.data.jpa</artifactId> <version>${egovframework.jpa.version}</version> </dependency> <!-- Hibernate --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>${hibernate.version}</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>5.4.2.Final</version> </dependency> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-jpa</artifactId> <version>1.11.10.RELEASE</version> <exclusions> <exclusion> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> </exclusion> <exclusion> <groupId>org.slf4j</groupId> <artifactId>jcl-over-slf4j</artifactId> </exclusion> </exclusions> </dependency> </dependencies>