mirror of
https://github.com/typeorm/typeorm.git
synced 2025-12-08 21:26:23 +00:00
repository#persist now returns entity and inserts ids into persisted entities ; added basic integration tests
This commit is contained in:
parent
bdfc2eb05f
commit
97208dc72a
@ -132,6 +132,7 @@ export class Gulpfile {
|
||||
integration() {
|
||||
chai.should();
|
||||
chai.use(require("sinon-chai"));
|
||||
chai.use(require("chai-as-promised"));
|
||||
return gulp.src("./build/es5/test/integration/**/*.js")
|
||||
.pipe(mocha());
|
||||
}
|
||||
|
||||
@ -25,6 +25,7 @@
|
||||
],
|
||||
"devDependencies": {
|
||||
"chai": "^3.4.1",
|
||||
"chai-as-promised": "^5.2.0",
|
||||
"del": "^2.2.0",
|
||||
"gulp": "^3.9.0",
|
||||
"gulp-mocha": "^2.2.0",
|
||||
|
||||
@ -18,7 +18,6 @@ TypeORM.createMysqlConnection(options, [Post]).then(connection => {
|
||||
post.text = "Hello how are you?";
|
||||
post.title = "hello";
|
||||
|
||||
// finally save it
|
||||
let postRepository = connection.getRepository<Post>(Post);
|
||||
|
||||
postRepository
|
||||
|
||||
181
sample/sample10-mixed/app.ts
Normal file
181
sample/sample10-mixed/app.ts
Normal file
@ -0,0 +1,181 @@
|
||||
import {TypeORM} from "../../src/TypeORM";
|
||||
import {Post} from "./entity/Post";
|
||||
import {PostDetails} from "./entity/PostDetails";
|
||||
import {Image} from "./entity/Image";
|
||||
import {ImageDetails} from "./entity/ImageDetails";
|
||||
import {Cover} from "./entity/Cover";
|
||||
import {Category} from "./entity/Category";
|
||||
import {Chapter} from "./entity/Chapter";
|
||||
|
||||
// first create a connection
|
||||
let options = {
|
||||
host: "192.168.99.100",
|
||||
port: 3306,
|
||||
username: "test",
|
||||
password: "test",
|
||||
database: "test",
|
||||
autoSchemaCreate: true
|
||||
};
|
||||
|
||||
TypeORM.createMysqlConnection(options, [Post, PostDetails, Image, ImageDetails, Cover, Category, Chapter]).then(connection => {
|
||||
|
||||
let postRepository = connection.getRepository<Post>(Post);
|
||||
|
||||
let postCover = new Cover();
|
||||
postCover.url = "http://covers.com/post.jpg";
|
||||
|
||||
let details = new PostDetails();
|
||||
details.meta = "hello";
|
||||
details.comment = "wow";
|
||||
|
||||
let category1 = new Category();
|
||||
category1.description = "about post1";
|
||||
|
||||
let category2 = new Category();
|
||||
category2.description = "about post2";
|
||||
|
||||
let image = new Image();
|
||||
image.name = "post.jpg";
|
||||
|
||||
let post = new Post();
|
||||
post.title = "Hello post";
|
||||
post.text = "Hello world of post#1";
|
||||
post.cover = postCover;
|
||||
post.details = details;
|
||||
post.images.push(image);
|
||||
post.categories = [category1, category2];
|
||||
|
||||
postRepository.persist(post).then(result => {
|
||||
|
||||
/*const qb = postRepository.createQueryBuilder("post")
|
||||
.leftJoinAndSelect("post.details", "details")
|
||||
.leftJoinAndSelect("post.images", "images")
|
||||
// .leftJoinAndSelect("post.coverId", "coverId")
|
||||
.leftJoinAndSelect("post.categories", "categories")
|
||||
.where("post.id=:id")
|
||||
.setParameter("id", 6);
|
||||
|
||||
return qb
|
||||
.getSingleResult()
|
||||
.then(post => {
|
||||
console.log("loaded post: ", post);
|
||||
|
||||
let category1 = new Category();
|
||||
category1.id = 12;
|
||||
category1.description = "about cat#12";
|
||||
|
||||
let category2 = new Category();
|
||||
category2.id = 52;
|
||||
category2.description = "about cat#52";
|
||||
|
||||
let image = new Image();
|
||||
image.name = "second image of the post";
|
||||
|
||||
//post
|
||||
post.title = "This! is updated post$";
|
||||
post.text = "Hello world of post#4";
|
||||
post.categories = [category2, category1];
|
||||
post.images.push(image);
|
||||
return postRepository.persist(post);
|
||||
|
||||
})
|
||||
.then(() => qb.getSingleResult())
|
||||
.then(reloadedPost => console.log("reloadedPost: ", reloadedPost));*/
|
||||
})
|
||||
.then(result => console.log(result))
|
||||
.catch(error => console.log(error.stack ? error.stack : error));
|
||||
|
||||
return;
|
||||
|
||||
const postJson = {
|
||||
id: 1, // changed
|
||||
text: "This is post about hello", // changed
|
||||
title: "hello", // changed
|
||||
details: { // new relation added
|
||||
id: 10, // new object persisted
|
||||
comment: "This is post about hello",
|
||||
meta: "about-hello!",
|
||||
chapter: {
|
||||
id: 1, // new object persisted
|
||||
about: "part I"
|
||||
},
|
||||
categories: [{
|
||||
id: 5, // new object persisted
|
||||
description: "cat5"
|
||||
}]
|
||||
},
|
||||
cover: null, // relation removed
|
||||
images: [{ // new relation added
|
||||
id: 4, // new object persisted
|
||||
name: "post!.jpg",
|
||||
secondaryPost: {
|
||||
id: 2,
|
||||
title: "secondary post"
|
||||
}
|
||||
}, { // secondaryPost relation removed
|
||||
id: 3,
|
||||
name: "post_2!.jpg", // changed
|
||||
details: { // new relation added
|
||||
id: 3, // new object persisted
|
||||
meta: "sec image",
|
||||
comment: "image sec"
|
||||
}
|
||||
}],
|
||||
categories: [{ // two categories removed, new category added
|
||||
id: 4, // new persisted
|
||||
description: "cat2"
|
||||
}]
|
||||
};
|
||||
|
||||
let entity = postRepository.create(postJson);
|
||||
return postRepository.initialize(postJson)
|
||||
.then(result => {
|
||||
const mergedEntity = postRepository.merge(result, entity);
|
||||
console.log("entity created from json: ", entity);
|
||||
console.log("entity initialized from db: ", result);
|
||||
console.log("entity merged: ", mergedEntity);
|
||||
const diff = postRepository.difference(result, mergedEntity);
|
||||
console.log("diff: ", diff);
|
||||
//console.log("diff[0]: ", diff[0].removedRelations);
|
||||
})
|
||||
.catch(error => console.log(error.stack ? error.stack : error));
|
||||
|
||||
let qb = postRepository
|
||||
.createQueryBuilder("post")
|
||||
.addSelect("cover")
|
||||
.addSelect("image")
|
||||
.addSelect("imageDetails")
|
||||
.addSelect("secondaryImage")
|
||||
.addSelect("category")
|
||||
.innerJoin("post.coverId", "cover")
|
||||
.leftJoin("post.images", "image")
|
||||
.leftJoin("post.secondaryImages", "secondaryImage")
|
||||
.leftJoin("image.details", "imageDetails", "on", "imageDetails.meta=:meta")
|
||||
.leftJoin("post.categories", "category", "on", "category.description=:description")
|
||||
//.leftJoin(Image, "image", "on", "image.post=post.id")
|
||||
//.where("post.id=:id")
|
||||
.setParameter("id", 1)
|
||||
.setParameter("description", "cat2")
|
||||
.setParameter("meta", "sec image");
|
||||
|
||||
return qb
|
||||
.getSingleResult()
|
||||
.then(post => console.log(post))
|
||||
// .then(result => console.log(JSON.stringify(result, null, 4)))
|
||||
.catch(error => console.log(error.stack ? error.stack : error));
|
||||
|
||||
/*let details = new PostDetails();
|
||||
details.comment = "This is post about hello";
|
||||
details.meta = "about-hello";
|
||||
|
||||
const post = new Post();
|
||||
post.text = "Hello how are you?";
|
||||
post.title = "hello";
|
||||
//post.details = details;
|
||||
|
||||
postRepository
|
||||
.persist(post)
|
||||
.then(post => console.log("Post has been saved"))
|
||||
.catch(error => console.log("Cannot save. Error: ", error));*/
|
||||
|
||||
}).catch(error => console.log(error.stack ? error.stack : error));
|
||||
@ -4,7 +4,7 @@ import {OneToMany, ManyToMany, ManyToOne} from "../../../src/decorator/Relations
|
||||
import {Post} from "./Post";
|
||||
import {PostDetails} from "./PostDetails";
|
||||
|
||||
@Table("sample2_category")
|
||||
@Table("sample10_category")
|
||||
export class Category {
|
||||
|
||||
@PrimaryColumn("int", { autoIncrement: true })
|
||||
@ -3,7 +3,7 @@ import {Table} from "../../../src/decorator/Tables";
|
||||
import {OneToMany} from "../../../src/decorator/Relations";
|
||||
import {PostDetails} from "./PostDetails";
|
||||
|
||||
@Table("sample2_chapter")
|
||||
@Table("sample10_chapter")
|
||||
export class Chapter {
|
||||
|
||||
@PrimaryColumn("int", { autoIncrement: true })
|
||||
@ -3,7 +3,7 @@ import {Table} from "../../../src/decorator/Tables";
|
||||
import {OneToMany} from "../../../src/decorator/Relations";
|
||||
import {Post} from "./Post";
|
||||
|
||||
@Table("sample2_cover")
|
||||
@Table("sample10_cover")
|
||||
export class Cover {
|
||||
|
||||
@PrimaryColumn("int", { autoIncrement: true })
|
||||
@ -4,7 +4,7 @@ import {ManyToOne, OneToMany, OneToOne} from "../../../src/decorator/Relations";
|
||||
import {Post} from "./Post";
|
||||
import {ImageDetails} from "./ImageDetails";
|
||||
|
||||
@Table("sample2_image")
|
||||
@Table("sample10_image")
|
||||
export class Image {
|
||||
|
||||
@PrimaryColumn("int", { autoIncrement: true })
|
||||
@ -3,7 +3,7 @@ import {Table} from "../../../src/decorator/Tables";
|
||||
import {OneToOne} from "../../../src/decorator/Relations";
|
||||
import {Image} from "./Image";
|
||||
|
||||
@Table("sample2_image_details")
|
||||
@Table("sample10_image_details")
|
||||
export class ImageDetails {
|
||||
|
||||
@PrimaryColumn("int", { autoIncrement: true })
|
||||
61
sample/sample10-mixed/entity/Post.ts
Normal file
61
sample/sample10-mixed/entity/Post.ts
Normal file
@ -0,0 +1,61 @@
|
||||
import {PrimaryColumn, Column} from "../../../src/decorator/Columns";
|
||||
import {Table} from "../../../src/decorator/Tables";
|
||||
import {OneToMany, ManyToOne, ManyToMany, OneToOne} from "../../../src/decorator/Relations";
|
||||
import {Image} from "./Image";
|
||||
import {Cover} from "./Cover";
|
||||
import {Category} from "./Category";
|
||||
import {PostDetails} from "./PostDetails";
|
||||
|
||||
@Table("sample10_post")
|
||||
export class Post {
|
||||
|
||||
@PrimaryColumn("int", { autoIncrement: true })
|
||||
id: number;
|
||||
|
||||
@Column({
|
||||
nullable: false
|
||||
})
|
||||
title: string;
|
||||
|
||||
@Column({
|
||||
nullable: false
|
||||
})
|
||||
text: string;
|
||||
|
||||
@OneToOne<PostDetails>(true, () => PostDetails, details => details.post, {
|
||||
isCascadeInsert: true,
|
||||
isCascadeUpdate: true,
|
||||
isCascadeRemove: true
|
||||
})
|
||||
details: PostDetails;
|
||||
|
||||
@OneToMany<Image>(type => Image, image => image.post, {
|
||||
isCascadeInsert: true,
|
||||
isCascadeUpdate: true,
|
||||
isCascadeRemove: true
|
||||
})
|
||||
images: Image[] = [];
|
||||
|
||||
@OneToMany<Image>(type => Image, image => image.secondaryPost)
|
||||
secondaryImages: Image[];
|
||||
|
||||
@ManyToOne<Cover>(type => Cover, cover => cover.posts, {
|
||||
name: "coverId",
|
||||
isCascadeInsert: true,
|
||||
isCascadeRemove: true
|
||||
})
|
||||
cover: Cover;
|
||||
|
||||
@Column("int", {
|
||||
nullable: true
|
||||
})
|
||||
coverId: number;
|
||||
|
||||
@ManyToMany<Category>(true, type => Category, category => category.posts, {
|
||||
isCascadeInsert: true,
|
||||
isCascadeUpdate: true,
|
||||
isCascadeRemove: true
|
||||
})
|
||||
categories: Category[];
|
||||
|
||||
}
|
||||
35
sample/sample10-mixed/entity/PostDetails.ts
Normal file
35
sample/sample10-mixed/entity/PostDetails.ts
Normal file
@ -0,0 +1,35 @@
|
||||
import {PrimaryColumn, Column} from "../../../src/decorator/Columns";
|
||||
import {Table} from "../../../src/decorator/Tables";
|
||||
import {OneToOne, OneToMany, ManyToOne} from "../../../src/decorator/Relations";
|
||||
import {Post} from "./Post";
|
||||
import {Chapter} from "./Chapter";
|
||||
import {Category} from "./Category";
|
||||
|
||||
@Table("sample10_post_details")
|
||||
export class PostDetails {
|
||||
|
||||
@PrimaryColumn("int", { autoIncrement: true })
|
||||
id: number;
|
||||
|
||||
@Column()
|
||||
meta: string;
|
||||
|
||||
@Column()
|
||||
comment: string;
|
||||
|
||||
@OneToOne<Post>(false, type => Post, post => post.details)
|
||||
post: Post;
|
||||
|
||||
@OneToMany<Category>(type => Category, category => category.details, {
|
||||
isCascadeInsert: true,
|
||||
isCascadeRemove: true
|
||||
})
|
||||
categories: Category[];
|
||||
|
||||
@ManyToOne<Chapter>(_ => Chapter, chapter => chapter.postDetails, {
|
||||
isCascadeInsert: true,
|
||||
isCascadeRemove: true
|
||||
})
|
||||
chapter: Chapter;
|
||||
|
||||
}
|
||||
@ -1,181 +1,35 @@
|
||||
import {TypeORM} from "../../src/TypeORM";
|
||||
import {Post} from "./entity/Post";
|
||||
import {ConnectionOptions} from "../../src/connection/ConnectionOptions";
|
||||
import {PostDetails} from "./entity/PostDetails";
|
||||
import {Image} from "./entity/Image";
|
||||
import {ImageDetails} from "./entity/ImageDetails";
|
||||
import {Cover} from "./entity/Cover";
|
||||
import {Category} from "./entity/Category";
|
||||
import {Chapter} from "./entity/Chapter";
|
||||
|
||||
// first create a connection
|
||||
let options = {
|
||||
let options: ConnectionOptions = {
|
||||
host: "192.168.99.100",
|
||||
port: 3306,
|
||||
username: "test",
|
||||
password: "test",
|
||||
username: "root",
|
||||
password: "admin",
|
||||
database: "test",
|
||||
autoSchemaCreate: true
|
||||
};
|
||||
|
||||
TypeORM.createMysqlConnection(options, [Post, PostDetails, Image, ImageDetails, Cover, Category, Chapter]).then(connection => {
|
||||
TypeORM.createMysqlConnection(options, [Post, PostDetails]).then(connection => {
|
||||
|
||||
let postRepository = connection.getRepository<Post>(Post);
|
||||
|
||||
let postCover = new Cover();
|
||||
postCover.url = "http://covers.com/post.jpg";
|
||||
|
||||
let details = new PostDetails();
|
||||
details.meta = "hello";
|
||||
details.comment = "wow";
|
||||
details.authorName = "Umed";
|
||||
details.comment = "about post";
|
||||
details.metadata = "post,details,one-to-one";
|
||||
|
||||
let category1 = new Category();
|
||||
category1.description = "about post1";
|
||||
|
||||
let category2 = new Category();
|
||||
category2.description = "about post2";
|
||||
|
||||
let image = new Image();
|
||||
image.name = "post.jpg";
|
||||
|
||||
let post = new Post();
|
||||
post.title = "Hello post";
|
||||
post.text = "Hello world of post#1";
|
||||
post.cover = postCover;
|
||||
post.details = details;
|
||||
post.images.push(image);
|
||||
post.categories = [category1, category2];
|
||||
|
||||
postRepository.persist(post).then(result => {
|
||||
|
||||
/*const qb = postRepository.createQueryBuilder("post")
|
||||
.leftJoinAndSelect("post.details", "details")
|
||||
.leftJoinAndSelect("post.images", "images")
|
||||
// .leftJoinAndSelect("post.coverId", "coverId")
|
||||
.leftJoinAndSelect("post.categories", "categories")
|
||||
.where("post.id=:id")
|
||||
.setParameter("id", 6);
|
||||
|
||||
return qb
|
||||
.getSingleResult()
|
||||
.then(post => {
|
||||
console.log("loaded post: ", post);
|
||||
|
||||
let category1 = new Category();
|
||||
category1.id = 12;
|
||||
category1.description = "about cat#12";
|
||||
|
||||
let category2 = new Category();
|
||||
category2.id = 52;
|
||||
category2.description = "about cat#52";
|
||||
|
||||
let image = new Image();
|
||||
image.name = "second image of the post";
|
||||
|
||||
//post
|
||||
post.title = "This! is updated post$";
|
||||
post.text = "Hello world of post#4";
|
||||
post.categories = [category2, category1];
|
||||
post.images.push(image);
|
||||
return postRepository.persist(post);
|
||||
|
||||
})
|
||||
.then(() => qb.getSingleResult())
|
||||
.then(reloadedPost => console.log("reloadedPost: ", reloadedPost));*/
|
||||
})
|
||||
.then(result => console.log(result))
|
||||
.catch(error => console.log(error.stack ? error.stack : error));
|
||||
|
||||
return;
|
||||
|
||||
const postJson = {
|
||||
id: 1, // changed
|
||||
text: "This is post about hello", // changed
|
||||
title: "hello", // changed
|
||||
details: { // new relation added
|
||||
id: 10, // new object persisted
|
||||
comment: "This is post about hello",
|
||||
meta: "about-hello!",
|
||||
chapter: {
|
||||
id: 1, // new object persisted
|
||||
about: "part I"
|
||||
},
|
||||
categories: [{
|
||||
id: 5, // new object persisted
|
||||
description: "cat5"
|
||||
}]
|
||||
},
|
||||
cover: null, // relation removed
|
||||
images: [{ // new relation added
|
||||
id: 4, // new object persisted
|
||||
name: "post!.jpg",
|
||||
secondaryPost: {
|
||||
id: 2,
|
||||
title: "secondary post"
|
||||
}
|
||||
}, { // secondaryPost relation removed
|
||||
id: 3,
|
||||
name: "post_2!.jpg", // changed
|
||||
details: { // new relation added
|
||||
id: 3, // new object persisted
|
||||
meta: "sec image",
|
||||
comment: "image sec"
|
||||
}
|
||||
}],
|
||||
categories: [{ // two categories removed, new category added
|
||||
id: 4, // new persisted
|
||||
description: "cat2"
|
||||
}]
|
||||
};
|
||||
|
||||
let entity = postRepository.create(postJson);
|
||||
return postRepository.initialize(postJson)
|
||||
.then(result => {
|
||||
const mergedEntity = postRepository.merge(result, entity);
|
||||
console.log("entity created from json: ", entity);
|
||||
console.log("entity initialized from db: ", result);
|
||||
console.log("entity merged: ", mergedEntity);
|
||||
const diff = postRepository.difference(result, mergedEntity);
|
||||
console.log("diff: ", diff);
|
||||
//console.log("diff[0]: ", diff[0].removedRelations);
|
||||
})
|
||||
.catch(error => console.log(error.stack ? error.stack : error));
|
||||
|
||||
let qb = postRepository
|
||||
.createQueryBuilder("post")
|
||||
.addSelect("cover")
|
||||
.addSelect("image")
|
||||
.addSelect("imageDetails")
|
||||
.addSelect("secondaryImage")
|
||||
.addSelect("category")
|
||||
.innerJoin("post.coverId", "cover")
|
||||
.leftJoin("post.images", "image")
|
||||
.leftJoin("post.secondaryImages", "secondaryImage")
|
||||
.leftJoin("image.details", "imageDetails", "on", "imageDetails.meta=:meta")
|
||||
.leftJoin("post.categories", "category", "on", "category.description=:description")
|
||||
//.leftJoin(Image, "image", "on", "image.post=post.id")
|
||||
//.where("post.id=:id")
|
||||
.setParameter("id", 1)
|
||||
.setParameter("description", "cat2")
|
||||
.setParameter("meta", "sec image");
|
||||
|
||||
return qb
|
||||
.getSingleResult()
|
||||
.then(post => console.log(post))
|
||||
// .then(result => console.log(JSON.stringify(result, null, 4)))
|
||||
.catch(error => console.log(error.stack ? error.stack : error));
|
||||
|
||||
/*let details = new PostDetails();
|
||||
details.comment = "This is post about hello";
|
||||
details.meta = "about-hello";
|
||||
|
||||
const post = new Post();
|
||||
post.text = "Hello how are you?";
|
||||
post.title = "hello";
|
||||
//post.details = details;
|
||||
post.details = details;
|
||||
|
||||
let postRepository = connection.getRepository<Post>(Post);
|
||||
|
||||
postRepository
|
||||
.persist(post)
|
||||
.then(post => console.log("Post has been saved"))
|
||||
.catch(error => console.log("Cannot save. Error: ", error));*/
|
||||
.catch(error => console.log("Cannot save. Error: ", error));
|
||||
|
||||
}).catch(error => console.log(error.stack ? error.stack : error));
|
||||
}, error => console.log("Cannot connect: ", error));
|
||||
@ -1,10 +1,7 @@
|
||||
import {PrimaryColumn, Column} from "../../../src/decorator/Columns";
|
||||
import {Table} from "../../../src/decorator/Tables";
|
||||
import {OneToMany, ManyToOne, ManyToMany, OneToOne} from "../../../src/decorator/Relations";
|
||||
import {Image} from "./Image";
|
||||
import {Cover} from "./Cover";
|
||||
import {Category} from "./Category";
|
||||
import {PostDetails} from "./PostDetails";
|
||||
import {OneToOne} from "../../../src/decorator/Relations";
|
||||
|
||||
@Table("sample2_post")
|
||||
export class Post {
|
||||
@ -12,14 +9,10 @@ export class Post {
|
||||
@PrimaryColumn("int", { autoIncrement: true })
|
||||
id: number;
|
||||
|
||||
@Column({
|
||||
nullable: false
|
||||
})
|
||||
@Column()
|
||||
title: string;
|
||||
|
||||
@Column({
|
||||
nullable: false
|
||||
})
|
||||
|
||||
@Column()
|
||||
text: string;
|
||||
|
||||
@OneToOne<PostDetails>(true, () => PostDetails, details => details.post, {
|
||||
@ -29,33 +22,4 @@ export class Post {
|
||||
})
|
||||
details: PostDetails;
|
||||
|
||||
@OneToMany<Image>(type => Image, image => image.post, {
|
||||
isCascadeInsert: true,
|
||||
isCascadeUpdate: true,
|
||||
isCascadeRemove: true
|
||||
})
|
||||
images: Image[] = [];
|
||||
|
||||
@OneToMany<Image>(type => Image, image => image.secondaryPost)
|
||||
secondaryImages: Image[];
|
||||
|
||||
@ManyToOne<Cover>(type => Cover, cover => cover.posts, {
|
||||
name: "coverId",
|
||||
isCascadeInsert: true,
|
||||
isCascadeRemove: true
|
||||
})
|
||||
cover: Cover;
|
||||
|
||||
@Column("int", {
|
||||
nullable: true
|
||||
})
|
||||
coverId: number;
|
||||
|
||||
@ManyToMany<Category>(true, type => Category, category => category.posts, {
|
||||
isCascadeInsert: true,
|
||||
isCascadeUpdate: true,
|
||||
isCascadeRemove: true
|
||||
})
|
||||
categories: Category[];
|
||||
|
||||
}
|
||||
@ -1,9 +1,7 @@
|
||||
import {PrimaryColumn, Column} from "../../../src/decorator/Columns";
|
||||
import {Table} from "../../../src/decorator/Tables";
|
||||
import {OneToOne, OneToMany, ManyToOne} from "../../../src/decorator/Relations";
|
||||
import {OneToOne} from "../../../src/decorator/Relations";
|
||||
import {Post} from "./Post";
|
||||
import {Chapter} from "./Chapter";
|
||||
import {Category} from "./Category";
|
||||
|
||||
@Table("sample2_post_details")
|
||||
export class PostDetails {
|
||||
@ -12,24 +10,19 @@ export class PostDetails {
|
||||
id: number;
|
||||
|
||||
@Column()
|
||||
meta: string;
|
||||
authorName: string;
|
||||
|
||||
@Column()
|
||||
comment: string;
|
||||
|
||||
@OneToOne<Post>(false, type => Post, post => post.details)
|
||||
@Column()
|
||||
metadata: string;
|
||||
|
||||
@OneToOne<Post>(true, () => Post, post => post.details, {
|
||||
isCascadeInsert: true,
|
||||
isCascadeUpdate: true,
|
||||
isCascadeRemove: true
|
||||
})
|
||||
post: Post;
|
||||
|
||||
@OneToMany<Category>(type => Category, category => category.details, {
|
||||
isCascadeInsert: true,
|
||||
isCascadeRemove: true
|
||||
})
|
||||
categories: Category[];
|
||||
|
||||
@ManyToOne<Chapter>(_ => Chapter, chapter => chapter.postDetails, {
|
||||
isCascadeInsert: true,
|
||||
isCascadeRemove: true
|
||||
})
|
||||
chapter: Chapter;
|
||||
|
||||
}
|
||||
@ -43,4 +43,9 @@ export interface Driver {
|
||||
*/
|
||||
query<T>(query: string): Promise<T>;
|
||||
|
||||
/**
|
||||
* Clears all tables in the currently connected database.
|
||||
*/
|
||||
clearDatabase(): Promise<void>;
|
||||
|
||||
}
|
||||
@ -92,4 +92,26 @@ export class MysqlDriver implements Driver {
|
||||
return new Promise<any>((ok, fail) => this.connection.query(query, (err: any, result: any) => err ? fail(err) : ok(result)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears all tables in the currently connected database.
|
||||
*/
|
||||
clearDatabase(): Promise<void> {
|
||||
if (!this.connection) throw new Error("Connection is not established, cannot execute a query.");
|
||||
|
||||
// todo: omprize and make coder better
|
||||
|
||||
const query1 = `SET FOREIGN_KEY_CHECKS = 0;`;
|
||||
const query2 = `SELECT concat('DROP TABLE IF EXISTS ', table_name, ';') AS q FROM information_schema.tables WHERE table_schema = '${this.connectionOptions.database}';`;
|
||||
const query3 = `SET FOREIGN_KEY_CHECKS = 1;`;
|
||||
|
||||
return this.query(query1)
|
||||
.then(() => this.query<any[]>(query2))
|
||||
.then(results => {
|
||||
const dropQueries = results.map(q => this.query(q['q']));
|
||||
return Promise.all(dropQueries);
|
||||
})
|
||||
.then(() => this.query(query3))
|
||||
.then(() => {});
|
||||
}
|
||||
|
||||
}
|
||||
@ -245,7 +245,11 @@ export class QueryBuilder<Entity> {
|
||||
}
|
||||
|
||||
getSingleResult(): Promise<Entity> {
|
||||
return this.getResults().then(entities => entities[0]);
|
||||
return this.getResults().then(entities => {
|
||||
console.log(this.getSql());
|
||||
console.log(entities);
|
||||
return entities[0];
|
||||
});
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@ -172,17 +172,11 @@ export class EntityPersistOperationsBuilder {
|
||||
updatesByRelationsOperations
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Private Methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
private updateIdsAfterPersist(insertOperations: InsertOperation[]) {
|
||||
insertOperations.forEach(insertOperation => {
|
||||
const metadata = this.connection.getMetadata(insertOperation.entity.constructor);
|
||||
insertOperation.entity[metadata.primaryColumn.name] = insertOperation.entityId;
|
||||
});
|
||||
}
|
||||
|
||||
private findRelationsWithEntityInside(insertOperation: InsertOperation, entityToSearchIn: any) {
|
||||
const metadata = this.connection.getMetadata(entityToSearchIn.constructor);
|
||||
|
||||
@ -167,6 +167,15 @@ export class Repository<Entity> {
|
||||
return this.update(updateOperation);
|
||||
}));
|
||||
|
||||
}).then(() => { // update ids
|
||||
|
||||
persistOperations.inserts.forEach(insertOperation => {
|
||||
const metadata = this.connection.getMetadata(insertOperation.entity.constructor);
|
||||
insertOperation.entity[metadata.primaryColumn.name] = insertOperation.entityId;
|
||||
});
|
||||
|
||||
return entity;
|
||||
|
||||
});
|
||||
//} else {
|
||||
// do update
|
||||
|
||||
87
test/integration/sample1-simple-entity.ts
Normal file
87
test/integration/sample1-simple-entity.ts
Normal file
@ -0,0 +1,87 @@
|
||||
import * as chai from "chai";
|
||||
import {expect} from "chai";
|
||||
import {Connection} from "../../src/connection/Connection";
|
||||
import {TypeORM} from "../../src/TypeORM";
|
||||
import {ConnectionOptions} from "../../src/connection/ConnectionOptions";
|
||||
import {Repository} from "../../src/repository/Repository";
|
||||
import {SchemaCreator} from "../../src/schema-creator/SchemaCreator";
|
||||
import {Post} from "../../sample/sample1-simple-entity/entity/Post";
|
||||
|
||||
chai.should();
|
||||
describe("insertion", function() {
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Configuration
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
let options: ConnectionOptions = {
|
||||
host: "192.168.99.100",
|
||||
port: 3306,
|
||||
username: "root",
|
||||
password: "admin",
|
||||
database: "test",
|
||||
autoSchemaCreate: true
|
||||
};
|
||||
|
||||
// connect to db
|
||||
let connection: Connection;
|
||||
before(function() {
|
||||
return TypeORM.createMysqlConnection(options, [Post]).then(conn => {
|
||||
connection = conn;
|
||||
}).catch(e => console.log("Error during connection to db: " + e));
|
||||
});
|
||||
|
||||
after(function() {
|
||||
connection.close();
|
||||
});
|
||||
|
||||
// clean up database before each test
|
||||
function reloadDatabase() {
|
||||
return connection.driver
|
||||
.clearDatabase()
|
||||
.then(() => new SchemaCreator(connection).create());
|
||||
}
|
||||
|
||||
let postRepository: Repository<Post>;
|
||||
beforeEach(function() {
|
||||
postRepository = connection.getRepository<Post>(Post);
|
||||
});
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Specifications: persist
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
describe("basic insert functionality", function() {
|
||||
let newPost: Post, savedPost: Post;
|
||||
|
||||
before(reloadDatabase);
|
||||
|
||||
beforeEach(function() {
|
||||
newPost = new Post();
|
||||
newPost.text = "Hello post";
|
||||
newPost.title = "this is post title";
|
||||
return postRepository.persist(newPost).then(post => savedPost = post);
|
||||
});
|
||||
|
||||
it("should return the same post instance after its created", function () {
|
||||
savedPost.should.be.equal(newPost);
|
||||
});
|
||||
|
||||
it("should have a new generated id after post is created", function () {
|
||||
expect(savedPost.id).not.to.be.empty;
|
||||
});
|
||||
|
||||
it("should have inserted post in the database", function() {
|
||||
return postRepository.findById(savedPost.id).should.eventually.eql({
|
||||
id: savedPost.id,
|
||||
text: "Hello post",
|
||||
title: "this is post title"
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
// todo: insert objects with different data types: boolean, dates etc.
|
||||
// todo: tests without? primary column / columns with different options
|
||||
|
||||
});
|
||||
149
test/integration/sample2-one-to-one.ts
Normal file
149
test/integration/sample2-one-to-one.ts
Normal file
@ -0,0 +1,149 @@
|
||||
import * as chai from "chai";
|
||||
import {expect} from "chai";
|
||||
import {Connection} from "../../src/connection/Connection";
|
||||
import {TypeORM} from "../../src/TypeORM";
|
||||
import {ConnectionOptions} from "../../src/connection/ConnectionOptions";
|
||||
import {Repository} from "../../src/repository/Repository";
|
||||
import {SchemaCreator} from "../../src/schema-creator/SchemaCreator";
|
||||
import {PostDetails} from "../../sample/sample2-one-to-one/entity/PostDetails";
|
||||
import {Post} from "../../sample/sample2-one-to-one/entity/Post";
|
||||
|
||||
chai.should();
|
||||
describe("insertion", function() {
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Configuration
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
let options: ConnectionOptions = {
|
||||
host: "192.168.99.100",
|
||||
port: 3306,
|
||||
username: "root",
|
||||
password: "admin",
|
||||
database: "test",
|
||||
autoSchemaCreate: true
|
||||
};
|
||||
|
||||
// connect to db
|
||||
let connection: Connection;
|
||||
before(function() {
|
||||
return TypeORM.createMysqlConnection(options, [Post, PostDetails]).then(conn => {
|
||||
connection = conn;
|
||||
}).catch(e => console.log("Error during connection to db: " + e));
|
||||
});
|
||||
|
||||
after(function() {
|
||||
connection.close();
|
||||
});
|
||||
|
||||
// clean up database before each test
|
||||
function reloadDatabase() {
|
||||
return connection.driver
|
||||
.clearDatabase()
|
||||
.then(() => new SchemaCreator(connection).create());
|
||||
}
|
||||
|
||||
let postRepository: Repository<Post>,
|
||||
postDetailsRepository: Repository<PostDetails>;
|
||||
before(function() {
|
||||
postRepository = connection.getRepository<Post>(Post);
|
||||
postDetailsRepository = connection.getRepository<PostDetails>(PostDetails);
|
||||
});
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Specifications: persist
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
describe("insert post and details", function() {
|
||||
let newPost: Post, details: PostDetails, savedPost: Post;
|
||||
|
||||
before(reloadDatabase);
|
||||
|
||||
beforeEach(function() {
|
||||
details = new PostDetails();
|
||||
details.authorName = "Umed";
|
||||
details.comment = "this is post";
|
||||
details.metadata = "post,posting,postman";
|
||||
|
||||
newPost = new Post();
|
||||
newPost.text = "Hello post";
|
||||
newPost.title = "this is post title";
|
||||
newPost.details = details;
|
||||
return postRepository.persist(newPost).then(post => savedPost = post);
|
||||
});
|
||||
|
||||
it("should return the same post instance after its created", function () {
|
||||
savedPost.should.be.equal(newPost);
|
||||
});
|
||||
|
||||
it("should return the same post details instance after its created", function () {
|
||||
savedPost.details.should.be.equal(newPost.details);
|
||||
});
|
||||
|
||||
it("should have a new generated id after post is created", function () {
|
||||
expect(savedPost.id).not.to.be.empty;
|
||||
expect(savedPost.details.id).not.to.be.empty;
|
||||
});
|
||||
|
||||
it("should have inserted post in the database", function() {
|
||||
return postRepository.findById(savedPost.id).should.eventually.eql({
|
||||
id: savedPost.id,
|
||||
text: "Hello post",
|
||||
title: "this is post title"
|
||||
});
|
||||
});
|
||||
|
||||
it("should have inserted post details in the database", function() {
|
||||
return postDetailsRepository.findById(savedPost.details.id).should.eventually.eql({
|
||||
id: savedPost.details.id,
|
||||
authorName: "Umed",
|
||||
comment: "this is post",
|
||||
metadata: "post,posting,postman"
|
||||
});
|
||||
});
|
||||
|
||||
it("should load post and its details if left join used", function() {
|
||||
return postRepository
|
||||
.createQueryBuilder("post")
|
||||
.leftJoinAndSelect("post.details", "details")
|
||||
.where("post.id=:id")
|
||||
.setParameter("id", savedPost.id)
|
||||
.getSingleResult()
|
||||
.should.eventually.eql({
|
||||
id: savedPost.id,
|
||||
text: "Hello post",
|
||||
title: "this is post title",
|
||||
details: {
|
||||
id: savedPost.details.id,
|
||||
authorName: "Umed",
|
||||
comment: "this is post",
|
||||
metadata: "post,posting,postman"
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it("should load details and its post if left join used (from reverse side)", function() {
|
||||
return postDetailsRepository
|
||||
.createQueryBuilder("details")
|
||||
.leftJoinAndSelect("details.post", "post")
|
||||
.where("details.id=:id")
|
||||
.setParameter("id", savedPost.id)
|
||||
.getSingleResult()
|
||||
.should.eventually.eql({
|
||||
id: savedPost.details.id,
|
||||
authorName: "Umed",
|
||||
comment: "this is post",
|
||||
metadata: "post,posting,postman",
|
||||
post: {
|
||||
id: savedPost.id,
|
||||
text: "Hello post",
|
||||
title: "this is post title",
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
// todo: insert objects with different data types: boolean, dates etc.
|
||||
|
||||
});
|
||||
@ -2,6 +2,7 @@
|
||||
"ambientDevDependencies": {
|
||||
"assertion-error": "github:DefinitelyTyped/DefinitelyTyped/assertion-error/assertion-error.d.ts#7a3ca1f0b8a0960af9fc1838f3234cc9d6ce0645",
|
||||
"chai": "github:DefinitelyTyped/DefinitelyTyped/chai/chai.d.ts#7a3ca1f0b8a0960af9fc1838f3234cc9d6ce0645",
|
||||
"chai-as-promised": "github:DefinitelyTyped/DefinitelyTyped/chai-as-promised/chai-as-promised.d.ts#d6e3f732183ca0ee4c4b438323253b384f5b4091",
|
||||
"mocha": "github:DefinitelyTyped/DefinitelyTyped/mocha/mocha.d.ts#7a3ca1f0b8a0960af9fc1838f3234cc9d6ce0645",
|
||||
"mockery": "github:DefinitelyTyped/DefinitelyTyped/mockery/mockery.d.ts#6f6e5c7dd9effe21fee14eb65fe340ecbbc8580a",
|
||||
"sinon": "github:DefinitelyTyped/DefinitelyTyped/sinon/sinon.d.ts#7a3ca1f0b8a0960af9fc1838f3234cc9d6ce0645"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user