Go 언어 SQLBoiler로 유형 안전에 여러 조건의 Where 절을 작성

11384 단어 MySQLDBORMSQLBoiler5

전치



작은 재료가됩니다
최근 Go 언어로 API를 만들고 있고 ORM에 SQLBoiler을 채용했습니다.
조금 복잡한 Where 절을 타입 세이프로 쓰는 방법의 정보가 의외로 적은 것이 아닐까 생각 집필했습니다.

테이블 구성



이러한 테이블이 있다고 가정합니다.
CREATE TABLE `foods` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `name` varchar(45) COLLATE utf8mb4_bin NOT NULL,
  `price` int(10) unsigned NOT NULL,
  `note` varchar(45) COLLATE utf8mb4_bin DEFAULT NULL,
  PRIMARY KEY (`id`),
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;




원시 쿼리



조금도 복잡한 Where 절이 아니라고 생각합니다만, 이 정도의 조건에서도 타입 세이프로 쓰지 않은 기사가 많기 때문에 집필하고 있습니다.
복잡한 하위 쿼리 등을 기대하는 사람들에게 죄송합니다.
SELECT 
    *
FROM
    foods
WHERE
    price >= 100 AND price < 500
        AND (note = '特売' OR note IS NULL)

SQLBoiler



비교적 잘 소개된 설명



이렇게 소개되는 경우가 많은 인상입니다. "간단하게 빌더로 쿼리를 조립한다"라고도 말할까요?
모델에 매핑해 주는 이점은 있습니다만, 너무 생 쿼리와 변함없이 필자로서는 더 ORM의 혜택을 받고 싶습니다. 혜택을 받고 싶지 않다면 ORM을 채용하지 않는 옵션도 있다고 생각합니다.

소스 코드
res, err := models.Foods(
    qm.Where("price >= ? AND price < ? AND (note = ? OR note IS NULL)", 100, 500, "特売")).
    All(context.Background(), db.DB)

SQLBoiler 디버그 모드에서 출력되는 쿼리
SELECT * FROM `foods` WHERE (price >= ? AND price < ? AND (note = ? OR note IS NULL));
[100 500 特売]

WHERE/AND/OR/() 마다 조립하는 기술



위의 표현, 공식 문서에서 이름을 찾을 수 없으며 독해력이나 어휘력이 없어서 죄송합니다.
이런 식으로 나누어 쓸 수도 있습니다. 比較的よく紹介されている記述 와 비교하면 ORM의 활용률은 올랐습니다. AND 라든지 OR , () 의 typo는 줄어들지도 모릅니다. 필자로서는 더 ORM의 혜택을 받고 싶습니다.

소스 코드
res, err := models.Foods(
    qm.Where("price >= ?", 100), qm.And("price < ?", 500),
    qm.Expr(qm.And("note = ?", "特売"), qm.Or("note IS NULL"))).
    All(context.Background(), db.DB)

SQLBoiler 디버그 모드에서 출력되는 쿼리
SELECT * FROM `foods` WHERE price >= ? AND price < ? AND (note = ? OR note IS NULL);
[100 500 特売]

유형 안전을 조립하는 묘사



ORM의 혜택을 많이 받고 싶다면 다음과 같이 쓸 수 있습니다. SQLBoiler 공식적으로 강력히 추천하는 방법입니다.
「중복적인 기술이지만, 타입 세이프로 컴파일 에러가 되기 때문에 좋지요」라고 하는 것입니다. SQLBoiler에 관계없이 다른 ORM에서도 이러한 사상은 있네요.
인텔리센스(코드 보완)를 활용할 수 있는 것도 매력의 하나라고 느낍니다.

소스 코드
res, err := models.Foods(
    models.FoodWhere.Price.GTE(100), models.FoodWhere.Price.LT(500),
    qm.Expr(models.FoodWhere.Note.EQ(null.StringFrom("特売")), qm.Or2(models.FoodWhere.Note.IsNull()))).
    All(context.Background(), db.DB)

SQLBoiler 디버그 모드에서 출력되는 쿼리
SELECT * FROM `foods` WHERE `foods`.`price` >= ? AND `foods`.`price` < ? AND (`foods`.`note` = ? OR `foods`.`note` is null);
[100 500 {特売 true}]

끝에



ORM 자체의 부디라고 하는 것은 비비기 쉬운 재료라고 생각하므로 할애합니다. 원래 ORM을 채용해도 풀 스택이나 마이크로의 논의도 있습니다. 모든 것을 ORM에 의지하는 것은 어렵고 생 쿼리로 쓰는 편이 좋은 장면도 있으므로 「ORM으로 소모한다」가 아니라 밸런스 좋게 사용해 생산성이나 보수성, 견뢰성을 올릴 수 있으면 좋을까라고 생각하고 있습니다 . 또, 공식 문서에 타입 세이프한 기술 방법도 써 있습니다만 조사중은 모릅니다. 코드를 쓰고 나서 결과론으로서 「아아, 이 일인가」라고 이해했습니다. 필자의 독해력의 문제를 선반에 올리면서, 문서를 좀 더 친절하게 해 주었으면 합니다.

좋은 웹페이지 즐겨찾기