简体   繁体   English

如何修复休眠的hbm.xml文件以使复合主键正常工作? (MappingException)

[英]How do I fix my hibernate hbm.xml file to make my composite primary keys work? (MappingException)

GitHub Example demonstrating problem GitHub示例演示问题

https://github.com/jl431/Example.git https://github.com/jl431/Example.git

All my code required to reproduce error is here. 重现错误所需的所有代码都在这里。

Would also need to start mysql server and change connection details in hibernate file. 还需要启动mysql服务器并更改休眠文件中的连接详细信息。

Error 错误

Initial SessionFactory creation failed.org.hibernate.MappingException: Could not determine type for: beans.User, at table: RATINGS, for columns: [org.hibernate.mapping.Column(USER_ID)]
Exception in thread "main" java.lang.ExceptionInInitializerError
    at simple.HibernateUtil.buildSessionFactory(HibernateUtil.java:26)
    at simple.HibernateUtil.<clinit>(HibernateUtil.java:10)
    at simple.MovieManager.<init>(MovieManager.java:9)
    at simple.MovieManager.main(MovieManager.java:13)
Caused by: org.hibernate.MappingException: Could not determine type for: beans.User, at table: RATINGS, for columns: [org.hibernate.mapping.Column(USER_ID)]
    at org.hibernate.mapping.SimpleValue.getType(SimpleValue.java:336)
    at org.hibernate.tuple.PropertyFactory.buildStandardProperty(PropertyFactory.java:353)
    at org.hibernate.tuple.component.ComponentMetamodel.<init>(ComponentMetamodel.java:71)
    at org.hibernate.mapping.Component.getType(Component.java:180)
    at org.hibernate.mapping.SimpleValue.isValid(SimpleValue.java:310)
    at org.hibernate.mapping.RootClass.validate(RootClass.java:271)
    at org.hibernate.cfg.Configuration.validate(Configuration.java:1360)
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1851)
    at simple.HibernateUtil.buildSessionFactory(HibernateUtil.java:19)
    ... 3 more

Here are a few key files where I assume the problem lays. 这是我认为存在问题的一些关键文件。 Remaining code is available from the github repo url above. 其余代码可从上面的github repo url获得。

hibernate.cfg.xml hibernate.cfg.xml

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
    <session-factory>

        <!-- Database connection settings -->
        <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="connection.url">jdbc:mysql://localhost:3306/testingbeta</property>
        <property name="connection.username">root</property>
        <property name="connection.password"></property>


        <!-- JDBC connection pool (use the built-in) -->
        <property name="connection.pool_size">1</property>

        <!-- SQL dialect -->
        <property name="dialect">org.hibernate.dialect.MySQLDialect</property>

        <!-- Enable Hibernate's automatic session context management -->
        <property name="current_session_context_class">thread</property>

        <!-- Disable the second-level cache  -->
        <property name="cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</property>

        <!-- Echo all executed SQL to stdout -->
        <property name="show_sql">true</property>

        <!-- Drop and re-create the database schema on startup -->
        <property name="hbm2ddl.auto">create</property>

        <mapping resource="Movie.hbm.xml"/>
        <mapping resource="User.hbm.xml"/>
        <mapping resource="Rating.hbm.xml"/>

    </session-factory>
</hibernate-configuration>

Rating.hbm.xml Rating.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="beans">
    <class name="Rating" table="RATINGS">
        <composite-id name="RatingId" class="RatingId">
            <key-property name="user" column="USER_ID" />
            <key-property name="movie" column="MOVIE_ID" />
        </composite-id>

        <property name="rating" />
    </class>
</hibernate-mapping>

Rating.java Rating.java

package beans;

import java.util.Date;

public class Rating {
    private RatingId ratingId;
    private int rating;
    private Date timestamp;

    public Rating() {}  // No arg contructor for hibernate

    public Rating(RatingId ratingId, int rating) {
        super();
        this.ratingId = ratingId;
        this.rating = rating;
    }

    public RatingId getRatingId() {
        return ratingId;
    }

    public void setRatingId(RatingId ratingId) {
        this.ratingId = ratingId;
    }

    public int getRating() {
        return rating;
    }

    public void setRating(int rating) {
        this.rating = rating;
    }
}

RatingId.java RatingId.java

package beans;

import java.io.Serializable;

public class RatingId implements Serializable {
    private User user;
    private Movie movie;

    public RatingId(User user, Movie movie) {
        this.user = user;
        this.movie = movie;
    }

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    public Movie getMovie() {
        return movie;
    }

    public void setMovie(Movie movie) {
        this.movie = movie;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((movie == null) ? 0 : movie.hashCode());
        result = prime * result + ((user == null) ? 0 : user.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        RatingId other = (RatingId) obj;
        if (movie == null) {
            if (other.movie != null)
                return false;
        } else if (!movie.equals(other.movie))
            return false;
        if (user == null) {
            if (other.user != null)
                return false;
        } else if (!user.equals(other.user))
            return false;
        return true;
    }
}

I doubt if the composite key columns could be in different tables (in our case - USERS and MOVIE tables). 我怀疑组合键列是否可以在不同的表中(在我们的情况下-USERS和MOVIE表)。 As far as I understand they need to be in RATINGS table. 据我了解,它们需要位于RATINGS表中。 I tried mapping them in the same table and was able to persist the rating object successfully. 我尝试将它们映射到同一张表中,并且能够成功保留评级对象。 I am using JPA annotations. 我正在使用JPA批注。 The configuration is quite simpler with annotations. 带注释的配置非常简单。 Below is the code. 下面是代码。

Note - Composite key is defined using @Embeddeble and @EmbeddedId annotations in JPA. 注-组合键是使用JPA中的@Embeddeble@EmbeddedId注释定义的。

@Embeddable
public class User {

    @Column(name = "USER_ID")
    private long userId;
    @Column(name = "EMAIL_ADDRESS")
    private String email;
    public User() {}

    public User(long userId, String email, String password) {
        this.userId = userId;
        this.email = email;
    }
    public long getUserId() {
        return userId;
    }
    public void setUserId(long userId) {
        this.userId = userId;
    }
    public String getEmail() {
        return email;
    }
    public void setEmail(String email) {
        this.email = email;
    }
}

@Embeddable
public class Movie {
    @Column(name = "MOVIE_ID")
    private long movieId;

    @Column(name = "MOVIE_NAME")
    private String title;

    public Movie() {}
    public Movie(long movieId, String title) {
        this.movieId = movieId;
        this.title = title;
    }
    public long getMovieId() {
        return movieId;
    }
    public void setMovieId(long movieId) {
        this.movieId = movieId;
    }
    public String getTitle() {
        return title;
    }
    public void setTitle(String title) {
        this.title = title;
    }
}

@Embeddable
public class RatingId implements Serializable {

    @Embedded
    private User user;  //Embeddable inside Embeddable.
    @Embedded
    private Movie movie;

    public RatingId() {
    }

    public RatingId(User user, Movie movie) {
        this.user = user;
        this.movie = movie;
    }

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    public Movie getMovie() {
        return movie;
    }

    public void setMovie(Movie movie) {
        this.movie = movie;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((movie == null) ? 0 : movie.hashCode());
        result = prime * result + ((user == null) ? 0 : user.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        RatingId other = (RatingId) obj;
        if (movie == null) {
            if (other.movie != null)
                return false;
        } else if (!movie.equals(other.movie))
            return false;
        if (user == null) {
            if (other.user != null)
                return false;
        } else if (!user.equals(other.user))
            return false;
        return true;
    }
}

@Entity
@Table(name = "RATING")
public class Rating {

    @EmbeddedId
    private RatingId ratingId;
    private int rating;
    private Date timestamp;

    public Rating() {}  // No arg contructor for hibernate

    public Rating(RatingId ratingId, int rating) {
        super();
        this.ratingId = ratingId;
        this.rating = rating;
    }

    public RatingId getRatingId() {
        return ratingId;
    }

    public void setRatingId(RatingId ratingId) {
        this.ratingId = ratingId;
    }

    public int getRating() {
        return rating;
    }

    public void setRating(int rating) {
        this.rating = rating;
    }
}

Calling entityManager.persist(rating) persisted the rating object in db. 调用entityManager.persist(rating)将评级对象持久保存在db中。 As a summary there is only one table in database - RATINGS that has all the required attributes - user, movie & rating. 总而言之,数据库中只有一个表-RATINGS具有所有必需的属性-用户,电影和评分。 Is that what you were also visualizing? 那也是你想像的吗?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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