Mybatis if test 문자열처리

동적쿼리(dynamic sql)에서 많이 사용되는 Mybatis if test 에서의 문자열 처리.

※ java 문법과 동일하다고 보면 된다.

 

즉 문자열 비교를 위해 연산자 사용을 해선 안되고

equals 함수 사용시 null 값이 파라미터로 들어올 가능성을 대비하여 코딩해야 한다.

 

 

[Mybatis if test 에서의 문자열 처리]

1. null 체크

1
2
3
<if test = 'id neq null and id neq ""'>
<if test = 'id != null and id neq ""'>
<if test = 'id != null and !"".equals(id)'>
cs

 

2. 문자 비교

java단에서 gender를 'M' 으로 저장시(Char)

1
<if test=" 'M'.equals(gender) ">
cs

java단에서 gender를 "F" 으로 저장시(String)

1
<if test=' "F".equals(gender) '>
cs

 

3. 문자열 비교

1) equalsIgnoreCase 사용

1
<if test = '"pyo".equalsIgnoreCase(id)'> 
cs

2) == 연산자 사용

1
<if test = "id == 'pyo'.toString()"> 
cs

3) eq 사용

1
<if test = "id eq 'pyo'.toString()"> 
cs

 

[사용하지 말아야 할 문자열 비교 방법]

1
2
3
4
5
6
<!-- 1 -->
<if test = 'id == "pyo"'>
<!-- 2 -->
<if test = "gender.equals('X')">
<!-- 3 -->
<if test = 'id.equalsIgnoreCase("pyo")'>
cs

순서대로

1) 연산자를 사용한 참조객체의 비교는 에러 유발

2) String.equals(character) 로 취급하여 에러발생

3) java.lang.String 의 .equalsIgnoreCase 와 마찬가지로 위에서 id 가 null 인 경우 exception 발생하므로

<if test = '"pyo".equalsIgnoreCase(id)'> 와 같이 처리해야 한다.

 

 

결론:

character 를 사용하는 특별한 케이스를 제외하고

항상 가장 바깥쪽은 quote( ' ) 로 감싸고 안쪽 문자열은 double quote( " ) 로 감싼다

 

참고:

https://sinpk.tistory.com/entry/Mybatis-if-%EB%AC%B8%EC%9E%90%EC%97%B4-%EB%B9%84%EA%B5%90

 

반응형

'back > Mybatis,Ibatis' 카테고리의 다른 글

[mybatis] xml에서 java method 사용  (0) 2020.08.24
[Ibatis] dtd 경로 문제  (1) 2019.12.30
[Mybatis] $과 # 차이  (0) 2019.12.05
[Mybatis] like 조건시 문자열 처리  (1) 2019.02.13

 

현상 : 

QueryDSL 을 위해 Entity에 대한 Query Class 생성 후,

junit 테스트를 돌렸으나 생성한 Query Class 를 찾지 못한다는 NoDefClassFoundError 발생

※ NoDefClassFoundError : compile 시엔 문제없으나, runtime 시 class를 찾지 못하는 현상 (참고)

 

해결 :
1. compile 은 성공적으로 되었으며, compile 한 jar 파일을 실행하여 해당 메소드 호출할 경우 문제가 없는 것으로 보아

build.gradle 혹은 코드문제가 아닌 eclipse 설정이 문제라고 판단.

2. project property > Java Build Path > Source 탭 확인 : 이상없음

3. project property > Deployment Assembly 확인 : 상대경로로 지정된 패키징 경로가 존재.. 해당 부분 제거 후 문제 해결

 

 

 

 

 

 

반응형

 

 

[ Error vs Exception ]

Error: An Error indicates serious problem that a reasonable application should not try to catch.

> 애플리케이션이 잡지 말아야 할 심각한 에러(핸들링이 어려운 에러)

 

Exception: Exception indicates conditions that a reasonable application might try to catch.

> 애플리케이션이 잡을 수 있는 에러(핸들링이 할 수 있는 에러)

 

 

[ ClassNotFoundError vs NoDefClassFoundError ]

ClassNotFoundException is an exception that occurs when you try to load a class at run time using Class.forName() or loadClass() methods and mentioned classes are not found in the classpath.

> 런타임에 Class.forName() 혹은 loadClass() 메소드를 사용했고 refrection에 사용된 class가 classpath에 없는 경우 발생

 

NoClassDefFoundError is an error that occurs when a particular class is present at compile time, but was missing at run time.

> 특정 클래스가 컴파일시엔 존재했으나 런타임 때 찾을 수 없는 경우

위와 관련된 경험: https://developyo.tistory.com/241?category=747217

 

 

[Checked Exception vs Unchecked Exception ]

Checked Exception : Java forces you to handle these error scenarios in some manner in your application code. 

> java 가 핸들링을 강요하는 exception (ex: sqlException, IOException)

 

Unchecked Exception : A method is not forced by compiler to declare the unchecked exceptions thrown by its implementation. Generally, such methods almost always do not declare them, as well.

Spring Transaction only supervise Unchecked Exceptions.

> 핸들링을 강요하지 않는 exception (ex: NullPointerException)

 

 

참고)

error vs exception

https://www.geeksforgeeks.org/exceptions-in-java/

ClassNotFoundError vs NoDefClassFoundError

https://dzone.com/articles/java-classnotfoundexception-vs-noclassdeffounderro

CheckedException vs Unchecked Exception

https://www.geeksforgeeks.org/checked-vs-unchecked-exceptions-in-java/

 

반응형

 

[ jar 빌드 ]

apply plugin: 'java'
@SpringBootApplication
public class Application {
   //jar
   public static void main(String[] args) {
      SpringApplication.run(Application.class, args);
   }
}

 

[ war 빌드 ]

내장 tomcat 의 scope를 runtime 으로 바꿔준다

apply plugin: 'war'

dependencies {
    compile('org.springframework.boot:spring-boot-starter-web')
    providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'
}
@SpringBootApplication
public class Application extends SpringBootServletInitializer {
   //war
   @Override
   protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
      return application.sources(Application.class);
   }

   public static void main(String[] args) {
      SpringApplication.run(Application.class, args);
   }
}

 

 

반응형

'back' 카테고리의 다른 글

[Java] 일급콜렉션 : First Class Collection  (0) 2022.10.06
[TDD] 테스트주도개발  (0) 2022.10.04
JWT  (0) 2020.11.18

아래의 색인창(ctrl+F 단축키)에서 정규식 사용이 가능하다.

 

[실제 사용 사례]

iBatis 의 동적쿼리를 위한 파라미터 매핑구문은 #param# 을 사용하고

Mybatis 의 동적쿼리를 위한 파라미터 매핑구문은 #{param} 을 사용한다.

 

프레임워크의 버전이 올라가면서 iBatis를 Mybatis로 바꾸게 된다면

iBatis의 #parameter#를 Mybatis의 #{parameter} 로 바꿔줘야 한다.

 

이 때 아래와 같이 손쉽게 바꿔줄 수 있다.

Find : #([a-zA-Z]+)#

Replace with : #{$1}

 

위와 같이 정규식 중 캡쳐하고싶은 그룹을 () 로 묶고

묶은 순서대로 $ 식별자와 함께 index 를 넣어 치환해줄 수 있다.

반응형

JPQL : 객체지향쿼리

- SQL을 추상화한 JPA의 객체지향 쿼리

- 테이블이 아닌 엔티티 객체를 대상으로 쿼리

- 엔티티와 속성은 대소문자 구분

- 테이블 이름이 아닌 엔티티 이름 사용

- 별칭(alias) 사용 필수

 

 

1. EntityManager 사용시

select alias 시 전체 조회 (sql 에서 a.* 와 같음)

변수바인딩은 :이름 혹은 ?시퀀스 로 할 수 있다

1
2
3
4
5
6
7
8
9
10
11
12
@Autowired
EntityManager em;
 
User user = new User();
user.setName("pyo");
userRepository.save(user);
      
TypedQuery<User> tq = em.createQuery("select u from User u where u.name = :name", User.class);
tq.setParameter("name""pyo");
      
List<User> rs = tq.getResultList();
LOGGER.info("id : " + rs.get(0).getId());
cs

 

2. repository interface 사용시

@Query를 사용해서 직접 JPQL 지정

이름을 사용한 바인딩시 @Param("이름") 을 사용하지 않을 경우 에러가 발생하니 주의

1
2
3
4
5
6
7
8
9
10
11
12
13
public interface UserRepository extends JpaRepository<User, Long>{
    
   List<User> findByName(String name);
   User findById(long id);
   
   @Query("select u from User u where u.name = ?1")
   User customFind1(String nm);
   
   
   @Query("select u from User u where u.name = :name")
   User customFind2(@Param("name"String nm);
   
}
cs

 

JPQL , SQL 의 문제점

- JPQL 은 문자(String)이며, Type-Check가 불가능.

- 해당 로직 실행 전까지 작동여부 확인이 불가

- 실행시점에 오류가 발견됨

 

 

QueryDSL

- 문자가 아닌 코드로 작성

- 컴파일 시점 문법 오류 발견이 가능

- 코드 자동 완성

- 동적쿼리 가능

- JPQL 단점 보완

 

[gradle 설정]

gradle 설정은 gradle 버전마다 상이하다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
buildscript {
    ext {
        springBootVersion = '2.1.4.RELEASE'
        querydslPluginVersion = '1.0.10'
    }
    repositories {
        mavenCentral()
        maven { url "https://plugins.gradle.org/m2/" } // plugin 저장소
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
        classpath "io.spring.gradle:dependency-management-plugin:1.0.7.RELEASE"
        classpath("gradle.plugin.com.ewerk.gradle.plugins:querydsl-plugin:${querydslPluginVersion}")
    }
}
 
 
apply plugin: 'java'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
apply plugin: "com.ewerk.gradle.plugins.querydsl"
apply plugin: 'eclipse'
 
group = 'com.jpp'
version = '0.0.1'
sourceCompatibility = '1.8'
targetCompatibility = '1.8'
 
configurations {
   compileOnly {
      extendsFrom annotationProcessor
   }
}
 
repositories {
   mavenCentral()
}
 
dependencies {
   compile 'org.springframework.boot:spring-boot-starter-actuator'
   compile 'org.springframework.boot:spring-boot-starter-data-jpa'
   compile 'org.springframework.boot:spring-boot-starter-web'
   compileOnly 'org.projectlombok:lombok'
   runtimeOnly 'com.h2database:h2'
   annotationProcessor 'org.projectlombok:lombok'
   
   compile 'org.springframework.boot:spring-boot-starter-tomcat'
   
   testCompile('org.springframework.boot:spring-boot-starter-test') {
      exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
   }
   
   compile 'org.apache.tomcat.embed:tomcat-embed-jasper'
   compile 'javax.servlet:jstl'
   
   compile 'org.json:json:20180813'
   compile 'com.google.code.gson:gson:2.8.5'
   
   compile group: 'org.aspectj'name'aspectjweaver', version: '1.9.2'
   compile group: 'org.aspectj'name'aspectjrt', version: '1.9.2'
   
   compile 'com.querydsl:querydsl-jpa' // querydsl
   compile 'com.querydsl:querydsl-apt' // querydsl
}
 
test {
   useJUnitPlatform()
   ignoreFailures = true
}
 
def querydslSrcDir = 'src/main/generated'
 
querydsl {
    library = "com.querydsl:querydsl-apt"
    jpa = true
    querydslSourcesDir = querydslSrcDir
}
 
sourceSets {
    main {
        java {
            srcDirs = ['src/main/java', querydslSrcDir]
        }
    }
}
 
compileQuerydsl{
    options.annotationProcessorPath = configurations.querydsl
}
 
configurations {
    querydsl.extendsFrom compileClasspath
}
 
cs

 

gradle build 후 지정한 경로(src/main/generated)에 Query Class가 생성되었음을 확인 할 수 있다.

 

[QueryDSL 사용]

1
2
3
4
5
6
7
8
9
@PersistenceContext
EntityManager em;
 
public List<User> selectUserByNm(String nm){
  JPAQueryFactory jqf = new JPAQueryFactory(em);
  
  return jqf.selectFrom(user).where(user.name.eq(nm)).fetch();
}
 
cs

 

 

참고 :

Tacademy 김영한 개발자님의 강의

김영한 개발자님의 JPA 저서

https://www.baeldung.com/spring-data-jpa-query

https://www.baeldung.com/querydsl-with-jpa-tutorial

 

 

 

 

반응형

'back > JPA' 카테고리의 다른 글

[JPA] cascade  (0) 2022.11.10
[JPA] equals , hashcode  (0) 2022.11.08
[JPA] JPA 영속성 컨텍스트  (0) 2020.03.08
[JPA] 연관관계 매핑 : 단방향, 양방향 매핑  (0) 2020.03.01
[JPA] JPA 기초 설정 및 entity 필드 매핑  (0) 2020.02.27

1. 데이터베이스 Isolation Level 이란

트랜잭션에서 일관성 없는 데이터를 허용하는 수준

 

 

2. Isolation Level 의 종류

- Read Uncommitted

- Read Commited

- Repeatable Read

- Serializable

Read Uncommitted -> Serializable 로 갈 수록 격리수준이 높다(high)

Serializable -> Read Uncommitted 로 갈 수록 격리수준이 낮다(low)

1) Read Uncommitted
- SELECT 문장 수행시 해당 데이터에 Shared Lock 이 걸리지 않는 Level
- 아직 commit 되지 않은 트랜잭션 A 의 데이터를 B가 SELECT 할 수 있음
발생하는 문제 : dirty read, non-repeatable read, phantom read

2) Read Commited
- Select 문장이 수행되는 동안 데이터에 Shared Lock 이 걸린다
- 아직 commit 되지 않은 트랜잭션 A 의 데이터를 B가 SELECT 할 수 없다
발생하는 문제 : non-repeatable read, phantom read

3) Repeatable Read
- 트랜잭션 A가 시작되기 전에 커밋된 내용까지만 조회할 수 있다.
- 자신의 트랜잭션 보다 낮은 트랜잭션에서 커밋된 것만 읽는다.
(모든 InnoDB의 트랜잭션은 고유한 트랜잭션 시퀀스를 가지고 있으며 Undo 영역에 백업된 모든 레코드는 변경을 발생시킨 트랜잭션의 번호가 포함되어 있다)
발생하는 문제 : phantom read

4) Serializable
- 트랜잭션이 완료될 때까지 다른 트랜잭션이 해당되는 영역에 대한 수정 및 입력을 할 수 없다.
- 완벽한 LOCK 을 건다.

 

3. 격리 수준에 따라 나타나는 현상

3-1) Dirty Read

1) 트랜잭션 A 에서 값을 넣는다. insert into user (seq, gender, name) values (1, 'M', 'pyo');

2) 트랜잭션 B 에서 값을 읽는다. select * from user where seq = 1;

3) 트랜잭션 A 에서 insert 했던 값을 롤백한다. 

4) 트랜잭션 B 에서 읽어놓은 값은 실제로 DB에 존재하지 않는 데이터가 돼버린다. (dirty 하다)

 

3-2) Non-repeatable Read

1) 트랜잭션 A 에서 값을 읽는다. select gender, name from user where seq = 1;

    result : M pyo

2) 트랜잭션 B 에서 값을 넣는다. update user set gender = 'W' where seq = 1;

3) 트랜잭션 B 에서 commit 한다.

4) 트랜잭션 A 에서 값을 읽는다. select gender, name from user where seq = 1;

    result : W pyo

    남자였던 pyo 가 여자가 되었다. 위처럼 반복해서 동일한 데이터를 읽을 경우 상이한 결과가 나온다.

 

3-3) Phantom Read

1) 트랜잭션 A 에서 범위(range) 기준으로 값을 읽는다.

2) 트랜잭션 B 에서 1)에 포함되는 값을 넣는다.

3) 트랜잭션 B 에서 commit 한다.

4) 트랜잭션 A 에서 범위(range) 기준으로 값을 읽는다.

   result : 1)에서 읽히지 않은 값이 결과로 나온다 

 

Isolation Level Dirty Read NonRepeatable Read Phantom Read
Read Uncommitted Permitted Permitted Permitted
Read Commited - Permitted Permitted
Repeatable Read - - Permitted
Serializable - - -

 

 Non-repeatable read vs Phantom read

Non-repeatable read 와 Phantom read 의 차이

 

※ 엔진별 Default Isolation Level

- Mysql InnoDB 엔진 : Repeatable-Read 

- Oracle : Read-Commited

 

 

4. isolation level 지정하기

1) sql에서의 isolation level 지정

SET TRANSACTION ISOLATION LEVEL 
   { READ COMMITTED | READ UNCOMMITTED | REPEATABLE READ | SERIALIZABLE }

2) spring transaction 에서의 isolation level 지정

예제 참고

 

 

참고 :

영문으로 되어 있는 설명

그림으로 설명이 잘 되어 있는 곳

sql 코드로 설명이 잘 되어 있는 곳

mysql 공식문서

 

반응형

'DB' 카테고리의 다른 글

[DB] InnoDB vs MyISAM : InnoDB와 MyISAM의 차이점  (0) 2020.08.18

1. Servlet 생명주기

Init > Service(get/post) > Destory

https://minwan1.github.io/2017/10/08/2017-10-08-Spring-Container,Servlet-Container/

https://javannspring.tistory.com/231

 

 

2. BeanFactory 와 ApplicationContext 구조

https://whiteship.tistory.com/518

BeanFactory 를 ListenableBeanFactory, HierachialBeanFactory가 구현

ListenableBeanFactory, HierachialBeanFactory를 ApplicationContext가 구현

XmlWebApplicationContext, FileSystemXmlApplicationContext, ClassPathXmlApplicationContext 등이ApplicationContext 구현

 

 

3. 객체 생성의 차이

https://otep.tistory.com/19

ApplicationContext 는 Bean을 preload.

BeanFactory getBean 은 lazy 

 

 

4. Init/Destroy Method 지정 방법

Init 지정 방법

https://www.baeldung.com/running-setup-logic-on-startup-in-spring

1. @PostConstruct 사용

2. InitializingBean Interface 구현, afterPropertiesSet() 사용

3. ApplicationListener<ContextEvt> 구현

4. @Bean InitMethod 사용

순서 : @PostConstruct > InitializingBean > init-method > ContextStartedEvent 

https://programmer.ink/think/5ddc351b29481.html

 

Destory 지정 방법

https://www.baeldung.com/spring-shutdown-callbacks

1. @PreDestroy 사용

2. DisposableBean Interface 구현, Destroy() 사용

3. ApplicationListener<ContextEvt> 구현

4. ServletContetListener 구현 (web.xml 등록)

5. @Bean destroyMethod 사용

순서 : ContextClosedEvent > @PreDestroy > DisposableBean > destroy-method 

https://programmer.ink/think/5ddc351b29481.html

 

※ Init 은 Order @DependOn 등을 사용하여 주입 순서를 지정 할 수 있음

※ Bean Destroy 는 Bean Init 의 역순으로 이루어짐

 

 

반응형

2020.03.15 시작

 

반응형

Allocation of File Data in Disk 

Contiguous Allocation

단점 :

- external fragmentation, hole이 발생

장점 : 

- Fast I/O (헤드가 이동하는 시간이 짧음)

- 한번의 seek/rotation 으로 많은 바이트 transfer

- Realtime file용, process의 swapping 용으로 사용

- Direct access(=random access) 가능

 

Linked Allocation

장점 :

- external fragmentation 발생 없음

단점 :

- No random access

- Reliability 문제

- 한 sector 가 고장나 pointer 유실시 많은 부분을 잃음

- Pointer를 위한 공간이 block의 일부가 되어 공간 효율성을 떨어뜨림 (512bytes는 sector로, 4bytes는 pointer로 사용됨)

* FAT(File-allocation table) 파일 시스템 : 포인터를 별도의 위치에 보관하여 reliability와 공간효율성 문제 해결

 

Indexed Allocation

장점 :

- external fragmentation 발생 없음

- Direct access 가능

단점 :

- Small file의 경우 공간 낭비

- 파일이 너무 큰 경우 하나의 block 으로 index 를 저장 할 수 없음

 

UNIX 파일시스템 구조

Boot block

- 모든 파일시스템은 boot block 이 제일 위에있음

- 컴퓨터 부팅시 0번블럭(붙 블럭)을 올려서 부팅시킴

Superblock

- 파일시스템에 관한 총체적인 정보를 담고 있다

Inode

- 파일 이름을 제외한 파일의 모든 메타 데이터 저장

Data block

- 파일 실제 내용 보관

 

FAT 파일 시스템

FAT

메타데이터의 일부를 보관 (위치정보)

FAT 배열의 크기는 data block 의 크기와 동일

FAT 은 복제본을 저장하여 신뢰도를 높임

 

 

Free Space Management : 비어있는 블락 관리방법

1. Bit map 

Bit map 을 위한 부가적인 공간을 필요로 함

연속적인 n개의 free block을 찾는데 효과적

 

2. Linked list 

모든 free block들을 링크로 연결(free list)

연속적인 가용공간을 찾는게 힘듦

공간낭비 없음

 

3. Grouping

linked list 방법의 변형

첫번째 free block이 n개의 pointer를 가짐

n-1 pointer는 free data block을 가리킴

마지막 pointer가 가리키는 block은 또 다시 n pointer를 가짐

 

4. Counting

프로그램들이 종종 여러 개의 연속적인 block을 할당하고 반납한다는 성질에 착안

 

Directory Implementation : 디렉토리 저장 방법

1. Linear list

- <filename, file의 메타데이터>의 list

- 구현이 간단함

- 디렉토리 내에 파일이 있는지 찾기 위해서는 linear search 필요(time-consuming)

2. Hash Table

- linear list + hashing

- Hash table은 file name을 이 파일의 linear list의 위치로 바꾸어줌

- search time을 없앰

- Collision 발생 가능

* F에 Hash 함수 적용시 F는 특정 범위로 한정지어짐.

* Hash 함수를 적용하여 조회

 

 

 

 

※ 이화여대 반효경 교수님의 운영체제 강의 정리

반응형

+ Recent posts