PowerPoint 프레젠테이션

Similar documents
@OneToOne(cascade = = "addr_id") private Addr addr; public Emp(String ename, Addr addr) { this.ename = ename; this.a

Spring Data JPA Many To Many 양방향 관계 예제

Spring Boot/JDBC JdbcTemplate/CRUD 예제

- JPA를사용하는경우의스프링설정파일에다음을기술한다. <bean id="entitymanagerfactory" class="org.springframework.orm.jpa.localentitymanagerfactorybean" p:persistenceunitname=

내장서버로사용. spring-boot-starter-data-jpa : Spring Data JPA 사용을위한설정 spring-boot-devtools : 개발자도구를제공, 이도구는응용프로그램개발모드에서유 용한데코드가변경된경우서버를자동으로다시시작하는일들을한다. spri

Spring Boot

rmi_박준용_final.PDF

* Factory class for query and DML clause creation * tiwe * */ public class JPAQueryFactory implements JPQLQueryFactory private f

Web Application을 구성하는 패턴과 Spring ROO의 사례


13주-14주proc.PDF

PowerPoint 프레젠테이션

I T C o t e n s P r o v i d e r h t t p : / / w w w. h a n b i t b o o k. c o. k r

Mobile Service > IAP > Android SDK [ ] IAP SDK TOAST SDK. IAP SDK. Android Studio IDE Android SDK Version (API Level 10). Name Reference V

<session-factory> <property name="hibernate.connection.driver_class">oracle.jdbc.driver.oracledriver</property> <property name="hibernate.connection.u

10.ppt

표준프레임워크로 구성된 컨텐츠를 솔루션에 적용하는 것에 문제가 없는지 확인

비긴쿡-자바 00앞부속

untitled

MasoJava4_Dongbin.PDF

Connection 8 22 UniSQLConnection / / 9 3 UniSQL OID SET

thesis

쉽게 풀어쓴 C 프로그래밊

Interstage5 SOAP서비스 설정 가이드

교육2 ? 그림

09-interface.key

PowerPoint 프레젠테이션

<property name="configlocation" value="classpath:/egovframework/sqlmap/example/sql-map-config.xml"/> <property name="datasource" ref="datasource2"/> *

슬라이드 1

01-OOPConcepts(2).PDF

어댑터뷰

untitled

파워포인트 템플릿

No Slide Title

Chap7.PDF

DIY 챗봇 - LangCon

FileMaker 15 ODBC 및 JDBC 설명서

07 자바의 다양한 클래스.key

thesis

FileMaker ODBC and JDBC Guide

Analytics > Log & Crash Search > Unity ios SDK [Deprecated] Log & Crash Unity ios SDK. TOAST SDK. Log & Crash Unity SDK Log & Crash Search. Log & Cras

( )부록

예제 2) Test.java class A intvar= 10; void method() class B extends A intvar= 20; 1"); void method() 2"); void method1() public class Test 3"); args) A

FileMaker ODBC and JDBC Guide

05-class.key

Microsoft PowerPoint - 2강

02 C h a p t e r Java

교육자료

PowerPoint Presentation

fundamentalOfCommandPattern_calmglow_pattern_jstorm_1.0_f…

14-Servlet

API STORE 키발급및 API 사용가이드 Document Information 문서명 : API STORE 언어별 Client 사용가이드작성자 : 작성일 : 업무영역 : 버전 : 1 st Draft. 서브시스템 : 문서번호 : 단계 : Docum

Modern Javascript

ibmdw_rest_v1.0.ppt

Design Issues

¾Æ½Ã¾ÆÀú³Î8È£-ÅëÇÕ

과정명

DBMS & SQL Server Installation Database Laboratory

쉽게 풀어쓴 C 프로그래밍

FileMaker ODBC 및 JDBC 가이드

PowerPoint Presentation

Microsoft PowerPoint - 04-UDP Programming.ppt

RDB개요.ppt

Microsoft PowerPoint - Java7.pptx

2파트-07

8 장데이터베이스 8.1 기본개념 - 데이터베이스 : 데이터를조직적으로구조화한집합 (cf. 엑셀파일 ) - 테이블 : 데이터의기록형식 (cf. 엑셀시트의첫줄 ) - 필드 : 같은종류의데이터 (cf. 엑셀시트의각칸 ) - 레코드 : 데이터내용 (cf. 엑셀시트의한줄 )

신림프로그래머_클린코드.key

ETL_project_best_practice1.ppt

q 이장에서다룰내용 1 객체지향프로그래밍의이해 2 객체지향언어 : 자바 2

Web Service Computing

JAVA PROGRAMMING 실습 08.다형성

KYO_SCCD.PDF

DocsPin_Korean.pages

쉽게 풀어쓴 C 프로그래밍

자바 프로그래밍

Microsoft PowerPoint - Smart CRM v4.0_TM 소개_ pptx

1

NoSQL

Intro to Servlet, EJB, JSP, WS

C# Programming Guide - Types

ilist.add(new Integer(1))과 같이 사용하지 않고 ilist.add(1)과 같이 사용한 것은 자바 5.0에 추가된 기본 자료형과 해당 객체 자료 형과의 오토박싱/언박싱 기능을 사용한 것으로 오토박싱이란 자바 컴파일러가 객체를 요구하는 곳에 기본 자료형

JMF2_심빈구.PDF

[ 목차 ] 5.1 데이터베이스프로그래밍개념 5.2 T-SQL T-SQL 문법 5.3 JAVA 프로그래밍 2

<4D F736F F F696E74202D20C1A63038C0E520C5ACB7A1BDBABFCD20B0B4C3BC4928B0ADC0C729205BC8A3C8AF20B8F0B5E55D>

JUNIT 실습및발표

Microsoft PowerPoint - hci2-lecture12 [호환 모드]

슬라이드 1

슬라이드 1

자바GUI실전프로그래밍2_장대원.PDF

PowerPoint Presentation

°¡°Ç2¿ù-ÃÖÁ¾

Facebook API

ch09

슬라이드 1

Spring Batch 2.0 시작하기

PowerPoint 프레젠테이션

PowerPoint Template

제11장 프로세스와 쓰레드

Apache Ivy

PowerPoint Presentation

Transcription:

Object Relation Mapping

오늘학습목표 ORM 에대한이해 Spring Data JPA 를활용한 ORM 구현

태그기반질답게시판

요구사항 설계실습 사용자는질문을할수있어야한다. 질문에대한답변을할수있어야한다. 질문을할때태그를추가할수있어야한다. 태그는태그풀에존재하는태그만추가할수있다. 태그가추가될경우해당태그수는 +1 증가, 삭제될경우해당태그수는 -1 증가해야한다.

어디서부터시작할것인가? 객체 or 테이블

User 1 0..n Question 0..n 0..n Tag 1 1 0..n Answer 0..n

비즈니스로직구현

테이블설계로부터시작한다면 요구사항 질문할때태그를추가할수있다. ( 예 java eclipse) 질문을수정할때태그를수정할수있다. ( 예. eclipse ant)

질문추가시 java eclipse 태그추가할경우 insert into question values(?,?,?,?,?); => question_id = 1 select id, name from tag where name= java ; => tag_id = 11 select id, name from tag where name= eclipse ; => tag_id = 12 insert into question_tag values( 1, 11 ); insert into question_tag values( 1, 12 ); update tag set tagged_count = tagged_count + 1 where name= java ; update tag set tagged_count = tagged_count + 1 where name= eclipse ;

질문수정시 eclipse ant 태그추가할경우 update question set title=?, contents=? where question_id = 1; delete from question where question_id = 1; select id, name from tag where name= eclipse ; => tag_id = 12 select id, name from tag where name= ant ; => tag_id = 13 insert into question_tag values( 1, 12 ); insert into question_tag values( 1, 13); update tag set tagged_count = tagged_count + 1 where name= ant ; update tag set tagged_count = tagged_count - 1 where name= java ;

객체간의관계는사라지고단순 CRUD 만존재하게된다.

객체설계로부터시작한다면 요구사항 질문할때태그를추가할수있다. ( 예 java eclipse) 질문을수정할때태그를수정할수있다. ( 예. eclipse ant)

orm_start 브랜치 일단테이블구조는의식하지않고비즈니스로직구현한다.

구현실습 질문할때태그를추가할수있다. ( 예 java eclipse) Question 에 Tag 를추가한다. 태그풀 (TagRepository 로추상화 ) 에서 Tag 추출한다. Tag 가존재하는경우에만 Tag 로인정한다. Tag 를추가하는경우 Tag 의 taggedcount 를 +1 증가시킨다.

구현실습 질문을수정할때태그를수정할수있다. ( 예. eclipse ant) 수정할 Question 을생성한다. Tag 를추가한다. 태그풀 (TagRepository 로추상화 ) 에서 Tag 추출한다. Tag 가존재하는경우에만 Tag 로인정한다. 추가된 Tag 는 Tag 의 taggedcount 를 +1 증가, 삭제된 Tag 는 Tag 의 taggedcount 를 -1 감소한다.

자바객체와테이블매핑

@Entity @Entity public class User { } @Entity public class Question { }

@Entity public class User { @Id private String userid = null; } @Id

객체로부터테이블스키마 Export public class JPASchemaExport { public static void main(string[] args) { Ejb3Configuration cfg = new Ejb3Configuration(); HashMap<String, String> props = new HashMap<String, String>(); props.put("hibernate.format_sql", "true"); Ejb3Configuration configured = cfg.configure("slipp.qna", props); SchemaExport se = new SchemaExport(configured.getHibernateConfiguration()); se.setdelimiter(";"); se.create(true, false); } } 객체와테이블을매핑하면테이블스키마를자동으로 Export 할수있다.

@Entity public class Question { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long questionid; } @Id 자동증가

@Column @Entity public class Question { @Column(name = "title", length=100, nullable = false) private String title; }

@Entity public class Employee { @OneToOne @JoinColumn(name="PSPACE_ID") private ParkingSpace parkingspace; } @OneToOne

@Entity public class Question { @OneToMany(mappedBy = "question") private List<Answer> answers; } @OneToMany

@ManyToOne @Entity public class Answer { @ManyToOne @org.hibernate.annotations.foreignkey(name = "fk_answer_parent_id") private Question question; }

@Entity public class Question { @ManyToMany private Set<Tag> tags = Sets.newHashSet(); } @ManyToMany

@ManyToMany Join Table @Entity public class Question { @ManyToMany @JoinTable(name = "question_tag", joincolumns = @JoinColumn(name = "question_id"), inversejoincolumns = @JoinColumn(name = "tag_id")) @org.hibernate.annotations.foreignkey (name = "fk_question_tag_question_id", inversename = "fk_question_tag_tag_id") private Set<Tag> tags = Sets.newHashSet(); }

@Transient @Entity public class Question { @Transient private String plaintags; } 객체의필드는기본적으로테이블과매핑한다. 필드중테이블칼럼과매핑하고싶지않은경우 @Transient 를사용한다.

Lazy Loading @Entity public class Question { @ManyToMany(fetch = FetchType.LAZY) @JoinTable(name = "question_tag", joincolumns = @JoinColumn(name = "question_id"), inversejoincolumns = @JoinColumn(name = "tag_id")) @org.hibernate.annotations.foreignkey (name = "fk_question_tag_question_id", inversename = "fk_question_tag_tag_id") private Set<Tag> tags = Sets.newHashSet(); } @OneToMany(mappedBy = "question", fetch = FetchType.LAZY) @OrderBy("answerId DESC") private List<Answer> answers;

ORM 설정및 Repository 구현 JPA( 표준 ) + Hibernate( 구현체 )

JPA 설정 의존관계추가 <dependency> <groupid>org.springframework</groupid> <artifactid>spring-orm</artifactid> <version>${org.springframework.version}</version> </dependency> <dependency> <groupid>org.hibernate.javax.persistence</groupid> <artifactid>hibernate-jpa-2.0-api</artifactid> <version>1.0.0.final</version> </dependency> <dependency> <groupid>org.hibernate</groupid> <artifactid>hibernate-entitymanager</artifactid> <version>${hibernate.version}</version> </dependency> <dependency> <groupid>org.springframework.data</groupid> <artifactid>spring-data-jpa</artifactid> <version>1.0.3.release</version> </dependency>

JPA 설정 META-INF/persistence.xml <?xml version="1.0" encoding="utf-8" standalone="no"?> <persistence [...]> <persistence-unit name="slipp.qna" transaction-type="resource_local"> <provider>org.hibernate.ejb.hibernatepersistence</provider> <properties> <property name="hibernate.dialect" value="org.hibernate.dialect.h2dialect" /> <property name="hibernate.hbm2ddl.auto" value="create" /> <property name="hibernate.ejb.naming_strategy" value="org.hibernate.cfg.improvednamingstrategy" /> <property name="hibernate.format_sql" value="true" /> <property name="hibernate.show_sql" value="false"/> </properties> </persistence-unit> </persistence>

JPA 설정 infrastructure.xml <?xml version="1.0" encoding="utf-8"?> <beans [...]> <bean id="jpadialect" class="org.springframework.orm.jpa.vendor.hibernatejpadialect" /> <bean id="entitymanagerfactory" class="org.springframework.orm.jpa.localcontainerentitymanagerfactorybean" p:persistencexmllocation="classpath:meta-inf/persistence.xml" p:persistenceunitname="slipp.qna" p:datasource-ref="datasource" p:jpadialect-ref="jpadialect" /> <bean id="transactionmanager" class="org.springframework.orm.jpa.jpatransactionmanager" p:entitymanagerfactory-ref="entitymanagerfactory" /> <bean id="datasource" class="org.apache.commons.dbcp.basicdatasource" p:driverclassname="org.h2.driver" p:url="jdbc:h2:~/slipp-user" p:username="sa" p:password="" destroy-method="close" /> <tx:annotation-driven transaction-manager="transactionmanager" /> </beans>

Spring 설정 applicationcontext.xml <?xml version="1.0" encoding="utf-8"?> <beans [...]> <import resource="classpath:infrastructure.xml"/> <jpa:repositories base-package="net.slipp.repository"/> </beans>

실습 package net.slipp.repository.user; import net.slipp.domain.user.user; import org.springframework.data.repository.crudrepository; public interface UserRepository extends CrudRepository<User, String> { }

orm_finish 브랜치 실습 QnA 게시판완료

JPA 와 Hibernate

JPA Query - JPQL -- 기본쿼리 SELECT e FROM Employee e -- Filtering 쿼리 SELECT e FROM Employee e WHERE e.department.name = 'NA42' AND e.address.state IN ('NY','CA') -- Join 쿼리 SELECT p.number FROM Employee e, Phone p WHERE e = p.employee AND e.department.name = 'NA42' AND p.type = 'Cell'

JPA Query - JPQL -- 인자전달 SELECT e FROM Employee e WHERE e.department =?1 AND e.salary >?2 SELECT e FROM Employee e WHERE e.department = :dept AND e.salary > :base JPQL 은각데이터베이스별로다른 SQL 을표준화한 Query Language 이다. Hibernate 만사용한다면 HQL 이존재한다.

JPA Query 실행 - NamedQuery -- NamedQuery 정의 @NamedQuery(name="findEmployeesAboveSal", query="select e " + "FROM Employee e " + "WHERE e.department = :dept AND " + " e.salary > :sal") -- NamedQuery 사용 public List<Employee> findemployeesabovesal(department dept, long minsal) { return em.createnamedquery("findemployeesabovesal", Employee.class).setParameter("dept", dept).setparameter("sal", minsal).getresultlist(); }

JPA Query Criteria API -- JPQL SELECT e FROM Employee e WHERE e.name = 'John Smith' -- Criteria API CriteriaBuilder cb = em.getcriteriabuilder(); CriteriaQuery<Employee> c = cb.createquery(employee.class); Root<Employee> emp = c.from(employee.class); c.select(emp).where(cb.equal(emp.get("name"), "John Smith"));

Spring Data JPA public interface UserRepository extends JpaRepository<User, Long> { @Query("select u from User u where u.emailaddress =?1") User findbyemailaddress(string emailaddress); } public interface UserRepository extends JpaRepository<User, Long> { @Query("select u from User u where u.firstname = :firstname or u.lastname = :lastname") User findbylastnameorfirstname(@param("lastname") String lastname, @Param("firstname") String firstname); }

Spring Data JPA 쿼리 http://www.springsource.org/spring-data/jpa

Spring Data JPA 사용규칙 특정칼럼을활용한 select 나단순쿼리는 method naming convention 을따른다. 쿼리복잡도가높아 method naming convention 에의해처리하지못하는경우, 하지만정적인쿼리는 Named Query(@Query Annotation) 을활용한다. 동적인쿼리의경우에는 Criteria API 를활용한다.

Spring Data JPA 복잡한쿼리 public interface CustomerRepository extends CrudRepository<Customer, Long>, JpaSpecificationExecutor { } JpaSpecificationExecutor 인터페이스를상속하면 Specification 인터페이스를실행할수있는추가메소드를실행할수있다. public interface Specification<T> { Predicate topredicate(root<t> root, CriteriaQuery<?> query, CriteriaBuilder builder); }

Spring Data JPA 복잡한쿼리 public class CustomerSpecs { public static Specification<Customer> islongtermcustomer() { return new Specification<Customer>() { Predicate topredicate(root<t> root, CriteriaQuery<?> query, CriteriaBuilder builder) { LocalDate date = new LocalDate().minusYears(2); return builder.lessthan(root.get(customer_.createdat), date); } }; } public static Specification<Customer> hassalesofmorethan(montaryamount value) { return new Specification<Customer>() { Predicate topredicate(root<t> root, CriteriaQuery<?> query, CriteriaBuilder builder) { } } } }; // build query here

JPA Query Criteria API

JPA Query Criteria API

ORM 사용시테이블스키마관리

기능안정화단계전까지 데이터베이스를매번초기화한다. <?xml version="1.0" encoding="utf-8" standalone="no"?> <persistence [...]> <persistence-unit name="slipp.qna" transaction-type="resource_local"> <provider>org.hibernate.ejb.hibernatepersistence</provider> <properties> <property name="hibernate.dialect" value="org.hibernate.dialect.h2dialect" /> <property name="hibernate.hbm2ddl.auto" value="create" /> <property name="hibernate.ejb.naming_strategy" value="org.hibernate.cfg.improvednamingstrategy" /> <property name="hibernate.format_sql" value="true" /> <property name="hibernate.show_sql" value="false"/> </properties> </persistence-unit> </persistence>

기능안정화단계 CarbonFive 와같은플러그인을활용해테이블스키마변경관리한다. <?xml version="1.0" encoding="utf-8" standalone="no"?> <persistence [...]> <persistence-unit name="slipp.qna" transaction-type="resource_local"> <provider>org.hibernate.ejb.hibernatepersistence</provider> <properties> <property name="hibernate.dialect" value="org.hibernate.dialect.h2dialect" /> <property name="hibernate.hbm2ddl.auto" value= update" /> <property name="hibernate.ejb.naming_strategy" value="org.hibernate.cfg.improvednamingstrategy" /> <property name="hibernate.format_sql" value="true" /> <property name="hibernate.show_sql" value="false"/> </properties> </persistence-unit> </persistence>

Maven Carbon Five 플러그인활용 https://code.google.com/p/c5-db-migration/

schema_version 테이블

mvn db-migration:new Dname= 생성쿼리설명 mvn db-migration:migrate

Spring Security 권한처리

applicationcontext-security.xml <beans:beans [...]> <global-method-security pre-post-annotations="enabled" /> <http pattern="/resources*/**" security="none"/> <http use-expressions="true"> <intercept-url pattern="/qna/form" access="hasrole('role_user')"/> [ ] <intercept-url pattern="/**" access="permitall" /> <form-login login-processing-url="/security/login" login-page="/security/form" default-target-url="/" always-use-default-target="false" /> <logout logout-url="/security/logout" logout-success-url="/" /> </http> <authentication-manager alias="authenticationmanager"> <authentication-provider ref="authenticationprovider"/> </authentication-manager> <beans:bean id="authenticationprovider" class="net.slipp.support.security.slippauthenticationprovider" /> <beans:bean id="userdetailsservice" class="net.slipp.support.security.slippuserdetailsservice"/> </beans:beans>

Spring Security 설정 web.xml <filter> <filter-name>springsecurityfilterchain</filter-name> <filter-class>org.springframework.web.filter.delegatingfilterproxy</filter-class> </filter> <filter-mapping> <filter-name>springsecurityfilterchain</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>

Controller 와로그인사용자연결하기 @Target(ElementType.PARAMETER) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface LoginUser { boolean required() default true; }

Controller 와로그인사용자연결하기 @RequestMapping(value="", method=requestmethod.post) public String create(@loginuser User user, HttpServletRequest request, Question question) { logger.debug("question : {}", question); } qnaservice.createquestion(user, question); return "redirect:/qna"; [...] @RequestMapping(value="", method=requestmethod.put) public String update(@loginuser User user, Question question) { logger.debug("question : {}", question); qnaservice.updatequestion(user, question); return "redirect:/qna"; }