JPA-DATA @ManyToOne 삭제시 부모참조(연결 컬럼 UPDATE) 문제가 생길시

예전 HIBERNATE에서 하던 방식대로 참조 하는 부모객체의 정보를 NULL로 만들어서 연결을 끊어주고 DELETE하는 방식을 사용해야 합니다.

BbsSet<->BbsItem 2개의 테이블이 ManyToOne으로 엮여 있는 경우

@JsonIgnore
@OneToMany(fetch = FetchType.LAZY)
@JoinColumn(name = "BBS_SET_SEQ")
private List<BbsItem> bbsItemList = new ArrayList<BbsItem>();

@JsonIgnore
@ManyToOne(cascade = { CascadeType.ALL }, fetch = FetchType.LAZY)
@JoinColumn(name = "BBS_SET_SEQ", insertable=false, updatable=false)
private BbsSet bbsSet;

BbsItem 삭제시 아래와 같이 UPDATE문을 실행 하게 됩니다.

UPDATE T_BBS_ITEM SET BBS_SET_SEQ=null WHERE BBS_ITEM_SEQ=?

BBS_SET_SEQ 은 FK 키로 잡혀 있기 때문에 NOT NULL이여서 에러가 발생되고 삭제에 실패 하게 됩니다.
이 경우 BbsItem의 bbsSet 을 bbsSet=null; 로 관계를 끊어주고 delete해야 정상적으로 BbsItem 정보가 삭제 됩니다.
(bulk update 할 수도 있는데 다른 방법이 있을거 같은데 hibernate에서 하던 방식으로 처리 했습니다.)

반응형
Posted by 질주하는구
,

JPA-DATA에서 @Query-Map을 이용해서 데이터를 가지고 오는 경우

@Query(value = "SELECT new Map(MAX(bbsItemListOrder) as listOrder, MAX(bbsItemMiniOrder) as miniListOrder, MAX(bbsItemViewOrder) as viewOrder)  FROM BbsItem WHERE bbsSetSeq = :bbsSetSeq")
public Map<String, Integer> getMaxOrder(@Param("bbsSetSeq") Integer bbsSetSeq);

위와 같이 select부분에 new Map 및 as listOrder 로 Map생성 key값 지정 해서 데이터를 조회 할 수 있습니다.

반응형
Posted by 질주하는구
,

T_BBS_ITEM(BbsItem) 테이블의 항목 정보중 특정 컬럼(BBS_ITEM_GROUP-bbsItemGroup-항목그룹) 정보만 가지고 오려는 경우
@Query으로 데이터를 가지고 올 수 있습니다.
이때 return값은 List<String>으로 처리를 하고 쿼리문 작성시 nativeQuery 옵션을 줘서 쿼리문 형식을 원하는 방식으로 정의 할 수 있습니다.

- nativeQuery 옵션 사용
@Query(value = "SELECT BBS_ITEM_GROUP FROM T_BBS_ITEM WHERE BBS_SET_SEQ = :bbsSetSeq", nativeQuery = true)
Hibernate: 
    /* dynamic native SQL query */ SELECT
        BBS_ITEM_GROUP 
    FROM
        T_BBS_ITEM 
    WHERE
        BBS_SET_SEQ = ?

- nativeQuery 옵션 미 사용
@Query(value = "SELECT bbsItemGroup FROM BbsItem WHERE bbsSetSeq = :bbsSetSeq")
Hibernate: 
    /* SELECT
        bbsItemGroup 
    FROM
        BbsItem 
    WHERE
        bbsSetSeq = :bbsSetSeq */ select
            bbsitem0_.BBS_ITEM_GROUP as col_0_0_ 
        from
            T_BBS_ITEM bbsitem0_ 
        where
            bbsitem0_.BBS_SET_SEQ=?

이 경우에는 nativeQuery 옵션을 사용 할 필요 까지 없는 겨우여서 사용 하지 않지만 쿼리문을 직접 사용해야 하는 경우 기존 시스템을 이관해야 하는
경우등 특별한 경우에 해당 옵션을 활용 할 수 있습니다.

반응형
Posted by 질주하는구
,

spring bean validation에서  사용하는 어노테이션은 아래와  같습니다.

 

-  값이 true인지 또는 false인지 검사한다. null은 유효하다고 판단한다. 
@AssertTrue
@AssertFalse

- 지정한 값보다 작거나 같은지 또는 크거나 같은지 검사한다. inclusive가 false면 value로 지정한 값은 포함하지 않는다. null은 유효하다고 판단한다.
@DecimalMax
@DecimalMin
ex>
@DecimalMin(value = "0.0")
@DecimalMax(value = "100.0")

-  지정한 값보다 작거나 같은지 또는 크거나 같은지 검사한다. null은 유효하다고 판단한다.
@Max
@Min
ex> 
@Min(0)
@Max(99999999)

- 자릿수가 지정한 크기를 넘지 않는지 검사한다. null은 유효하다고 판단한다.
@Digits

- 길이나 크기가 지정한 값 범위에 있는지 검사한다. null은 유효하다고 판단한다.
@Size
ex>
@Size(min = 4, max = 100)

- 값이 null인지 또는 null이 아닌지 검사한다. 
@Null
@NotNull
ex>
@NotNull(message = "이름은 Null 일 수 없습니다!")  (null 조건 검색)

- 값이 정규표현식에 일치하는지 검사한다. null은 유효하다고 판단한다.
@Pattern

- 문자열나 배열의 경우 null이 아니고 길이가 0이 아닌지 검사한다. 콜렉션의 경우 null이 아니고 크기가 0이 아닌지 검사한다.(null, "" 2가지 조건을  검색)
@NotEmpty()

- null이 아니고 최소한 한 개 이상의 공백아닌 문자를 포함하는지 검사한다.(null, "", " "  3가지  조건을 검색)
@NotBlank()

- 양수인지 검사한다. OrZero가 붙은 것은 0 또는 양수인지 검사한다. null은 유효하다고 판단한다.
@Positive()
@PositiveOrZero()

- 음수인지 검사한다. OrZero가 붙은 것은 0 또는 음수인지 검사한다.  null은 유효하다고 판단한다.
@Negative()
@NegativeOrZero()

- 이메일 주소가 유효한지 검사한다. null은 유효하다고 판단한다.
@Email()

- 해당 시간이 미래 시간인지 검사한다. OrPresent가 붙은 것은 현재 또는 미래 시간인지 검사한다. null은 유효하다고 판단한다.
@Future()
@FutureOrPresent()

- 해당 시간이 과거 시간인지 검사한다. OrPresent가 붙은 것은 현재 또는 과거 시간인지 검사한다. null은 유효하다고 판단한다.
@Past()
@PastOrPresent()

반응형
Posted by 질주하는구
,

jpa-data에서 테이블을 oracle의 start with 처럼 재귀적으로 호출 하기 위해 self join 하는 경우 아래와 같이 정의 해주면 됩니다.

T_CONTS_TEMPLATE 테이블의 컬럼 중

CONTS_TEMP_SEQ<--기본키
CONTS_PARENT_SEQ<--부모키
이 존재 하는 경우 parent와 children을 아래와 같이 정의 합니다.

//@Where(clause = "useYn='N'")
@JsonIgnore
@ManyToOne(cascade = { CascadeType.ALL }, fetch = FetchType.LAZY)
@JoinColumn(name = "CONTS_PARENT_SEQ", insertable=false, updatable=false)
private ContentsTemplate parent;

//@Where(clause = "useYn='N'")
@JsonProperty("nodes")
@OneToMany(fetch = FetchType.LAZY)
@JoinColumn(name = "CONTS_PARENT_SEQ")
@OrderBy("contsTempSeq asc")
private List<ContentsTemplate> children = new ArrayList<ContentsTemplate>();


@JsonIgnore 은 부모 객체를 json으로 변경 하면서 children을 재 참조 하는 상황을 방지 하기 위해서 json 생성시 예외 처리 합니다.
@JsonProperty("nodes") 은 Bootstrap Tree View 에서 데이터를 받을때 nodes라는 이름으로 받기 때문에 추가 해줬습니다.
FetchType.LAZY은 가능하면 lazy로 해주는게 좋습니다. EAGER(즉시호출) 하는 경우 예상하지 못한 쿼리문이
출력 되는경우가 생겨서 언제나 쿼리문 검증을 해야 하는 부담감이 있습니다.

반응형
Posted by 질주하는구
,

junit 테스트 시 'failed to lazily initialize a collection of role' 관련 에러가 발생되는 경우 lazy를 사용하는 경우 입니다.

웹에서는 web.xml에 OpenEntityManagerInViewFilter 관련 필터를 추가해서 해결하는데(@Transactional 을 추가해서 해결 하기도 하는데 필터로 작업 하고 있습니다. hibernate인경우 openSessionInViewFilter 를 추가 합니다.) junit의 경우 

@Transactional 을 추가 해서 session유지를 해줘야 합니다.

반응형
Posted by 질주하는구
,

테스트 케이스 작성시 spring4의 설정파일을 로드하기 위해

 

@ExtendWith(SpringExtension.class)
@ContextConfiguration
(
{
   "file:src/main/resources/egovframework/spring/context-aspect.xml",
   "file:src/main/resources/egovframework/spring/context-common.xml",
   "file:src/main/resources/egovframework/spring/context-datasource.xml",
   "file:src/main/resources/egovframework/spring/context-hibernate.xml",
   "file:src/main/resources/egovframework/spring/context-idgen.xml",
   "file:src/main/resources/egovframework/spring/context-mapper.xml",
   "file:src/main/resources/egovframework/spring/context-properties.xml",
   "file:src/main/resources/egovframework/spring/context-springdata.xml",
   "file:src/main/resources/egovframework/spring/context-sqlMap.xml",
   "file:src/main/resources/egovframework/spring/context-transaction.xml"
  }
)

 

같이 설정파일을 업로드 해줘야 합니다.

@RunWith(SpringJUnit4ClassRunner.class) -> @ExtendWith(SpringExtension.class)

반응형
Posted by 질주하는구
,

spring4에서 junit5 테스트 진행 시 NoClassDefFoundError ErrorCoded 와 같은 에러가 발생되는 경우

 

spring4의 test관련 라이브러리 문제로 junit5를 위한 의존성을 추가 해줘야 합니다.

(

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.1.0.RELEASE</version>
<scope>test</scope>
</dependency>

) 의 경우 버전 문제로 에러가 발생 됩니다.

 

아래의 내용과 같이 pom.xml에 추가

 

<repositories>
    <repository>
        <id>jitpack.io</id>
        <url>https://jitpack.io</url>
    </repository>
</repositories>

<dependencies>
    <dependency>
        <groupId>com.github.sbrannen</groupId>
        <artifactId>spring-test-junit5</artifactId>
        <version>1.5.0</version>
        <!--<scope>test</scope>-->
    </dependency>
</dependencies>

 

mockito를 사용하고자 하는 경우

 

<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-junit-jupiter</artifactId>
    <version>3.4.4</version>
    <!--<scope>test</scope>-->
</dependency>

 

내용도 추가 해서 사용하면 됩니다.

https://github.com/Dae-Hwa/nano-tips/issues/26

반응형
Posted by 질주하는구
,

jpa-data 작업 중 No bean named 'transactionManager' available: No matching PlatformTransactionManager bean found for qualifier 'transactionManager' - neither qualifier match nor bean name match!

같은 에러가 발생시 transaction을 이미 지정한 경우 해당 트랜잭션의 id를 

 

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">

같이 transactionManager로 지정 txManager등의 이름 사용시 해당 bean을 찾지 못하는 문제 발생

반응형
Posted by 질주하는구
,

pointcut을 여러개 지정 하기 위해서는 아래와 같이 작성 하면 됩니다.

 

<aop:pointcut id="requiredTx" expression="execution(* egovframework..impl.*Impl.*Transaction(..)) || execution(* egovframework.cmmn.service.impl.*Impl.*Transaction(..))"/>

 

'||'(or)나 '&&'(and), '!'(not) 을 사용할 수 있습니다.

반응형
Posted by 질주하는구
,