简体   繁体   中英

Using entity inside entity with relationships and populating database in Nest JS / TypeORM

Let's say we are constructing our very first entities for a new web application. There is an entity for users :

@Entity()
export class User {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  username: string;

  @Column()
  password: string;

  @OneToOne(() => Author)
  author: Author;

Users can be Authors after registration. So there's a one-to-one relationship between users and authors table. Let's say we have another table called books , an author can have multiple books.

export class Author {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  Name: string;

  @OneToMany(() => Book, (Book) => Book.Author)
  Book: Book[];

  @OneToOne(() => User)
  @JoinColumn()
  User: User;

Here is a sample entity for Books repository:

export class Book {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  Name: string;

  @Column()
  ISIN: string;

  @OneToOne(() => Author)
  @JoinColumn()
  Author: Author;

The question is, when we migrated these entities and built our very first/clean database , how can we insert the data via calling API? A sample service for API Post method:

@Injectable()
export class BookService {
  constructor(
    @InjectRepository(Book)
    private BookRepository: Repository<Book>,
  ) {}
  async create(createBookDto: CreateBookDto) {
    await this.BookRepository.insert(createBookDto);
  }
}

And the Controller:

@Controller('books')
export class BookController {
  constructor(private readonly BookService: BookService) {}

  @Post('/Book')
  create(@Body() createBookDto: CreateBookDto) {
    return this.BookService.create(createBookDto);
  }
}

The problem here is that when I want to create a new book by POSTing data to the API route, it needs the Author to be defined. So how can I post existing user-books-author data into the database via this service?
The best option I think of is to create a new instance of the classes , get the data from request @Body and assign it to the objects of the class then save it to the database.
But I think it's not a good solution, as it's very preferred to use repositories instead of object-class type.

I think you do a mistake in your entity definition. There is OneToMany relation between Author to Book.

Modify your book entity like this

export class Book {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  Name: string;

  @Column()
  ISIN: string;

  @ManyToOne(() => Author, author=> author.book, { nullable: true })
  @JoinColumn()
  Author: Author;

{ nullable: true } this will allow you to save your book data without having an author.

Modify your service to save the book information

public async create(createBookDTO: CreateBookDTO) {
        try {
            if (
                createBookDTO.hasOwnProperty('author') &&
                createTaskDTO.author
            ) {
                const author = await this.connection.manager.findOne(Author, {
                    where: {
                        id: createBookDTO.author,
                    },
                });
                if (author) {
                    createBookDTO.author = author;
                } else {
                    throw new NotAcceptableException('Author not found');
                }
            }

            return await this.bookRepo.save(createBookDTO);
        } catch (err) {
            throw new HttpException(err, err.status || HttpStatus.BAD_REQUEST);
        }
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM