Spring JPA 복합키(Composite Key) 설정
Spring JPA란 스프링 프레임워크에서 제공하는 JPA(Java Persistence API)의 구현체로 ORM 기술을 스프링 프레임워크와 통합하여 사용할 수 있도록 도와준다. ORM은 객체-관계 매핑(Object-Relational Mapping)의 약자로, 객체 지향 프로그래밍과 관계형 데이터베이스 간의 데이터 변환과 매핑을 자동화하는 기술이다. ORM은 개발자가 SQL 쿼리를 직접 작성하지 않고도 객체를 데이터베이스에 저장하고 조회할 수 있게 해주며 객체와 데이터베이스 간의 각종 매핑 규칙과 관계를설정하여 개발자가 객체 중심으로 개발할 수 있도록 지원한다.
Spring JPA is the implementation of the Java Persistence API (JPA) provided by the Spring Framework. It integrates ORM (Object-Relational Mapping) technology with the Spring Framework, allowing developers to use ORM seamlessly.
ORM, which stands for Object-Relational Mapping, is a technology that automates the conversion and mapping between object-oriented programming and relational databases. With ORM, developers can store and retrieve objects from a database without writing SQL queries directly. It provides various mapping rules and relationships between objects and databases, enabling developers to focus on object-oriented development.
By using Spring JPA, developers can benefit from the simplified data access layer, automatic SQL generation, transaction management, and other features provided by JPA. It eliminates the need for manual SQL queries and reduces the boilerplate code associated with database operations, making data persistence and retrieval easier and more efficient in Spring applications.
이를 이용해 개발자는 간편하게 데이터베이스와 통신을 처리하고, 객체를 데이터베이스에 매핑할 수 있다. 이러한 ORM의 사용은 기본 키를 가진 엔티티를 기반으로 객체 간의 관계를 매핑하는데 @Entity 어노테이션을 이용한 클래스를 생성하면 된다. 또 해당 클래스에 @Id 어노테이션을 사용하여 식별자(id) 필드를 지정해야 한다.
Using Spring JPA, developers can easily handle communication with the database and map objects to the database. The use of ORM allows developers to map relationships between objects based on entities with primary keys. By creating classes with the @Entity annotation, objects can be mapped to database tables. Additionally, the @Id annotation should be used to specify the identifier (id) field in the class.
@Entity
public class User {
@Id
private String id;
...
}
@Id 어노테이션을 사용하지 않는 경우 JPA에서는 해당 필드를 식별자로 인식할 수 없어 다음과 같은 오류를 발생시킨다.
If the @Id annotation is not used, JPA will not recognize the field as an identifier, and it will result in an error
@Entity
public class User {
@column
private String firstName;
@column
private String lastName;
...
}
Caused by: org.hibernate.AnnotationException: No identifier specified for entity: com.example.jpa.persistence.model.User
테이블에 기본 키를 사용하면 각 행을 고유하게 식별할 수 있으며 검색, 조인, 정렬과 같은 쿼리 결과에 성능을 미치게 되므로 기본 키를 사용하는 것이 맞다. 원칙적으로 기본 키를 사용하는 것이 맞지만 이미 사용중인 테이블에 데이터가 존재하고 수정이 어렵거나, 개발자가 테이블을 설계하지 않았거나, 권한이 없는 경우 등 해당 테이블을 수정하기 어려울 수 있다.
키가 없는 테이블은 JPA에서 어떻게 해야 할까? 이럴 때 복합 키를 이용하면 JPA에서 사용이 가능하다.
Using a primary key in a table allows each row to be uniquely identified and can improve performance in query results involving searching, joining, sorting, and other operations. In general, it is recommended to use a primary key. However, there are situations where it may be difficult to modify a table that already has data, or if the table was not designed by the developer, or if the developer lacks the necessary permissions. When dealing with a table that doesn't have a primary key, you can still utilize JPA by using a composite key. A composite key consists of multiple fields that, together, uniquely identify a row in the table. By defining a composite key in JPA, you can handle tables without a primary key and still benefit from JPA's features for mapping, querying, and managing the data.
Using a composite key allows you to define a custom set of fields as the unique identifier for an entity, even if the table itself doesn't have a primary key. This approach can help you work with existing tables or situations where modifying the table structure is challenging.
- UserCompositeKey.java
복합 키를 나타내기 위해 사용되는 클래스이다. 해당 클래스는 복합 키를 구성하는 각 컬럼을 멤버 변수로 가지고 있어야 한다. 복합 키를 first_name과 last_name으로 설정하고자 아래와 같이 멤버 변수를 추가하였다. @Embeddable 어노테이션은 해당 클래스가 JPA의 임베디드 클래스임을 나타내며 복합키를 매핑하는데 사용됨을 알려준다. JPA에서 엔티티의 필드에 접근하기 위해 Getter와 Setter를 만들어주어야 한다. 예제에서는 Lombok을 설정하여 사용하였지만 수동으로 만들어도 된다.
The following is an example of a class used to represent a composite key. This class should have member variables that correspond to each column of the composite key. In this example, we want to set the composite key as "first_name" and "last_name". The @Embeddable annotation indicates that this class is an embedded class in JPA and is used to map the composite key. In order to access the fields of the entity in JPA, you need to provide getters and setters for the fields. In the example, Lombok is used to generate the getters and setters automatically, but you can also create them manually.
package com.example.jpa.persistence.model;
import java.io.Serializable;
import javax.persistence.Embeddable;
import lombok.Getter;
import lombok.Setter;
@Embeddable
@Getter
@Setter
public class UserCompositeKey implements Serializable {
private static final long serialVersionUID = 1L;
private String firstName;
private String lastName;
}
- User.java
@EmbeddedId 어노테이션을 사용하여 UserCompositeKey 클래스가 복합키로 사용되고 있음을 명시한다. 복합 키를 사용할 때 first_name과 last_name에는 insertable = false, updatable = false 설정을 두어 두 필드가 데이터베이스에 대한 변경이 불가능하도록 설정을 하였다. 이 설정은 해당 필드를 읽기 전용 필드로 설정하여 수정 및 삭제를 방지해 테이블에서 각 행을 고유하게 식별할 수 있도록 사용한다.
By using the @EmbeddedId annotation, we indicate that the UserCompositeKey class is being used as a composite key. When using a composite key, we can specify insertable = false, updatable = false for the first_name and last_name fields to make them read-only and prevent any modifications to these fields in the database. This configuration sets these fields as immutable, ensuring that they are used only for identification purposes and cannot be updated or deleted. This helps in uniquely identifying each row in the table and maintaining data integrity.
By marking the first_name and last_name fields as read-only, we ensure that these fields are used solely for identification and cannot be changed. This is particularly useful when working with composite keys, where the primary purpose is to uniquely identify rows rather than modifying their values.
package com.example.jpa.persistence.model;
import javax.persistence.Column;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.Table;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
@Entity
@Table(name = "tb_user")
public class User {
@EmbeddedId
private UserCompositeKey id;
@Column(name = "first_name", insertable = false, updatable = false)
private String firstName;
@Column(name = "last_name", insertable = false, updatable = false)
private String lastName;
@Column(name = "email")
private String email;
}
insertable = false, updatable = false 설정을 하지 않으면 Spring은 아래와 같은 예외를 발생시킨다.
If you don't set insertable = false, updatable = false for the fields in your composite key, Spring may throw an exception
Caused by: org.hibernate.MappingException: Repeated column in mapping for entity: com.example.jpa.persistence.model.User column: first_name (should be mapped with insert="false" update="false")
- 복합키를 써야할 때?
복합 키를 사용하는 이유는 대표적으로 기본 키의 단일 컬럼으로 인해 고유성을 보장할 수 없어 여러 개의 컬럼을 조합하여 고유성을 확보할 수 있을때이다. 위와 같은 사용은 자칫 위험할 수 있는데 이 같은 방식은 복합 키를 사용하는데도 동일한 키가 데이터로 이미 존재하는 경우에는 데이터베이스 제약 조건 위반이나 조회 결과가 중복되어 나타나 개발자의 의도하지 않은 방향으로 수행될 수 있다. 왜냐하면 같은 성(first_name)과 같은 이름(last_name)을 가진 사람이 존재할 수 있기 때문이다. 따라서 복합키로도 데이터의 고유성을 확신할 수 없거나 중복된 데이터가 발생할 수 있는 상황이라면 DBA와 상의하여 해결방안에 대해 논의하는 것이 좋을 것이다.
One of the main reasons for using a composite key is when a single column as the primary key cannot guarantee uniqueness, and you need to combine multiple columns to ensure uniqueness. However, this approach can be risky because it can lead to database constraint violations or duplicate query results if the same key already exists in the data. For example, there might be multiple people with the same last name and first name. Therefore, if you cannot be sure of the uniqueness of the data with a composite key or if the possibility of duplicate data exists, it would be advisable to consult with a database administrator (DBA) to discuss possible solutions.
'Programming > Spring' 카테고리의 다른 글
Spring @RequestBody 415 Unsupported Media Type (feat. Postman) (0) | 2023.04.13 |
---|
댓글