Reputation: 39
I'm currently improving an old project that is working fine, I don't have to modify the code nor the database, all I can do is build the correct mapping for it...
There's the Actor, Role and Movie classes... With 3 respective tables in the database :
Table 'Actor' :
`id` INT
`name` VARCHAR
Table 'Role' :
`film` INT
`actor` INT
`role` VARCHAR
PRIMARY KEY (film, actor, role)
FOREIGN KEY (film) REFERENCES film(id)
Table 'Movie' :
`id` INT
`title` VARCHAR
So there are two associations to be made, [ONE actor has ONE role in ONE movie], and [ONE movie contains MANY roles associated to their respectives actors].
And basically, there should be a method in Movie class that allows to create a new role associated to an actor
film.createRole(actor, "Role"); //returning a role
I'm getting all the time the same error : Java NullPointerException from Hibernate. I guess there's a misconception in my code, any idea how I can do the correct mapping?
Code :
Movie.java :
@Entity
@Table(name = "movie")
public class Movie implements Serializable
{
@Id
@GeneratedValue
private int id;
private String title;
@OneToMany
@JoinTable(name = "role",
joinColumns = {
@JoinColumn(name="role")
}
)
private List<Role> roles;
//Getters and setters
public Role createRole(Actor actor, String role)
{
Role myRole = new Role();
RoleId roleId = new RoleId();
roleId.setMovie(this.id);
roleId.setRole(role);
roleId.setActor(actor.getId());
myRole.setId(roleId);
return myRole;
}
}
Role.java :
@Entity
@Table(name = "role")
public class Role implements Serializable
{
@EmbeddedId
private RoleId roleId;
//Getters and setters
}
RoleId.java :
@Embeddable
public class RoleId implements Serializable
{
@ManyToOne(optional=true)
@JoinTable(name = "role", joinColumns = {
@JoinColumn(name="movie")})
private int movie;
@ManyToOne(optional=true)
@JoinTable(name = "role", joinColumns = {
@JoinColumn(name="actor")
})
private int actor;
private String role;
//Getters and setters
}
Actor.java :
@Entity
@Table(name = "actor")
public class Actor implements Serializable
{
@Id
@GeneratedValue
private int id;
private String name;
@OneToMany
@JoinTable(name = "role", joinColumns = {
@JoinColumn(name="role", unique = true) })
private List<Role> roles;
//Getters and setters
}
Where's the mistake then? Thanks.
Upvotes: 0
Views: 1252
Reputation: 38655
I think You have bad annotation mapping. See how I did it.
RoleId
import java.io.Serializable;
import javax.persistence.Embeddable;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
@Embeddable
public class RoleId implements Serializable {
private static final long serialVersionUID = 1L;
@ManyToOne(optional = false)
@JoinColumn(name = "movie")
private Movie movie;
@ManyToOne(optional = false)
@JoinColumn(name = "actor")
private Actor actor;
private String role;
public Movie getMovie() {
return movie;
}
public void setMovie(Movie movie) {
this.movie = movie;
}
public Actor getActor() {
return actor;
}
public void setActor(Actor actor) {
this.actor = actor;
}
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
@Override
public String toString() {
return "movie=" + movie.getTitle() + ", actor=" + actor.getName()
+ ", role=" + role;
}
}
Role
@Entity
@Table(name = "role")
public class Role implements Serializable {
private static final long serialVersionUID = 1L;
@EmbeddedId
private RoleId id;
public RoleId getId() {
return id;
}
public void setId(RoleId id) {
this.id = id;
}
@Override
public String toString() {
return getId().toString();
}
}
Actor
@Entity
@Table(name = "actor")
public class Actor implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue
@Column(name = "id")
private int id;
private String name;
@OneToMany
@JoinColumn(name = "actor")
private List<Role> roles;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Role> getRoles() {
return roles;
}
public void setRoles(List<Role> roles) {
this.roles = roles;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder(124);
builder.append(name).append(" roles ");
builder.append(Arrays.toString(roles.toArray()));
return builder.toString();
}
}
Movie
@Entity
@Table(name = "movie")
public class Movie implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue
@Column(name = "id")
private int id;
private String title;
@OneToMany
@JoinColumn(name = "movie")
private List<Role> roles;
public Role createRole(Actor actor, String role) {
Role myRole = new Role();
RoleId roleId = new RoleId();
roleId.setMovie(this);
roleId.setRole(role);
roleId.setActor(actor);
myRole.setId(roleId);
return myRole;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public List<Role> getRoles() {
return roles;
}
public void setRoles(List<Role> roles) {
this.roles = roles;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder(124);
builder.append(title).append(" roles ");
builder.append(Arrays.toString(roles.toArray()));
return builder.toString();
}
}
MySQL Tables
CREATE TABLE `actor` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB;
CREATE TABLE `movie` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`title` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB;
CREATE TABLE `role` (
`movie` bigint(20) NOT NULL,
`actor` bigint(20) NOT NULL,
`role` varchar(255) NOT NULL DEFAULT '',
PRIMARY KEY (`movie`,`actor`,`role`),
CONSTRAINT `role_movie_movie` FOREIGN KEY (`movie`) REFERENCES `movie` (`id`),
CONSTRAINT `role_actor_actor` FOREIGN KEY (`actor`) REFERENCES `actor` (`id`)
) ENGINE=InnoDB;
INSERT INTO actor(name) VALUES('Arnold Schwarzenegger');
INSERT INTO actor(name) VALUES('Michael Biehn');
INSERT INTO actor(name) VALUES('Linda Hamilton');
INSERT INTO movie(title) VALUES('Termiantor');
INSERT INTO role VALUES(1, 1, 'Terminator');
INSERT INTO role VALUES(1, 2, 'Kyle Reese');
INSERT INTO role VALUES(1, 3, 'Sara Connor');
After executing below source code:
public static void main(String[] args) {
movieTest();
}
public static void movieTest() {
Session session = HibernateUtil.getSessionFactory().openSession();
showEntities(session, Movie.class, "Movies");
showEntities(session, Actor.class, "Actors");
showEntities(session, Role.class, "Roles");
}
private static void showEntities(Session session, Class<?> entity,
String name) {
System.out.println(name);
for (Object item : session.createCriteria(entity).list()) {
System.out.println(item);
}
}
You will see output like that
Movies
Termiantor roles [movie=Termiantor, actor=Arnold Schwarzenegger, role=Terminator, movie=Termiantor, actor=Michael Biehn, role=Kyle Reese, movie=Termiantor, actor=Linda Hamilton, role=Sara Connor]
Actors
Arnold Schwarzenegger roles [movie=Termiantor, actor=Arnold Schwarzenegger, role=Terminator]
Michael Biehn roles [movie=Termiantor, actor=Michael Biehn, role=Kyle Reese]
Linda Hamilton roles [movie=Termiantor, actor=Linda Hamilton, role=Sara Connor]
Roles
movie=Termiantor, actor=Arnold Schwarzenegger, role=Terminator
movie=Termiantor, actor=Michael Biehn, role=Kyle Reese
movie=Termiantor, actor=Linda Hamilton, role=Sara Connor
Upvotes: 1