TIL 금일 공부

|

1. SPRING BOOT JPA 쇼핑몰 프로젝트 진행상황

  • ~~회원가입 처리 ~~
  • 회원,비회원 카트 담기
  • ~~회원,비회원 주문 ~~
  • 회원,비회원 주문내역 확인
  • 페이징 처리
  • 검색기능 추가( querydsl )
  • backEnd단 유효성검사 처리 2019.02.27일 완료
  • FrontEnd단 유효성검사 처리(jquery validation plugin 사용)
  • 썸네일 업로드 혹은 이미지 리사이즈
  • 페이스북 혹은 gmail 연동작업
  • 이메일 연동 작업 ( 비밀번호 찾기 )
  • jpql N+1 문제
  • 기능별 수정삭제 기능
  • aws 배포후 테스트, 문제가 없을 경우 travis ci를 사용해서 배포자동화 작업

2. 알고리즘

  • hackerrank 문제풀이

JPQL란?

|

1. JPQL이란?

  • JPQL는 JPA의 일부로 정의된 플랫폼 독립적인 쿼리 언어입니다.
  • JPQL은 관계형 데이터베이스의 엔티티에 대한 쿼리를 만드는데 사용합니다.
  • 데이터베이스와 실제 연결되는게 아닌, JPA 엔티티에 대해 동작하기 때문에 엔티티의 컬럼명을 적어줘야합니다.

2. JPQL fetch join 사용법

1) 공식문서 명령어 , [LEFT [OUTER] INNER] JOIN FETCH 조인경로

2) 엔티티 패치 조인

  • ex) select m from parent p join fetch p.child
  • 연관된 엔티티나 컬렉션을 함께 조회한다. p와 p.child를 모두 검색한다.
  • 참고로 일반적인 JPQL은 별칭을 허용하지 않는다.
  • 하이버네이트는 페치 조인에도 별칭을 허용한다.

select
    parent0_.id as id1_1_0_,
    child1_.id as id1_0_1_,
    parent0_.child_id as child_id3_1_0_,
    parent0_.name as name2_1_0_,
    child1_.name as name2_0_1_ 
from
    Parent parent0_ 
inner join
    Child child1_ 
        on parent0_.child_id=child1_.id

3) 컬렉션 패치 조인

  • 일 대 다 관계를 패치 조인 할 경우
  • ex) select p from Parent p join fetch p.child where p.name = ‘child_name’
  • 연관된 child의 p.name의 값이 child_name과 동일한 모든값이 나온다
  • 또한 fetch join으로 인해서 지연로딩이 발생하지 않는다.

select
    parent0_.id as id1_1_0_,
    child2_.id as id1_0_1_,
    parent0_.name as name2_1_0_,
    child2_.name as name2_0_1_,
    child1_.Parent_id as Parent_i1_2_0__,
    child1_.child_id as child_id2_2_0__ 
from
    Parent parent0_ 
inner join
    Parent_Child child1_ 
    on parent0_.id=child1_.Parent_id 
inner join
    Child child2_ 
    on child1_.child_id=child2_.id 
where
    parent0_.name=?


String name = "testName1";
Parent parents = em.createQuery("" +
    "SELECT p " +
    "FROM Parent p " +
    "JOIN FETCH p.child " +
    "where p.name = :name ", Parent.class) 
    .setParameter("name", name) // :name에 값 매핑
    .getSingleResult();
System.out.println(parents);

3. fetch join의 단점

  1. 페치 조인 대상에는 별칭을 줄 수 없다.
  2. 둘 이상의 컬렉션을 페치 할 수 없다.
  3. 컬렉션을 페치 조인하면 페이징 API를 사용 할 수 없다.

View 정의, 장단점?

|

1. View 정의

  1. 뷰는 사용자에게 접근이 허용된 자료만을 제한적으로 보여주기 위해 하나 이상의 기본 테이블로부터 유도된, 이름을 가지는 가상 테이블이다.

  2. 뷰는 저장장치 내에 물리적으로 존재하지 않는만 사용자에게 있는 것처럼 간주한다.

  3. 뷰는 데이터 보정작업, 처리과정 시험 등 임시적인 작업을 위한 용도로 활용한다.

  4. 뷰는 조인문의 사용 최소화로 사용상의 편의성을 최대한 한다.

2. View 사용시 장단점

  1. 논리적 데이터 독립성을 제공한다.

  2. 동일 데이터에 대해 동시에 여러사용자의 상이한 응용이나 요구를 지원해 준다.

  3. 사용자의 데이터관리를 간단하게 해준다.

  4. 접근 제어를 통한 자동 보안이 제공된다.

3. 단점

  1. 독립적인 인덱스를 가질 수 없다.

  2. Alter View문을 사용할 수 없다. 즉 뷰의 정의를 변경 할 수 없다

  3. 뷰의 내용에 대해서 삽입,삭제, 갱신, 연산등의 제약이 많다.

/* 생성문 */
CREATE VIEW 뷰이름[(속성이름[,속성이름])]AS SELECT;

--고객 테이블에서 주소가 서울시인 고객들의 성명과 전화번호를 서울고객이라는 뷰로 만들어라--
CREATE VIEW 서울고객(성명, 전화번호)
AS SELECT 성명 전화번호
FROM 고객
WHERE 주소 = '서울시';

/* 뷰 삭제문 */

--문법--
DROP VIEW 뷰이름 RESTRICT or CASCADE

--서울고객이라는 뷰를 삭제해라--
DROP VIEW 서울고객 RESTRICT;

함수형 자바스크립트를 위한 기초

|

1.1 함수형 자바스크립트를 위한 기초

가장 중요한점은 함수를 다루는 다양한 방법들을 잘 익히는 것이 중요하다.

1. 일급함수

자바스크립트에서 함수는 일급 객체이자 일급 함수이다. 자바스크립트에서 객체는 일급 객체이다.

여기서 ‘일급’은 값으로 다룰 수 있다는 의미로, 아래와 같은 조건을 만족해야 한다.

  • 변수에 담을 수 있다.
  • 함수나 메서드의 인자로 넘길 수 있다.
  • 함수나 메서드에서 리턴할 수 있다.

자바스크립트에서 모든 값은 일급이다. 자바스크립트에서 모든 객체는 일급 객체이며, 함수도 객체이자

일급 객체다. 그럼 일급 함수는 무엇일까? 보통 일급 함수는 아래와 같은 추가적인 조건을 더 만족한다.

  • 아무때나(런타임에서도) 선언이 가능하다.
  • 익명으로 선언할 수 있다.
  • 익명으로 선언한 함수도 함수나 메서드의 인자로 넘길 수 있다.

자바스크립트의 함수는 위 조건을 모두 만족하는 일급 함수다.


// 예제코드
function f1() {}
var a = typeof f1 == 'function' ? f1 : function() {};

function f2() {
    return function() {};
}

console.log((function(a,b){ return a + b; })(10,5));

function callAndAdd(a,b) {
    return a() + b();
}
callAndAdd(function() { return 10; }, function() { return 5; });

2. 클로저

클로저는 함수형 자바스크립트에서 매우 중요하며, 계속해서 활용되기 때문에 보다 정확한 이해가 필요하다.

스코프에 대한 개념을 잘 알고 있다면 이 글을 읽는데 도움이 될 것이다.

정의 : 클로저는 자신이 생성될 때의 스코프에서 알 수 있었던 변수를 기억하는 함수이다.

관점에 따라 약간씩 다르지만 클로저라는 용어에 담긴 속성이나 특징들을 모두 빠짐없이 가지고 있는

특별한 함수만을 클로저라고 칭하는 것이 옳다고 생각한다. 함수가 의미적으로나 실제적으로나 진짜 클로저가

되기 위한 가장 중요한 조건은 다음과 같다.

xml, java config 설정법

|

xml로 설정하기

1. data source bean을 설정한다


<!-- Connection Pool DataSource -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
     <property name="driverClassName" value="com.mysql.jdbc.Driver" />
     <property name="url" value="jdbc:mysql://localhost:3306/jpadb" />
     <property name="username" value="jpadb" />
     <property name="password" value="jpadb" />
</bean>

  • applicationContext.xml 파일에서 dataSource를 정의한다.

2. Entity Manager factory bean을 설정한다

1) Entity 탐색 범위 설정 2) 하이버네이트 구현체 사용 3) 하이버네이트 상세 설정

3. transaction manager bean을 설정한다

4. enable annotation driven transaction management를 설정한다

  • 트랜잭션 관리자 활성화 및 등록 합니다

5. Spring Data Jpa를 설정한다


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:jpa="http://www.springframework.org/schema/data/jpa"
  xmlns:tx="http://www.springframework.org/schema/tx"
  xmlns:context="http://www.springframework.org/schema/context"
  xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/data/jpa 
    http://www.springframework.org/schema/data/jpa/spring-jpa-1.0.xsd
    http://www.springframework.org/schema/tx 
    http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
    http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context-3.1.xsd">

  <!-- data source bean 설정 -->
  <jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/CustomerSupport"/>

  <!-- configuration for Hibernate 하이버네이트 기본설정 -->
  <bean id="hibernateJpaVendorAdapter" 
    class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>

  <!-- entity manager factory bean 설정 -->
  <bean id="entityManagerFactory" 
    class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <property name="jpaVendorAdapter" ref="hibernateJpaVendorAdapter"/>
    <!-- Set JPA properties -->
    <property name="jpaProperties">
      <props>
        <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop>
        <prop key="javax.persistence.schema-generation.database.action">none</prop>
        <prop key="hibernate.ejb.use_class_enhancer">true</prop>
      </props>
    </property>
    <!-- 기본 entity 설정 -->
    <property name="packagesToScan" value="foo.bar.model"/>
    <!-- shareCaheMode 설정 -->
    <property name="sharedCacheMode" value="ENABLE_SELECTIVE"/>
    <!-- 유효성 검사 설정 -->
    <property name="validationMode" value="NONE"/>
  </bean>

  <!-- 트랜잭션 매니저 활성화 설정 -->
  <bean id="transactionManager" 
    class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory"/>
  </bean>

  <!-- 트랜잭션 관리자 사용가능하게 등록 -->
  <tx:annotation-driven/>

  <!-- 
    Spring Data JPA 설정 및 저장소 인터페이스의 기본 패키지 설정
  -->
  <jpa:repositories base-package="foo.bar.repository"/>
</beans>

[출처1] (https://victorydntmd.tistory.com/202) [출처2] (https://stackoverflow.com/questions/25049778/how-to-configure-spring-data-jpa-using-xml)

2. java config로 설정하기

xml 과 설정해야 할 bean은 동일하다.


@Configuration
@EnableTransactionManagement
public class PersistenceJPAConfig{
 
   @Bean
   public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
      LocalContainerEntityManagerFactoryBean em 
        = new LocalContainerEntityManagerFactoryBean();
      em.setDataSource(dataSource());
      em.setPackagesToScan(new String[] { "org.baeldung.persistence.model" });
 
      JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
      em.setJpaVendorAdapter(vendorAdapter);
      em.setJpaProperties(additionalProperties());
 
      return em;
   }
 
   @Bean
   public DataSource dataSource(){
      DriverManagerDataSource dataSource = new DriverManagerDataSource();
      dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
      dataSource.setUrl("jdbc:mysql://localhost:3306/spring_jpa");
      dataSource.setUsername( "tutorialuser" );
      dataSource.setPassword( "tutorialmy5ql" );
      return dataSource;
   }
 
   @Bean
   public PlatformTransactionManager transactionManager(
     EntityManagerFactory emf){
       JpaTransactionManager transactionManager = new JpaTransactionManager();
       transactionManager.setEntityManagerFactory(emf);
 
       return transactionManager;
   }
 
   @Bean
   public PersistenceExceptionTranslationPostProcessor exceptionTranslation(){
       return new PersistenceExceptionTranslationPostProcessor();
   }
 
   Properties additionalProperties() {
       Properties properties = new Properties();
       properties.setProperty("hibernate.hbm2ddl.auto", "create-drop");
       properties.setProperty(
         "hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect");
        
       return properties;
   }
}