Java JPA类关联,NullPointerException?

时间:2012-10-27 10:22:49

标签: java

我目前正在改进一个工作正常的旧项目,我不必修改代码也不需要修改数据库,我所能做的就是为它构建正确的映射...

有Actor,Role和Movie类......数据库中有3个相应的表:

表'演员':

`id` INT
`name` VARCHAR

表'角色':

`film` INT
`actor` INT
`role` VARCHAR
PRIMARY KEY (film, actor, role)
FOREIGN KEY (film) REFERENCES film(id)

表'电影':

`id` INT
`title` VARCHAR

所以有两个关联,[一个演员在一部电影中扮演一个角色],[一部电影包含与各自演员相关联的多个角色]。

基本上,Movie类中应该有一个方法允许创建一个与actor相关联的新角色

film.createRole(actor, "Role"); //returning a role

我总是得到同样的错误:来自Hibernate的Java NullPointerException。我想我的代码中存在一种误解,不知道我怎么能做正确的映射?

代码:

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

}

那么错误在哪里? 感谢。

1 个答案:

答案 0 :(得分:1)

我认为你的注释映射不好。看看我是怎么做到的。

角色ID

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;
    }
}

作用

@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();
    }
}

演员

@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();
    }
}

电影

@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表

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');

执行以下源代码后:

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);
    }
}

你会看到像那样的输出

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