Golang xORM 편리한 기능 소개

xORM은 필자가 선호하는 ORMObject–relational mapping 프레임워크이다. 주요 특징Features은 아래와 같다.

https://gobook.io/read/gitea.com/xorm/manual-en-US/

https://gobook.io/read/gitea.com/xorm/manual-en-US/

https://gobook.io/read/gitea.com/xorm/manual-en-US/

https://gobook.io/read/gitea.com/xorm/manual-en-US/

xORM은 대부분의 ORM에서 지원하는 테이블 간의 연관 관계 처리를 지원하지 않는다. 필요하면 직접 구현해야 한다. 언뜻 생각하면 불편할 것 같은데 연관 관계를 포기함으로써 기능들이 단순화되어 익히는데 시간이 짧게 걸리고 쓰기 쉽다는 장점이 있다.

이 글은 필자가 xORM을 사용하며 편리하다고 느낀 기능을 소개한다.

INSERT/UPDATE 시간을 자동으로 기록하기

아래와 같이 상품 테이블이 있다고 생각해 보자.

1
2
3
4
5
6
CREATE TABLE IF NOT EXISTS products
(
    `id`   INT          NOT NULL AUTO_INCREMENT,
    `name` VARCHAR(100) NOT NULL,
    PRIMARY KEY (id)
);

xORM으로 테이블을 아래와 같이 struct에 매핑할 수 있다.

1
2
3
4
5
6
7
type Product struct {
	Id   int64  `xorm:"id pk autoincr"`
	Name string `xorm:"name"`
}
func (Product) TableName() string {
	return "products"
}

INSERT/UPDATE 시에 시간을 자동으로 기록하고 싶을 때가 있다.

이때 사용할 수 있는 것이 xORM의 CreatedUpdated 태그이다.

Created tag will automatically inserted current time when you insert one record.  - https://gobook.io/read/gitea.com/xorm/manual-en-US/chapter-04/1.created.html

Updated could automatically add a timestamp on the record when you insert or update one record. You have to add one updated tag on xorm tag section.  -https://gobook.io/read/gitea.com/xorm/manual-en-US/chapter-06/2.updated.html

먼저 테이블에 시간 컬럼을 추가한다.

1
2
3
4
5
6
CREATE TABLE IF NOT EXISTS products
(
    -- ...
    `created_at` DATETIME     NOT NULL,
    `updated_at` DATETIME     NOT NULL,
);

그리고 코드에 CreatedUpdated 태그로 추가 매핑한다.

1
2
3
4
5
type Product struct {
    // ...
    CreatedAt time.Time `xorm:"created"`
    UpdatedAt time.Time `xorm:"updated"`
}

xORM은 INSERT 하면 created_at 컬럼에 UPDATE 하면 updated_at 컬럼에 현재 시간을 자동으로 기록한다.

1
2
3
4
var product Product
engine.Insert(&product)
// ...
engine.ID(1).Update(&product)

데이터를 실제로 삭제하지 않고 삭제 효과 누리기

여러 가지 이유로 테이블에 데이터를 삭제하지 않으면서 삭제한 것처럼 해야 할 때가 있다.

간단하게는 삭제 여부를 기록하는 컬럼(Status)을 추가하여 구현할 수 있다.

1
2
3
4
type Product struct {
    // ...
    Status string `xorm:"status"`
}

단점은 상품 테이블을 조회할 때 삭제 여부를 항상 염두에 두어야 한다.

이때 사용할 수 있는 것이 xORM의 Deleted 태그이다.

Deleted will not really remove one record from table but only tag as deleted via current time. - https://gobook.io/read/gitea.com/xorm/manual-en-US/chapter-07/1.deleted.html

먼저 삭제 시간 컬럼을 추가한다.

1
2
3
4
5
CREATE TABLE IF NOT EXISTS products
(
    -- ...
    `deleted_at`    DATETIME,
);

그리고 코드에 Deleted 태그로 추가 매핑한다.

1
2
3
4
type Product struct {
    // ...
    DeletedAt time.Time `xorm:"deleted"`
}

xORM은 SELECT 할 때 deleted_at에 값이 있다면 자동으로 결과에서 제외한다.

페이징 할 때 데이터와 총건수를 한 번에 조회하기

일반적으로 페이징 UI를 만들기 위해서는 두 가지가 필요하다.

  • 전체 데이터 수
  • 페이지 데이터

출처 : https://ant.design/components/table/

출처 : https://ant.design/components/table/

xORM으로 페이징 데이터를 아래처럼 조회할 수 있다.

1
2
3
4
5
6
offset := (pageable.Page - 1) * pageable.PageSize
var products Product
// 페이지 데이터 조회
err := engine.Limit(pageable.PageSize, offset).Find(&products)
// 전체 데이터 수 조회
count, err := engine.Count(entity.Product{});

xORM에서 제공하는 FindAndCount 함수로 위의 두 가지(페이지 데이터 조회, 전체 데이터 수 조회)를 한 번에 할 수 있다.

1
count, err := engine.Limit(pageable.PageSize, offset).FindAndCount(&products)

코드는 줄었지만 데이터베이스 쿼리는 2번으로 동일하다.

마치며

필자는 FindAndCount 함수를 코드 리뷰를 통해 알았다. 코드 리뷰를 함께한 동료들에게 감사한다.


Popit은 페이스북 댓글만 사용하고 있습니다. 페이스북 로그인 후 글을 보시면 댓글이 나타납니다.