[java] Java Querydsl을 사용하여 데이터베이스 테이블의 데이터 필드 제약 조건 이력 관리하기

데이터베이스 테이블의 필드 제약 조건은 데이터의 무결성을 보장하기 위해 매우 중요합니다. 이러한 필드 제약 조건을 변경하거나 삭제할 때에는 이력을 꼭 관리해야 합니다. Java Querydsl은 데이터베이스 쿼리를 더 쉽게 작성하고 실행할 수 있도록 도와주는 라이브러리입니다. 이번 포스트에서는 Java Querydsl을 사용하여 데이터베이스 테이블의 데이터 필드 제약 조건 이력을 관리하는 방법에 대해 알아보겠습니다.

필요한 라이브러리 추가하기

먼저 Java Querydsl을 사용하기 위해 필요한 라이브러리들을 추가해야 합니다. 이 예제에서는 Gradle을 사용하므로, build.gradle 파일에 다음과 같이 의존성을 추가해주세요:

dependencies {
    implementation 'com.querydsl:querydsl-core:4.4.0'
    implementation 'com.querydsl:querydsl-jpa:4.4.0'
    implementation 'javax.persistence:javax.persistence-api:2.2'
    implementation 'org.hibernate:hibernate-core:5.4.10.Final'
}

Entity 클래스 생성하기

이제 데이터베이스 테이블과 매핑되는 Entity 클래스를 생성해야 합니다. 예를 들어, Product 테이블의 name 필드의 제약 조건을 변경하는 경우를 가정해보겠습니다.

import javax.persistence.*;

@Entity
@Table(name = "product")
public class Product {
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @Column(name = "name")
    private String name;
    
    // Getter and Setter
}

필드 제약 조건 변경 이력 테이블 생성하기

이력을 관리하기 위해 필드 제약 조건 변경 이력을 저장할 테이블을 생성해야 합니다. 이 테이블은 기존 필드 제약 조건 정보와 변경된 필드 제약 조건 정보를 저장하는 역할을 합니다. 예제에서는 product_constraint_history라는 테이블을 생성하겠습니다:

CREATE TABLE product_constraint_history (
    id          BIGINT AUTO_INCREMENT PRIMARY KEY,
    product_id  BIGINT,
    column_name VARCHAR(255),
    constraint_name VARCHAR(255),
    previous_constraint VARCHAR(255),
    new_constraint VARCHAR(255),
    modified_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (product_id) REFERENCES product(id)
);

Querydsl 쿼리 작성하기

Java Querydsl을 사용하여 필드 제약 조건 변경 이력을 관리하려면 해당 테이블에 데이터를 추가, 수정, 조회하는 작업을 해야 합니다.

데이터 추가

import com.querydsl.jpa.impl.JPAQueryFactory;

@Service
public class ProductService {

    @PersistenceContext
    private EntityManager entityManager;

    @Transactional
    public void updateFieldConstraint(Product product, String newConstraint) {
        QProduct qProduct = QProduct.product;
        
        // 이전 제약 조건 조회
        String previousConstraint = entityManager.createQuery(
                "SELECT p.columnCheckConstraints FROM Product p WHERE p.id = :id", String.class)
                .setParameter("id", product.getId())
                .getSingleResult();
        
        // 제약 조건 변경
        entityManager.createQuery(
                "ALTER TABLE product ALTER COLUMN name " +
                        "DROP CONSTRAINT product_name_check, " +
                        "ADD CONSTRAINT product_name_check " +
                        "CHECK (name " + newConstraint + ")"
        ).executeUpdate();
        
        // 변경 이력 저장
        QProductConstraintHistory qHistory = QProductConstraintHistory.productConstraintHistory;
        ProductConstraintHistory history = new ProductConstraintHistory();
        history.setProductId(product.getId());
        history.setColumnName("name");
        history.setConstraintName("product_name_check");
        history.setPreviousConstraint(previousConstraint);
        history.setNewConstraint(newConstraint);
        entityManager.persist(history);
    }
}

데이터 수정

import com.querydsl.jpa.impl.JPAQueryFactory;

@Service
public class ProductService {

    @PersistenceContext
    private EntityManager entityManager;

    @Transactional
    public void updateFieldConstraint(Product product, String newConstraint) {
        QProduct qProduct = QProduct.product;
        
        // 이전 제약 조건 조회
        String previousConstraint = entityManager.createQuery(
                "SELECT p.columnCheckConstraints FROM Product p WHERE p.id = :id", String.class)
                .setParameter("id", product.getId())
                .getSingleResult();
        
        // 제약 조건 변경
        entityManager.createQuery(
                "ALTER TABLE product ALTER COLUMN name " +
                        "DROP CONSTRAINT product_name_check, " +
                        "ADD CONSTRAINT product_name_check " +
                        "CHECK (name " + newConstraint + ")"
        ).executeUpdate();
        
        // 변경 이력 수정
        JPAQueryFactory queryFactory = new JPAQueryFactory(entityManager);
        queryFactory.update(qProductConstraintHistory)
                .where(qProductConstraintHistory.productId.eq(product.getId()))
                .set(qProductConstraintHistory.newConstraint, newConstraint)
                .execute();
    }
}

데이터 조회

import com.querydsl.jpa.impl.JPAQueryFactory;

@Service
public class ProductService {

    @PersistenceContext
    private EntityManager entityManager;

    public List<ProductConstraintHistory> getFieldConstraintHistory(Product product) {
        QProductConstraintHistory qHistory = QProductConstraintHistory.productConstraintHistory;
        JPAQueryFactory queryFactory = new JPAQueryFactory(entityManager);
        return queryFactory.selectFrom(qHistory)
                .where(qHistory.productId.eq(product.getId()))
                .fetch();
    }
}

마치며

Java Querydsl을 사용하여 데이터베이스 테이블의 데이터 필드 제약 조건 이력을 관리하는 방법에 대해 알아보았습니다. Querydsl을 사용하면 데이터의 무결성을 보장하는 필드 제약 조건의 변경 이력을 쉽게 관리할 수 있습니다. 필드 제약 조건을 변경하거나 삭제할 때는 이력을 꼭 관리하여 데이터의 일관성을 유지하는 것이 중요합니다.