JPA(Hibernate)の失敗談。
同一セッションにおいて同一行はキャッシュされる。よって、何らかの要因で先行のSQLがそのカラム値とは別の値を返す場合、後のSQLでカラムを指定しても使用されない。
plugins {
id 'java'
id 'org.springframework.boot' version '3.4.1'
id 'io.spring.dependency-management' version '1.1.7'
}
group = 'com.example'
version = '0.0.1-SNAPSHOT'
java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
compileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
runtimeOnly 'com.oracle.database.jdbc:ojdbc11'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}
tasks.named('test') {
useJUnitPlatform()
}
@Entity
@Data
public class Sample {
@Id
String code;
@Column(name = "value1")
String value1;
}
Sample result1 = (Sample)em.createNativeQuery("select code, 'hoge' as value1 from SAMPLE where code = 'code001'", Sample.class).getSingleResult();
System.out.println(result1);
Sample result2 = (Sample)em.createNativeQuery("select code, value1 from SAMPLE where code = 'code001'", Sample.class).getSingleResult();
System.out.println(result2);
System.out.println(result1 == result2);
実行結果は以下となる。
Sample(code=code001, value1=hoge)
Sample(code=code001, value1=hoge)
true
先行のSQLはカラム値ではなくhoge
という固定文字列を取得している。その後のSQLはカラムを指定しているが、実際にはキャッシュから返されるので、結果的にカラム値が無視されたような挙動になる。
キャッシュの存在を確認するため、二つのSQLの間にclear
を実行する。
Sample result1 = ...
System.out.println(result1);
em.clear();
Sample result2 = ...
System.out.println(result2);
System.out.println(result1 == result2);
すると下記のような結果が得られる。
Sample(code=code001, value1=hoge)
Sample(code=code001, value1=value1)
false