Standalone Java MVC application with JPA and..

Hibernate and c3p0 and Many to Many mapping using Sakila DB to show some information to the user based on selections!

Prerequisities

Make sure you are running MySQL Server in your local with Sakila database loaded..

This is the directory layout I have..

This time lets see the the application in action first, then show the code:
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
                             http://maven.apache.org/xsd/maven-4.0.0.xsd">
 
    <modelVersion>4.0.0</modelVersion>
    <packaging>jar</packaging>
 
    <groupId>biz.tugay</groupId>
    <artifactId>learningjpa</artifactId>
    <version>1.0-SNAPSHOT</version>
 
    <dependencies>
 
        <dependency>
            <groupId>org.eclipse.persistence</groupId>
            <artifactId>javax.persistence</artifactId>
            <version>2.1.1</version>
        </dependency>
 
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>5.1.0.Final</version>
            <scope>runtime</scope>
        </dependency>
 
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>5.1.0.Final</version>
            <scope>runtime</scope>
        </dependency>
 
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-c3p0</artifactId>
            <version>5.1.0.Final</version>
            <scope>runtime</scope>
        </dependency>
 
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.39</version>
            <scope>runtime</scope>
        </dependency>
 
        <dependency>
            <groupId>com.mchange</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.5.2</version>
            <scope>runtime</scope>
        </dependency>
 
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
 
        <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-all</artifactId>
            <version>1.10.19</version>
            <scope>test</scope>
        </dependency>
 
    </dependencies>
 
    <build>
        <plugins>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <version>1.5.0</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>exec</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <executable>mvn</executable>
                    <mainClass>biz.tugay.learningjpa.App</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>
 
    <properties>
        <maven.compiler.source>1.7</maven.compiler.source>
        <maven.compiler.target>1.7</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
</project>

persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
                                 http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"
             version="2.1">
    <persistence-unit name="sakiladb" transaction-type="RESOURCE_LOCAL">
        <properties/>
    </persistence-unit>
</persistence>

hibernate.properties
hibernate.connection.driver_class=com.mysql.jdbc.Driver
hibernate.connection.url=jdbc:mysql://localhost:3306/sakila
hibernate.connection.username=root
hibernate.connection.password=root
hibernate.connection.useUnicode=true
hibernate.connection.characterEncoding=utf-8
hibernate.show_sql=false
hibernate.hbm2ddl.auto=update
 
hibernate.c3p0.min_size=5
hibernate.c3p0.max_size=10
hibernate.c3p0.timeout=300
hibernate.c3p0.max_statements=5
hibernate.c3p0.unreturnedConnectionTimeout=2

PersistenceUtil.java
package biz.tugay.learningjpa.persistence;
 
import javax.persistence.EntityManager;
 
/**
 * User: Koray Tugay (koray@tugay.biz)
 * Date: 10/23/2016
 * Time: 12:49 PM
 */
public interface PersistenceUtil {
    EntityManager getEntityManager();
    void closeFactory();
}

PersistenceUtilImpl.java
package biz.tugay.learningjpa.persistence;
 
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
 
/**
 * User: Koray Tugay (koray@tugay.biz)
 * Date: 10/16/2016
 * Time: 4:06 PM
 */
public class PersistenceUtilImpl implements PersistenceUtil {
 
    private EntityManagerFactory entityManagerFactory;
 
    public PersistenceUtilImpl(final String persistenceUnit) {
        entityManagerFactory = Persistence.createEntityManagerFactory(persistenceUnit);
    }
 
    public EntityManager getEntityManager() {
        final EntityManager entityManager = entityManagerFactory.createEntityManager();
        return entityManager;
    }
 
    public void closeFactory() {
        entityManagerFactory.close();
    }
}

Actor.java
package biz.tugay.learningjpa.model;
 
import javax.persistence.*;
import java.util.List;
 
/**
 * User: Koray Tugay (koray@tugay.biz)
 * Date: 10/23/2016
 * Time: 9:49 AM
 */
 
@Entity
public class Actor {
 
    private Integer id;
    private String firstname;
    private String lastname;
 
    private List<Film> films;
 
    @Id
    @Column(name = "actor_id")
    @GeneratedValue(strategy = GenerationType.AUTO)
    public Integer getId() {
        return id;
    }
 
    public void setId(Integer actor_id) {
        this.id = actor_id;
    }
 
    @Basic
    @Column(name = "first_name")
    public String getFirstname() {
        return firstname;
    }
 
    public void setFirstname(String first_name) {
        this.firstname = first_name;
    }
 
    @Basic
    @Column(name = "last_name")
    public String getLastname() {
        return lastname;
    }
 
    public void setLastname(String last_name) {
        this.lastname = last_name;
    }
 
    @ManyToMany
    @JoinTable(name = "film_actor",
            joinColumns = @JoinColumn(name = "actor_id"),
            inverseJoinColumns = @JoinColumn(name = "film_id")
    )
    public List<Film> getFilms() {
        return films;
    }
 
    public void setFilms(List<Film> films) {
        this.films = films;
    }
}

Film.java
package biz.tugay.learningjpa.model;
 
import javax.persistence.*;
import java.util.List;
 
/**
 * User: Koray Tugay (koray@tugay.biz)
 * Date: 10/23/2016
 * Time: 10:03 AM
 */
 
@Entity
public class Film {
 
    private Integer id;
    private String title;
 
    private List<Actor> actors;
 
    @Id
    @Column(name = "film_id")
    @GeneratedValue(strategy = GenerationType.AUTO)
    public Integer getId() {
        return id;
    }
 
    public void setId(Integer id) {
        this.id = id;
    }
 
    @Basic
    public String getTitle() {
        return title;
    }
 
    public void setTitle(String title) {
        this.title = title;
    }
 
    @ManyToMany
    @JoinTable(name = "film_actor",
            joinColumns = @JoinColumn(name = "film_id"),
            inverseJoinColumns = @JoinColumn(name = "actor_id"))
    public List<Actor> getActors() {
        return actors;
    }
 
    public void setActors(List<Actor> actors) {
        this.actors = actors;
    }
}

ActorService.java
package biz.tugay.learningjpa.service;
 
import biz.tugay.learningjpa.model.Actor;
import biz.tugay.learningjpa.model.Film;
 
import java.util.List;
 
/**
 * User: Koray Tugay (koray@tugay.biz)
 * Date: 10/23/2016
 * Time: 1:40 PM
 */
public interface ActorService {
    List<Actor> allActors();
    List<Actor> actorsLimitBy(int limit);
    Actor getActorById(int actorId);
    List<Actor> getActorsOfFilm(Film film);
}

ActorServiceImpl.java
package biz.tugay.learningjpa.service.impl;
 
import biz.tugay.learningjpa.model.Actor;
import biz.tugay.learningjpa.model.Film;
import biz.tugay.learningjpa.persistence.PersistenceUtil;
import biz.tugay.learningjpa.service.ActorService;
 
import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;
import java.util.ArrayList;
import java.util.List;
 
/**
 * User: Koray Tugay (koray@tugay.biz)
 * Date: 10/23/2016
 * Time: 12:03 PM
 */
public final class ActorServiceImpl implements ActorService {
 
    private final PersistenceUtil persistenceUtil;
 
    public ActorServiceImpl(PersistenceUtil persistenceUtil) {
        this.persistenceUtil = persistenceUtil;
    }
 
    @Override
    public List<Actor> allActors() {
        final EntityManager entityManager = persistenceUtil.getEntityManager();
        final TypedQuery<Actor> query = entityManager.createQuery("SELECT a FROM Actor a", Actor.class);
        final List<Actor> allActors = query.getResultList();
        entityManager.close();
        return allActors;
    }
 
    @Override
    public List<Actor> actorsLimitBy(int limit) {
        final EntityManager entityManager = persistenceUtil.getEntityManager();
        final TypedQuery<Actor> query = entityManager.createQuery("SELECT a FROM Actor a", Actor.class);
        query.setMaxResults(limit);
        final List<Actor> actorsLimitBy = query.getResultList();
        entityManager.close();
        return actorsLimitBy;
    }
 
    @Override
    public Actor getActorById(int actorId) {
        final EntityManager entityManager = persistenceUtil.getEntityManager();
        final Actor actor = entityManager.find(Actor.class, actorId);
        entityManager.close();
        return actor;
    }
 
    @Override
    public List<Actor> getActorsOfFilm(Film film) {
        final EntityManager entityManager = persistenceUtil.getEntityManager();
        final Film persistFilm = entityManager.find(Film.class, film.getId());
        // Load lazy fetched Actors of the film..
        final ArrayList<Actor> actors = new ArrayList<Actor>();
        actors.addAll(persistFilm.getActors());
        entityManager.close();
        return actors;
    }
}

FilmService.java
package biz.tugay.learningjpa.service;
 
import biz.tugay.learningjpa.model.Actor;
import biz.tugay.learningjpa.model.Film;
 
import java.util.List;
 
/**
 * User: Koray Tugay (koray@tugay.biz)
 * Date: 10/23/2016
 * Time: 1:40 PM
 */
public interface FilmService {
    List<Film> allFilms();
    Film filmById(int filmId);
    List<Film> filmsOfActor(Actor actor);
}

FilmServiceImpl.java
package biz.tugay.learningjpa.service.impl;
 
import biz.tugay.learningjpa.model.Actor;
import biz.tugay.learningjpa.model.Film;
import biz.tugay.learningjpa.persistence.PersistenceUtil;
import biz.tugay.learningjpa.service.FilmService;
 
import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;
import java.util.ArrayList;
import java.util.List;
 
/**
 * User: Koray Tugay (koray@tugay.biz)
 * Date: 10/23/2016
 * Time: 12:40 PM
 */
public final class FilmServiceImpl implements FilmService {
 
    private final PersistenceUtil persistenceUtil;
 
    public FilmServiceImpl(final PersistenceUtil persistenceUtil) {
        this.persistenceUtil = persistenceUtil;
    }
 
    @Override
    public List<Film> allFilms() {
        final EntityManager entityManager = persistenceUtil.getEntityManager();
        final TypedQuery<Film> query = entityManager.createQuery("SELECT f FROM Film f", Film.class);
        final List<Film> allFilms = query.getResultList();
        entityManager.close();
        return allFilms;
    }
 
    @Override
    public Film filmById(int filmId) {
        final EntityManager entityManager = persistenceUtil.getEntityManager();
        final Film film = entityManager.find(Film.class, filmId);
        entityManager.close();
        return film;
    }
 
    @Override
    public List<Film> filmsOfActor(Actor actor) {
        final EntityManager entityManager = persistenceUtil.getEntityManager();
        final Actor persistentActor = entityManager.find(Actor.class, actor.getId());
        final ArrayList<Film> films = new ArrayList<Film>();
        films.addAll(persistentActor.getFilms());
        entityManager.close();
        return films;
    }
}

ActorView.java
package biz.tugay.learningjpa.view;
 
import biz.tugay.learningjpa.model.Actor;
 
import java.util.List;
 
/**
 * User: Koray Tugay (koray@tugay.biz)
 * Date: 10/23/2016
 * Time: 2:17 PM
 */
public interface ActorView {
    void printActors(final List<Actor> actors);
    int askForActorId();
}

ActorViewImpl.java
package biz.tugay.learningjpa.view.impl;
 
import biz.tugay.learningjpa.model.Actor;
import biz.tugay.learningjpa.view.ActorView;
 
import java.util.List;
import java.util.Scanner;
 
/**
 * User: Koray Tugay (koray@tugay.biz)
 * Date: 10/23/2016
 * Time: 12:11 PM
 */
public class ActorViewImpl implements ActorView {
 
    @Override
    public void printActors(final List<Actor> actors) {
        System.out.println("");
        System.out.println("");
        System.out.println("== Printing Actors ==");
        System.out.println("ID\tFirstname\tLastname");
        for (Actor actor : actors) {
            System.out.println(actor.getId() + "\t" + actor.getFirstname() + "\t" + actor.getLastname());
        }
    }
 
    @Override
    public int askForActorId() {
        System.out.println("");
        System.out.println("");
        System.out.println("Please enter Actor ID:");
        final Scanner scanner = new Scanner(System.in);
        int actorId = scanner.nextInt();
        return actorId;
    }
}

FilmView.java
package biz.tugay.learningjpa.view;
 
import biz.tugay.learningjpa.model.Film;
 
import java.util.List;
 
/**
 * User: Koray Tugay (koray@tugay.biz)
 * Date: 10/23/2016
 * Time: 2:19 PM
 */
public interface FilmView {
    void printFilms(List<Film> films);
    int askForFilmId();
}

FilmViewImpl.java
package biz.tugay.learningjpa.view.impl;
 
import biz.tugay.learningjpa.model.Film;
import biz.tugay.learningjpa.view.FilmView;
 
import java.util.List;
import java.util.Scanner;
 
/**
 * User: Koray Tugay (koray@tugay.biz)
 * Date: 10/23/2016
 * Time: 12:41 PM
 */
public class FilmViewImpl implements FilmView {
 
    @Override
    public void printFilms(List<Film> films) {
        System.out.println("");
        System.out.println("");
        System.out.println("== Printing Films ==");
        System.out.println("==ID==\t\t==Title==");
        for (Film film : films) {
            System.out.println(film.getId() + "\t\t" + film.getTitle());
        }
        System.out.println("");
        System.out.println("");
    }
 
    @Override
    public int askForFilmId() {
        System.out.println("");
        System.out.println("");
        System.out.println("Please Enter Film ID:");
        final Scanner scanner = new Scanner(System.in);
        final int filmId = scanner.nextInt();
        return filmId;
    }
}

ActorMenu.java
package biz.tugay.learningjpa.controller;
 
import biz.tugay.learningjpa.model.Actor;
import biz.tugay.learningjpa.model.Film;
import biz.tugay.learningjpa.service.ActorService;
import biz.tugay.learningjpa.view.ActorView;
 
import java.util.List;
 
/**
 * User: Koray Tugay (koray@tugay.biz)
 * Date: 10/23/2016
 * Time: 2:44 PM
 */
public class ActorMenu {
 
    private final ActorView actorView;
    private final ActorService actorService;
 
    public ActorMenu(ActorView actorView, ActorService actorService) {
        this.actorView = actorView;
        this.actorService = actorService;
    }
 
    public void listAllActors() {
        final List<Actor> actors = actorService.allActors();
        actorView.printActors(actors);
    }
 
    public Actor askForActorId() {
        int actorId = actorView.askForActorId();
        final Actor actor = actorService.getActorById(actorId);
        return actor;
    }
 
    public void printActorsOfFilm(Film film) {
        final List<Actor> actors = actorService.getActorsOfFilm(film);
        actorView.printActors(actors);
    }
}

FilmMenu.java
package biz.tugay.learningjpa.controller;
 
import biz.tugay.learningjpa.model.Actor;
import biz.tugay.learningjpa.model.Film;
import biz.tugay.learningjpa.service.FilmService;
import biz.tugay.learningjpa.view.FilmView;
 
import java.util.List;
 
/**
 * User: Koray Tugay (koray@tugay.biz)
 * Date: 10/23/2016
 * Time: 2:51 PM
 */
public class FilmMenu {
 
    private final FilmService filmService;
    private final FilmView filmView;
 
    public FilmMenu(FilmService filmService, FilmView filmView) {
        this.filmService = filmService;
        this.filmView = filmView;
    }
 
    public void printsFilmsOfActor(Actor actor) {
        final List<Film> films = filmService.filmsOfActor(actor);
        filmView.printFilms(films);
    }
 
    public void listAllFilms() {
        final List<Film> films = filmService.allFilms();
        filmView.printFilms(films);
    }
 
    public Film askForFilmById() {
        final int filmId = filmView.askForFilmId();
        final Film film = filmService.filmById(filmId);
        return film;
    }
}

MainMenu.java
package biz.tugay.learningjpa.controller;
 
import biz.tugay.learningjpa.model.Actor;
import biz.tugay.learningjpa.model.Film;
 
import java.io.IOException;
import java.util.Scanner;
 
/**
 * User: Koray Tugay (koray@tugay.biz)
 * Date: 10/23/2016
 * Time: 2:26 PM
 */
public class MainMenu {
 
    private final ActorMenu actorMenu;
    private final FilmMenu filmMenu;
 
    public MainMenu(ActorMenu actorMenu, FilmMenu filmMenu) {
        this.actorMenu = actorMenu;
        this.filmMenu = filmMenu;
    }
 
    public void showMainMenu() throws IOException, InterruptedException {
        // Clear console..
        new ProcessBuilder("cmd", "/c", "cls").inheritIO().start().waitFor();
 
        greetUser();
        final int userInput = getUserInput();
        if (userInput == -1) {
            System.exit(-1);
        } else {
            processUserInput(userInput);
            showMainMenu();
        }
    }
 
    private void greetUser() {
        System.out.println("Please select:");
        System.out.println("1 - Find Films by Actor");
        System.out.println("2 - Find Actors of a Film");
        System.out.println("Type -1 to Quit program..");
    }
 
    private int getUserInput() {
        final Scanner scanner = new Scanner(System.in);
        final int userSelection = scanner.nextInt();
        return userSelection;
    }
 
    private void processUserInput(int userInput) {
        switch (userInput) {
            case 1:
                actorMenu.listAllActors();
                final Actor actor = actorMenu.askForActorId();
                filmMenu.printsFilmsOfActor(actor);
                break;
            case 2:
                filmMenu.listAllFilms();
                final Film film = filmMenu.askForFilmById();
                actorMenu.printActorsOfFilm(film);
                break;
        }
        pressAnyKeyToContinue();
    }
 
    void pressAnyKeyToContinue() {
        System.out.println("Press any key to continue..");
        try {
            //noinspection ResultOfMethodCallIgnored
            System.in.read();
        } catch (IOException ignored) {
        }
    }
}

App.java
package biz.tugay.learningjpa;
 
import biz.tugay.learningjpa.controller.ActorMenu;
import biz.tugay.learningjpa.controller.FilmMenu;
import biz.tugay.learningjpa.controller.MainMenu;
import biz.tugay.learningjpa.persistence.PersistenceUtilImpl;
import biz.tugay.learningjpa.service.ActorService;
import biz.tugay.learningjpa.service.impl.ActorServiceImpl;
import biz.tugay.learningjpa.service.FilmService;
import biz.tugay.learningjpa.service.impl.FilmServiceImpl;
import biz.tugay.learningjpa.view.ActorView;
import biz.tugay.learningjpa.view.impl.ActorViewImpl;
import biz.tugay.learningjpa.view.FilmView;
import biz.tugay.learningjpa.view.impl.FilmViewImpl;
 
import java.io.IOException;
 
/**
 * User: Koray Tugay (koray@tugay.biz)
 * Date: 10/23/2016
 * Time: 12:12 PM
 */
public class App {
 
    public static void main(String[] args) throws IOException, InterruptedException {
        final PersistenceUtilImpl persistenceUtil = new PersistenceUtilImpl("sakiladb");
        final ActorService actorService = new ActorServiceImpl(persistenceUtil);
        final FilmService filmService = new FilmServiceImpl(persistenceUtil);
        final ActorView actorView = new ActorViewImpl();
        final FilmView filmView = new FilmViewImpl();
        final ActorMenu actorMenu = new ActorMenu(actorView, actorService);
        final FilmMenu filmMenu = new FilmMenu(filmService, filmView);
        final MainMenu mainMenu = new MainMenu(actorMenu, filmMenu);
        mainMenu.showMainMenu();
    }
}

Do you think this is a proper MVC implementation? Any comments? Please do contact me if you have any! Thank you!