[{"data":1,"prerenderedAt":564},["ShallowReactive",2],{"news-item-\u002Fja\u002Fnews\u002Ftypeorm":3},{"id":4,"title":5,"body":6,"category":551,"created by":552,"date":553,"description":554,"extension":555,"meta":556,"navigation":557,"path":558,"sections":559,"seo":560,"stem":561,"thumbnail":562,"__hash__":563},"content_ja\u002Fja\u002Fnews\u002Ftypeorm.md","TypeORMおよびTypeORMのQuery Builder",{"type":7,"value":8,"toc":534},"minimark",[9,16,20,23,27,30,33,37,40,43,46,49,53,56,59,62,65,68,71,77,80,86,89,100,106,109,115,121,124,130,136,139,145,151,157,159,165,171,177,179,185,191,197,199,205,211,217,219,225,231,234,237,242,248,250,256,261,267,269,275,280,286,291,297,302,308,313,316,319,325,331,334,340,344,350,352,357,361,367,369,374,378,384,386,391,395,401,403,408,412,418,420,425,430,436,442,446,452,454,460,464,470,472,478,482,488,492,498,502,508,511,514,517,520,523,526],[10,11,13],"h2",{"id":12},"初めに",[14,15,12],"strong",{},[17,18,19],"p",{},"TypeORMとは、NodeJS、Browser、Cordova、PhoneGap、Ionic、React Native、NativeScript、Expo、Electronといった各プラットフォームで実行でき、TypeScriptおよびJavaScript（ES5、ES6、ES7、ES8）を共用できるORMをいいます。TypeORMの目的としてはJavaScriptの最新機能をサポートでき、追加機能を提供することです。これにより、テーブルの少ないデータベースを使った小規模から、複数のデータベースを使った大規模までのアプリケーションを開発することができます。",[17,21,22],{},"ORMとはエンティティとデータベースのテーブルとをマップする手法をいいます。 ORMは、オブジェクトからテーブルへの変換およびテーブルからオブジェクトへの変換を自動化することにより、開発プロセスを簡素化します。",[24,25,26],"h3",{"id":26},"概要",[17,28,29],{},"TypeORMはnode.jsで実行される、TypeScriptで作ったObject Relational Mapperライブラリです。 TypeScriptは任意の入力機能を備えたJavaScriptの改良版であり、実行時に解釈しないコンパイラ型言語です。TypeScriptのコンパイラは、TypeScript（.ts）ファイルをJavaScript（.js）ファイルにコンパイルします。",[17,31,32],{},"TypeORMは、MySQL、PostgreSQL、MariaDB、SQLite、MS SQL Server、Oracle、SAP Hana、WebSQLといった色々なデータベースをサポートしています。TypeORMはデータベースに接続するようなアプリケーションを新規作成するために使いやすいORMです。TypeORMの機能はRDBMS向けの概念です。",[24,34,36],{"id":35},"typeormの特徴","TypeORMの特徴",[17,38,39],{},"モデルをもとにデータベースのスキーマを作成することを自動化",[17,41,42],{},"データベースへのオブジェクトの登録・更新・削除が易い",[17,44,45],{},"テーブルの間とのマッピング作成（1対1、1対多、多対多）",[17,47,48],{},"簡単なCLIコマンドの提供",[24,50,52],{"id":51},"typeormの利点","TypeORMの利点",[17,54,55],{},"TypeORMは簡単な実装でORMフレームワークを利用しやすいです。以下にその利点を示します。",[17,57,58],{},"1. 高品質で疎結合のアプリケーション",[17,60,61],{},"2. 拡張可能なアプリケーション",[17,63,64],{},"3. 他のモジュールとの結合が易い",[17,66,67],{},"4. 小規模アプリケーションから大規模な企業アプリケーションまでのあらゆるアーキテクチャに適合する",[17,69,70],{},"TypeORMは機能が沢山ありますが、この記事では、TypeScriptとTypeORMのQueryBuilderの使い方について説明させていただきます。",[10,72,74],{"id":73},"query-builder",[14,75,76],{},"Query Builder",[17,78,79],{},"Query Builderは複雑なSQL文を簡単に作るために使われ、Connectionメソッドから初期化されます。",[24,81,83],{"id":82},"connection",[14,84,85],{},"Connection",[17,87,88],{},"ConnectionメソッドでのQueryBuilderの使い方について、簡単な例を見てみましょう。",[90,91,96],"pre",{"className":92,"code":94,"language":95},[93],"language-text","import {getConnection} from \"typeorm\";\n\nconst user = await getConnection()\n.createQueryBuilder()\n.from(\"user\", \"user\")\n.select(\"user\")\n.where(\"user.id = :id\", { id: 1 })\n.getOne();\n","text",[97,98,94],"code",{"__ignoreMap":99},"",[24,101,103],{"id":102},"repository",[14,104,105],{},"Repository",[17,107,108],{},"以下のように、Query Builderを作成するためにRepositoryを使えます。",[90,110,113],{"className":111,"code":112,"language":95},[93],"import {getRepository} from \"typeorm\"; \nconst user = await getRepository(User)\n.createQueryBuilder(\"user\")\n.where(\"user.id = :id\", { id: 1 }) \n.getOne();\n",[97,114,112],{"__ignoreMap":99},[24,116,118],{"id":117},"adding-expression-use-getconnection-no-model-needed",[14,119,120],{},"Adding expression use getConnection (no model needed)",[17,122,123],{},"table user: id, name, age",[17,125,126,129],{},[14,127,128],{},"where"," は取得条件を満たすレコードを絞るために使われます。",[90,131,134],{"className":132,"code":133,"language":95},[93],"getConnection().createQueryBuilder().from(\"user\", \"user\").select(\"user\") .where(\"user.id = :id\", { id: 1 }) .getRawOne();\n",[97,135,133],{"__ignoreMap":99},[17,137,138],{},"上記のクエリは下記のクエリに相当します。",[90,140,143],{"className":141,"code":142,"language":95},[93],"select * from user where user.id=1;\n",[97,144,142],{"__ignoreMap":99},[17,146,147,150],{},[14,148,149],{},"orderBy"," はカラムの順序でレコードを並び替えるために使われます。",[90,152,155],{"className":153,"code":154,"language":95},[93],"getConnection().createQueryBuilder().from(\"user\", \"user\").orderBy(\"user.name\");\n",[97,156,154],{"__ignoreMap":99},[17,158,138],{},[90,160,163],{"className":161,"code":162,"language":95},[93],"select * from user order by user.name;\n",[97,164,162],{"__ignoreMap":99},[17,166,167,170],{},[14,168,169],{},"groupBy"," は指定したカラムでレコードをグループ化するために使われます。",[90,172,175],{"className":173,"code":174,"language":95},[93],"getConnection().createQueryBuilder().from(\"user\", \"user\").groupBy(\"user.id\")\n",[97,176,174],{"__ignoreMap":99},[17,178,138],{},[90,180,183],{"className":181,"code":182,"language":95},[93],"select * from user group by user.id; \n",[97,184,182],{"__ignoreMap":99},[17,186,187,190],{},[14,188,189],{},"limit"," は取得件数を指定するために使われます。",[90,192,195],{"className":193,"code":194,"language":95},[93],"getConnection().createQueryBuilder().from(\"user\", \"user\").limit(5);\n",[97,196,194],{"__ignoreMap":99},[17,198,138],{},[90,200,203],{"className":201,"code":202,"language":95},[93],"select * from user limit 5; \n",[97,204,202],{"__ignoreMap":99},[17,206,207,210],{},[14,208,209],{},"offset"," は取得を開始する位置を指定するために使われます。",[90,212,215],{"className":213,"code":214,"language":95},[93],"getConnection().createQueryBuilder().from(\"user\", \"user\").offset(5);\n",[97,216,214],{"__ignoreMap":99},[17,218,138],{},[90,220,223],{"className":221,"code":222,"language":95},[93],"select * from user offset 5;\n",[97,224,222],{"__ignoreMap":99},[17,226,227,230],{},[14,228,229],{},"joins"," は、関連する列に基づいて、2つ以上のテーブルの行を結合するために使われます。例えば、 「student」テーブルと「project」テーブルがあり、そのリレーションが1対多です。",[17,232,233],{},"student:  id, name, email, phone",[17,235,236],{},"project : id, name, student_id",[17,238,239],{},[14,240,241],{},"leftJoinAndSelect",[90,243,246],{"className":244,"code":245,"language":95},[93],"const student = await getConnection().createQueryBuilder().from(\"student\", \"student\")\n.leftJoinAndSelect(\"project\", \"project\", \"project.student_id = student.id\")\n.where(\"student.name = :name\", { name: \"Student1\" })\n.getOne();\n",[97,247,245],{"__ignoreMap":99},[17,249,138],{},[90,251,254],{"className":252,"code":253,"language":95},[93],"SELECT student.*, project.* FROM student student LEFT JOIN project project \nON project.student_id = student.id WHERE student.name = 'Student1'\n",[97,255,253],{"__ignoreMap":99},[17,257,258],{},[14,259,260],{},"innerJoinAndSelect",[90,262,265],{"className":263,"code":264,"language":95},[93],"const student = await getConnection().createQueryBuilder().from(\"student\", \"student\") \n.innerJoinAndSelect(\"project\", \"project\", \"project.student_id = student.id\") .where(\"student.name = :name\", { name: \"student1\" }) .getOne();\n",[97,266,264],{"__ignoreMap":99},[17,268,138],{},[90,270,273],{"className":271,"code":272,"language":95},[93],"SELECT student.*, project.* FROM student student INNER JOIN project project \nON project.student_id = student.id WHERE student.name = 'student1';\n",[97,274,272],{"__ignoreMap":99},[17,276,277],{},[14,278,279],{},"Insert",[90,281,284],{"className":282,"code":283,"language":95},[93],"import {getConnection} from \"typeorm\"; \n\nawait getConnection()\n.createQueryBuilder()\n.insert() \n.into('student') \n.values([ { name: \"test\", email: \"test@gmail.com\", phone: \"09011112222\"},\n { name: \"test2\", email: \"test2@gmail.com\", phone: \"09011112222\"}\n]) \n.execute();\n",[97,285,283],{"__ignoreMap":99},[17,287,288],{},[14,289,290],{},"Update",[90,292,295],{"className":293,"code":294,"language":95},[93],"import {getConnection} from \"typeorm\"; \n\nawait getConnection().createQueryBuilder() \n.update('student') \n.set({ name: \"test3\", email: \"test3@gmail.com\"}) \n.where(\"id = :id\", { id: 1 }) \n.execute(); \n",[97,296,294],{"__ignoreMap":99},[17,298,299],{},[14,300,301],{},"Delete",[90,303,306],{"className":304,"code":305,"language":95},[93],"import {getConnection} from \"typeorm\"; \n\n await getConnection() \n.createQueryBuilder() \n.delete()\n.from('student')\n.where(\"id = :id\", { id: 1 }) .execute();\n",[97,307,305],{"__ignoreMap":99},[17,309,310],{},[14,311,312],{},"Subqueries",[17,314,315],{},"例1：subQueryを使うことで、「email」に”test”が含まれているレコードの「name」を「student」テーブルから取得します。",[17,317,318],{},"例2：subQueryを使うことで、「studentId」、「studentName」、「name」に”test”が含まれているレコードの大きな「projectId」を「project」テーブルから取得します。",[90,320,323],{"className":321,"code":322,"language":95},[93],"const student = await getConnection().createQueryBuilder().select(\"student.name\", \"name\") \n.from((subQuery) => { return subQuery.select(\"student.name\", \"name\") \n                     .from(\"student\", \"student\").where(\"student.email like :email\", { email: '%test%'}) },\n                   \"student\") .getRawMany();\n\nconst student = await getConnection().createQueryBuilder()\n.select(`student.id as studentId,student.name as studentName,project.id as projectId`)) \n.from(\"student\", \"student\").leftJoin(\"project\", \"project\", \"project.student_id = student.id\")\n.where (\"project.id = (select max(id) from project where name like '%test%' \")).getRawMany();\n",[97,324,322],{"__ignoreMap":99},[24,326,328],{"id":327},"adding-expression-use-getrepository-with-model",[14,329,330],{},"Adding expression use getRepository() with model",[17,332,333],{},"例えば、以下のようなUserモデルがあります。",[90,335,338],{"className":336,"code":337,"language":95},[93],"import {Entity, PrimaryGeneratedColumn, Column} from \"typeorm\";\n\n@Entity('user') \nexport class User { \n@PrimaryGeneratedColumn() \nid: number;\n \n@Column('varchar', {name: 'name', nullable: true, length: 50}) \nname: string | null; \n\n@Column('int', {name: 'age', nullable: true}) \nname: number | null; \n}\n",[97,339,337],{"__ignoreMap":99},[17,341,342,129],{},[14,343,128],{},[90,345,348],{"className":346,"code":347,"language":95},[93],"getRepository(User).createQueryBuilder(\"user\").where(\"user.id= :id\", { id: 1 });\n",[97,349,347],{"__ignoreMap":99},[17,351,138],{},[90,353,355],{"className":354,"code":142,"language":95},[93],[97,356,142],{"__ignoreMap":99},[17,358,359,150],{},[14,360,149],{},[90,362,365],{"className":363,"code":364,"language":95},[93],"getRepository(User).createQueryBuilder(\"user\").orderBy(\"user.name\");\n",[97,366,364],{"__ignoreMap":99},[17,368,138],{},[90,370,372],{"className":371,"code":162,"language":95},[93],[97,373,162],{"__ignoreMap":99},[17,375,376,170],{},[14,377,169],{},[90,379,382],{"className":380,"code":381,"language":95},[93],"getRepository(User).createQueryBuilder(\"user\") .groupBy(\"user.id\")\n",[97,383,381],{"__ignoreMap":99},[17,385,138],{},[90,387,389],{"className":388,"code":182,"language":95},[93],[97,390,182],{"__ignoreMap":99},[17,392,393,190],{},[14,394,189],{},[90,396,399],{"className":397,"code":398,"language":95},[93],"getRepository(User).createQueryBuilder(\"user\").limit(5);\n",[97,400,398],{"__ignoreMap":99},[17,402,138],{},[90,404,406],{"className":405,"code":202,"language":95},[93],[97,407,202],{"__ignoreMap":99},[17,409,410,210],{},[14,411,209],{},[90,413,416],{"className":414,"code":415,"language":95},[93],"getRepository(User).createQueryBuilder(\"user\") .offset(5);\n",[97,417,415],{"__ignoreMap":99},[17,419,138],{},[90,421,423],{"className":422,"code":222,"language":95},[93],[97,424,222],{"__ignoreMap":99},[17,426,427,429],{},[14,428,229],{}," は、関連する列に基づいて、2つ以上のテーブルの行を結合するために使われます。以下の2つのエンティティを見ましょう。",[90,431,434],{"className":432,"code":433,"language":95},[93],"import {Entity, PrimaryGeneratedColumn, Column, OneToMany} from \"typeorm\";\nimport {Project} from \".\u002FProject\"; \n\n@Entity('student')\nexport class Student { \n@PrimaryGeneratedColumn()\nid: number; \n\n@Column('varchar', {name: 'name', nullable: true, length: 50})\nname: string | null;\n\n@Column('varchar', {name: 'email', nullable: true, length: 30})\nemail: string | null;\n\n@Column('varchar', {name: 'phone', nullable: true, length: 11})\nphone: string | null;\n\n@OneToMany(()=> Project, project => project.student) \nprojects: project[]; \n} \n",[97,435,433],{"__ignoreMap":99},[90,437,440],{"className":438,"code":439,"language":95},[93],"import {Entity, PrimaryGeneratedColumn, Column, ManyToOne}\n\nfrom \"typeorm\"; import {Student} from \".\u002FStudent\";\n\n@Entity('project') \nexport class Project {\n\n@PrimaryGeneratedColumn() \nid: number;\n\n@Column('varchar', {name: 'name', nullable: true, length: 50})\nname: string | null;\n\n@Column('bigint', {name: 'student_id', nullable: true, unsigned: true})\nstudentId: number | null;\n\n@ManyToOne(() => Student, student => student.projects)\n@JoinColumn([{name: 'student_id', referencedColumnName: 'id'}])\nstudent : Student;\n}\n",[97,441,439],{"__ignoreMap":99},[17,443,444],{},[14,445,241],{},[90,447,450],{"className":448,"code":449,"language":95},[93],"const student = await getRepository(Student).createQueryBuilder(\"student\")\n.leftJoinAndSelect(\"student.projects\", \"project\")\n.where(\"student.name = :name\", { name: \"Student1\" })\n.getOne();\n",[97,451,449],{"__ignoreMap":99},[17,453,138],{},[90,455,458],{"className":456,"code":457,"language":95},[93],"SELECT student.*, project.* FROM student student LEFT JOIN projects project \nON project.student = student.id WHERE student.name = 'Student1'\n",[97,459,457],{"__ignoreMap":99},[17,461,462],{},[14,463,260],{},[90,465,468],{"className":466,"code":467,"language":95},[93],"const student = await getRepository(Student).createQueryBuilder(\"student\")\n.innerJoinAndSelect(\"student.projects\", \"project\")\n.where(\"student.name = :name\", { name: \"student1\" })\n.getOne();\n",[97,469,467],{"__ignoreMap":99},[17,471,138],{},[90,473,476],{"className":474,"code":475,"language":95},[93],"SELECT student.*, project.* FROM students student INNER JOIN projects project \nON project.student = student.id WHERE student.name = 'Student1';\n",[97,477,475],{"__ignoreMap":99},[17,479,480],{},[14,481,279],{},[90,483,486],{"className":484,"code":485,"language":95},[93],"import {getConnection} from \"typeorm\"; \n\nawait getRepository(Student)\n.createQueryBuilder() \n.insert() \n.into(Student) \n.values([ { name: \"test\", email: \"test@gmail.com\", phone: \"09011112222\"}, \n{ name: \"test2\", email: \"test2@gmail.com\", phone: \"09011112222\"} ]) \n.execute();\n",[97,487,485],{"__ignoreMap":99},[17,489,490],{},[14,491,290],{},[90,493,496],{"className":494,"code":495,"language":95},[93],"import {getConnection} from \"typeorm\"; \n\nawait getRepository(Student)\n.createQueryBuilder() \n.update(Student) \n.set({ name: \"test3\", email: \"test3@gmail.com\"}) \n.where(\"id = :id\", { id: 1 }) .execute();\n",[97,497,495],{"__ignoreMap":99},[17,499,500],{},[14,501,301],{},[90,503,506],{"className":504,"code":505,"language":95},[93],"import {getConnection} from \"typeorm\"; \nawait getRepository(Student).createQueryBuilder() \n.delete() \n.from(Student) \n.where(\"id = :id\", { id: 1 }) \n.execute();\n",[97,507,505],{"__ignoreMap":99},[10,509,510],{"id":510},"最後に",[17,512,513],{},"簡単なものから複雑なものまでクエリ文を作成できるため、Query Builderを使用することをお勧めします。",[17,515,516],{},"シンタックスは純粋なクエリとほぼ同じなので、実装しやすくて、可読性が高いです。",[17,518,519],{},"モデル宣言なしで普通どおりにQuery Builderを使うことができます。",[17,521,522],{},"パフォーマンス面でQuery Builder利用による抽出時間はTypeORMの既存APIリポジトリの利用よりも早いです。",[10,524,525],{"id":525},"参照元",[17,527,528],{},[529,530,531],"a",{"href":531,"rel":532},"https:\u002F\u002Ftypeorm.io\u002F",[533],"nofollow",{"title":99,"searchDepth":535,"depth":535,"links":536},2,[537,543,549,550],{"id":12,"depth":535,"text":12,"children":538},[539,541,542],{"id":26,"depth":540,"text":26},3,{"id":35,"depth":540,"text":36},{"id":51,"depth":540,"text":52},{"id":73,"depth":535,"text":76,"children":544},[545,546,547,548],{"id":82,"depth":540,"text":85},{"id":102,"depth":540,"text":105},{"id":117,"depth":540,"text":120},{"id":327,"depth":540,"text":330},{"id":510,"depth":535,"text":510},{"id":525,"depth":535,"text":525},"tech talk","Briswell Vietnam Co Ltd","2022-06-29","初めに TypeORMとは、NodeJS、Browser、Cordova、PhoneGap、Ionic、React Native、NativeScript、Expo、Electronといった各プラットフォームで実行でき、TypeScriptおよびJavaScript（ES5、ES6、ES7、ES8）を共用できるORMをいいます。TypeORMの目的としてはJavaScriptの最新機能をサポートでき、追加機能を提供することです。これにより、テーブルの少ないデータベースを使った小規模から、複数のデータベースを使った大規模までのアプリケーションを開発することができます。","md",{},true,"\u002Fja\u002Fnews\u002Ftypeorm",null,{"title":5,"description":554},"ja\u002Fnews\u002Ftypeorm","https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2022\u002F06\u002F08154314\u002Fquerybuilder-typeorm.jpg","wAQ4rNXwCP3S1A-I-8YSr586mrz61C8wAeWn0CcPRhI",1782205042473]