Object Relational Mapping - part 2

Learning Objectives

Pre-requisites

Lesson

There is an important dimension missing from our 'home grown' ORM implementation - relationships. As we see from the class diagram below, our Restaurants have Menus and our Menus have Menu Items.

UML Class Diagram showing relationships between Restaurant, Menu and MenuItem classes

We want to be able to access our Menus like this:

restaurant.menus 
restaurant.getMenus();

and from each Menu we want to be able to access information about each item on the Menu, for example:

restaurant.menus[0].title 
restaurant.getMenus().get(0).getTitle()

We therefore need to expand our Restaurant class to include a function that will add a Menu instance to the Restaurant:

addMenu(menu) {
    this.menus.push(menu);
}
public void addMenu(Menu menu) {
    this.menus.add(menu);
}

We can then extend our save() method to save Restaurant Menus.

    save() {

        const self = this;

        try {
            return new Promise(function (resolve) {
                Restaurant.db.run(`INSERT INTO RESTAURANTS (name, image) VALUES (?, ?)`, [self.name, self.image], function (err) {
                    if (err) {
                        console.log(err.message);
                        throw err;
                    }
                    self.id = this.lastID; // set the object id to the inserted row id

                    if (self.menus) {
                        self.menus.forEach(async (menu) => {
                            // save each menu
                            await menu.save(self.id);
                        })

                    }

                    resolve(self);
                })
            });
        } catch (err) {
            console.log(err)
        }
    }
    public Restaurant save() {

        // using withHandle will auto close the db connection
        Long id = jdbi.withHandle(handle -> {

            return handle.createUpdate("INSERT INTO RESTAURANTS (name, imagelink) VALUES (?, ?)")
                    .bind(this.name, this.imageLink)
                    .executeAndReturnGeneratedKeys("id")
                    .mapTo(Long.class).findOnly();
        });

        for(Menu menu:menus) {
            menu.save(id);
        }

        this.id = id;

        return this;
    }

Assignment

Assignment extension tasks

Additional resources