참고 도서 : JPA 퀵스타트(채규태 지음)
jpa-quickstart's Introduction
jpa-quickstart's People
Forkers
ddangggoongjpa-quickstart's Issues
Issue : DDL 실행시 의도치 않은 email컬럼 발생
DDL 실행시 의도치 않은 "email" 컬럼 발생
1. 발생한 문제
JPA 코드를 실행하는 도중 "Entity"에 명시하지 않은 "email"컬럼이 쿼리문에 발생하게 되었습니다.
// console
(...)
Hibernate: drop table if exists S_EMP CASCADE
Hibernate: create table S_EMP (id bigint not null, DEPT_NAME varchar(255), email varchar(255), name varchar(255), salary double, START_DATE timestamp, title varchar(255), COMMISSION_PCT double, mailId varchar(255), primary key (id))
(...)
Hibernate: insert into S_EMP (COMMISSION_PCT, DEPT_NAME, mailId, name, salary, START_DATE, title, id) values (?, ?, ?, ?, ?, ?, ?, ?)
(...)
// Employee.java
package org.example.chapter02.biz.domain;
import lombok.Data;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import java.util.Date;
@Data
@Entity
@Table(name = "S_EMP")
public class Employee {
@Id
private Long id;
private String name;
private String mailId;
@Column(name = "START_DATE")
private Date startDate;
private String title;
@Column(name = "DEPT_NAME")
private String deptName;
private Double salary;
@Column(name = "COMMISSION_PCT")
private Double commissionPct;
}
콘솔과 "Entity"를 비교하면 분명 "email"컬럼 생성은 의도 하지 않았습니다. 하지만 콘솔에는
Hibernate: create table S_EMP (id bigint not null, DEPT_NAME varchar(255), email varchar(255), name varchar(255), salary double, START_DATE timestamp, title varchar(255), COMMISSION_PCT double, mailId varchar(255), primary key
2. 시도
1. DROP TABLE
"이전에 DDL로 생성한 테이블 컬럼이므로 h2데이터 베이스에서 테이블스키마를 저장해두는 풀이 있기 때문에 의도치 않은 컬럼이 생기는 것일까?" 하는 가정을 하게되었습니다.
DROP TABLE
을 시도 하였지만, 여전히 엔티티에서 정의하지 않은 "email"과 함께 DDL 실행됩니다.
2. 컬럼 필드 주석으로 추적하기
Employe
클래스의 멤버들을
@Id
private Long id;
위의 id
만 두고 주석처리를 하고 다시 JPA로 INSERT를 시도하였습니다.
분명 id
를 제외한 컬럼은 주석이지만 역시나 DDL은 "email"과 함께 다른 컬럼들도 생성하는 것을 확인하였습니다.
이는 Employee
클래스를 올바르게 참조하는 것이 아니라는 의미입니다.
3. 원인 및 해결
도서를 보며 코드를 따라 작성할 때, 도서의 환경은 Eclipse이고, 저의 환경은 IntelliJ입니다. IntelliJ는 다수의 프로젝트 생성을 허용하지 않기 때문에 내부에 "chapter01", "chapter02"패키지로 관리하고 있었습니다.
// hibernate 실행 시 작성했던 "chapter01"의 EmployeeVO
package org.example.chapter01.hibernate;
import lombok.Data;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import java.sql.Timestamp;
@Data
@Entity
@Table(name = "S_EMP")
public class EmployeeVO {
@Id
private Long id;
private String name;
@Column(name = "START_DATE")
private Timestamp startDate;
private String title;
@Column(name = "DEPT_NAME")
private String deptName;
private Double salary;
private String email;
}
이곳에 "email"컬럼이 있습니다.
// JPA 실행시 작성한 chapter02 경로의 Employee 클래스
package org.example.chapter02.biz.domain;
import lombok.Data;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import java.util.Date;
@Data
@Entity
@Table(name = "S_EMP")
public class Employee {
@Id
private Long id;
private String name;
private String mailId;
@Column(name = "START_DATE")
private Date startDate;
private String title;
@Column(name = "DEPT_NAME")
private String deptName;
private Double salary;
@Column(name = "COMMISSION_PCT")
private Double commissionPct;
}
두 코드 모두 @Entity
어노테이션과 @Table(name = "S_EMP")
어노테이션이 붙어 있는 공통점이 있습니다.
그렇다면 이렇게 추측해 볼 수 있습니다. "hibernate"에서 DDL을 수행할 때 @Entity
을 우선적으로 확인하여 "Entity"의 대상으로 하고 @Table
어노테이션의 테이블 명으로 DDL을 수행한뒤, 동일한 테이블 명에 대해서는 DDL을 수행 하지 않는 다는 것을 생각해 볼 수 있습니다.
매핑되는 테이블 명 달리하기
// "chapter01"의 테이블 명 변경
package org.example.chapter01.hibernate;
import lombok.Data;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import java.sql.Timestamp;
@Data
@Entity
@Table(name = "S_EMP_1")
public class EmployeeVO {
@Id
private Long id;
private String name;
@Column(name = "START_DATE")
private Timestamp startDate;
private String title;
@Column(name = "DEPT_NAME")
private String deptName;
private Double salary;
private String email;
}
// console
(...)
Hibernate: drop table if exists S_EMP CASCADE
(...)
Hibernate: drop table if exists S_EMP_1 CASCADE
Hibernate: create table S_EMP (id bigint not null, COMMISSION_PCT double, DEPT_NAME varchar(255), mailId varchar(255), name varchar(255), salary double, START_DATE timestamp, title varchar(255), primary key (id))
Hibernate: create table S_EMP_1 (id bigint not null, DEPT_NAME varchar(255), email varchar(255), name varchar(255), salary double, START_DATE timestamp, title varchar(255), primary key (id))
(...)
Hibernate: insert into S_EMP (COMMISSION_PCT, DEPT_NAME, mailId, name, salary, START_DATE, title, id) values (?, ?, ?, ?, ?, ?, ?, ?)
(...)
각기 다른 테이블이 생성되는 것을 알 수 있습니다.
![image](https://private-user-images.githubusercontent.com/118647313/341455738-da78828d-2418-45a7-bf30-7f4e1a0ca184.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjUzMzM0MDIsIm5iZiI6MTcyNTMzMzEwMiwicGF0aCI6Ii8xMTg2NDczMTMvMzQxNDU1NzM4LWRhNzg4MjhkLTI0MTgtNDVhNy1iZjMwLTdmNGUxYTBjYTE4NC5wbmc_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjQwOTAzJTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI0MDkwM1QwMzExNDJaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT03MzhkOTJhOTRjYmE3MTk1MTkwZjJhMzcxZDUxMjg5OTU5ZGY0ZWMyOWI5NTlmZTcwMTBlODM5NzQ5MGRkN2M3JlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCZhY3Rvcl9pZD0wJmtleV9pZD0wJnJlcG9faWQ9MCJ9.o4-YwZ5TjNAxDkntTTguI3_6NVQv27fLcOu-IFWb8_Y)
![image](https://private-user-images.githubusercontent.com/118647313/341456043-569a7e03-44a6-4ad8-8aee-52dc1ff130ba.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjUzMzM0MDIsIm5iZiI6MTcyNTMzMzEwMiwicGF0aCI6Ii8xMTg2NDczMTMvMzQxNDU2MDQzLTU2OWE3ZTAzLTQ0YTYtNGFkOC04YWVlLTUyZGMxZmYxMzBiYS5wbmc_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjQwOTAzJTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI0MDkwM1QwMzExNDJaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT00NmI4N2E4MjE4YTIzMmJiMDZjZjFmYTFlZTYxMWVhYTYwOTVhNmE4NGJlM2UxYjI2OGNmOWQ2MDRlNDU0ODAyJlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCZhY3Rvcl9pZD0wJmtleV9pZD0wJnJlcG9faWQ9MCJ9.Dyt4daoH7n4PoOaI2GNILjcy1zgC_z5rZw3GelCWpVE)
가정한 것에 의해 의도한대로 컬럼이 생성되었습니다.
Reader reader = Resources.getResourceAsReader("org/example/chapter01/mybatis/sql-map-config.xml")의 경로를 못찾는 문제
xml의 경로를 찾지 못하는 문제
Reader reader = Resources.getResourceAsReader("org/example/chapter01/mybatis/sql-map-config.xml");
디버깅 을 하다가 위 코드 부분에서 경로를 못찾는 문제가 있다는 것을 알게 되었습니다.
1. Try
오타 확인
JDBC에서 오타에 의해 실행이 안되었던 적이 있어 오타를 확인하여 몇가지의 오타를 고쳤지만, 여전히 동일한 오류가 발생하였습니다.
2. 원인
src
└── main
├── java
│ └── org
│ └── example
│ └── chapter01
│ └── mybatis
│ ├── EmployeeDAO.java
│ ├── EmployeeServiceClient.java
│ ├── EmployeeVO.java
│ ├── sql-map-config.xml
│ ├── s_emp-mapping.xml
└── resources
org.example.chapter01.mybatis
의 경로에 .xml
파일도 같이 두었습니다. 이로 인한 경로설정이 제대로 되지 않은 것이 원인이었습니다.
3. 해결
src
└── main
├── java
│ └── org
│ └── example
│ └── chapter01
│ └── mybatis
│ ├── EmployeeDAO.java
│ ├── EmployeeServiceClient.java
│ ├── EmployeeVO.java
└── resources
└── org
└── example
└── chapter01
└── mybatis
├── sql-map-config.xml
└── s_emp-mapping.xml
"IntelliJ IDEA"가 애플리케이션을 빌드할 때, 모든 리소스를 소스 경로에 상대적인 디렉토리 구조를 유지하면서 출력 디렉토리로 복사합니다. "IntelliJ IDEA" 에서는 아래의 형식은 기본적으로 리소스로 인식합니다.
.dtd
.jpeg
.properties
.gif
.jpg
.tld
.html
.png
.xml
참고 : IntelliJ 공식문서
.xml
파일을 클래스와 같은 경로에 두었기 때문에, 컴파일 시에 .java
파일이 .class
로 변환되는 동안 .xml
파일은 인식을 하지 못해 경로를 찾을 수 없었습니다. 즉, "IntelliJ"가 애플리케이션을 빌드 하는 과정에서 .xml
파일을 리소스로 인식하지 못하였습니다. 해당 파일을 resources
에 위치 시킴으로써 해결 할 수 있었습니다.
IDE는 다 비슷한줄 알고 단순히 도서를 보며 따라해보고 있었는데 이번 시간을 통해 Eclipse와 IntelliJ의 빌드 방식에 차이가 있다는 것을 알게되었습니다.
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.