Hibarnate org.hibernate.MappingException:无法确定类型SimpleStringProperty

时间:2017-04-09 15:37:43

标签: java database hibernate javafx

这个问题已被多次询问,但没有一个答案似乎对我有帮助,所以我会再次尝试再问一遍并希望运气:

我的课程得分

    @Entity(name="SokoTable")
    public class Score implements Serializable{

    @Column(name="ID")
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private private SimpleIntegerProperty id;

    @Column(name="Username")
    private SimpleStringProperty userName;
    @Column(name="Level")
    private SimpleStringProperty levelName;
    @Column(name="Steps")
    private SimpleIntegerProperty steps;
    @Column(name="Time")
    private SimpleIntegerProperty time;
    public Score(){ 
    }
    public Score(String userName, String levelName, int steps, int time) {
        super();
        this.userName = new SimpleStringProperty(userName);
        this.levelName = new SimpleStringProperty(levelName);
        this.steps = new SimpleIntegerProperty(steps);
        this.time = new SimpleIntegerProperty(time);
    }
    public int getId() {
        return id.get();
    }

    public void setId(int id) {
        this.id.set(id);
    }

    public String getUserName() {
        return userName.get();
    }
    public void setUserName(String userName) {
        this.userName.set(userName);
    }
    public String getLevelName() {
        return levelName.get();
    }
    public void setLevelName(String levelName) {
        this.levelName.set(levelName);
    }
    public int getSteps() {
        return steps.get();
    }
    public void setSteps(int steps) {
        this.steps.set(steps);
    }
    public int getTime() {
        return time.get();
    }
    public void setTime(int time) {
        this.time.set(time);
    }   
    }

将管理数据库的 SokoDBManager

public class SokoDBManager {

    private static SessionFactory factory;
    private static SokoDBManager instance=new SokoDBManager() ;
    public static SokoDBManager getInstance() {
        return instance;
    }

    private SokoDBManager() {
        Configuration configuration = new Configuration();
        configuration.configure();
        factory = configuration.buildSessionFactory();
        }

    private static void searchScoresWhoseNameStartsWith(String prefix) {
        Session session = factory.openSession();
        Query query = session.createQuery("from SokoTable where Username LIKE :prefix");
        query.setParameter("prefix", prefix + "%");

        List<Score> list = query.list();
        for (Score e : list) {
            System.out.println(e.getUserName());
        }
        session.close();
    }


    public void addScore(Score score){
        Session session = null;
        Transaction tx = null;

        try {
            session = factory.openSession();
            tx = session.beginTransaction();

            session.save(score);
            tx.commit();            
        }
        catch (HibernateException ex) {
            if (tx != null)
                tx.rollback();
            System.out.println(ex.getMessage());
        }
        finally {
            if (session != null)
                session.close();
        }       

    }
    // Method to print all Scores
    public static ObservableList<Score> getScoreList(String Levelname) {
        Session session = factory.openSession();
        ObservableList<Score> list=null;

        try {       
            Query query = session.createQuery("from SokoDB.Score where Level =:Levelname Order by Steps");      
            query.setParameter("Levelname",Levelname);      
            list = FXCollections.observableArrayList(query.list());
            System.out.println(list.getClass());
            for (Score e : list) {
                System.out.println(e.getUserName());
            }
        } catch (HibernateException e) {
            e.printStackTrace();
        } finally { 
            session.close();            
        }
        return list;

    }


    public void close() {
        factory.close();
    }
}

例如,如果我尝试运行此代码:

ObservableList<Score> data=SokoDBManager.getScoreList("Level 1");
        for(Score e :data)
            System.out.println(e.getTime());

我会收到此错误:

Caused by: java.lang.ExceptionInInitializerError
    at view.SokobanViewer.openFile(SokobanViewer.java:64)
    ... 53 more
Caused by: org.hibernate.MappingException: Could not determine type for: javafx.beans.property.SimpleStringProperty, at table: SokoTable, for columns: [org.hibernate.mapping.Column(Level)]
    at org.hibernate.mapping.SimpleValue.getType(SimpleValue.java:455)
    at org.hibernate.mapping.SimpleValue.isValid(SimpleValue.java:422)
    at org.hibernate.mapping.Property.isValid(Property.java:226)
    at org.hibernate.mapping.PersistentClass.validate(PersistentClass.java:597)
    at org.hibernate.mapping.RootClass.validate(RootClass.java:265)
    at org.hibernate.boot.internal.MetadataImpl.validate(MetadataImpl.java:329)
    at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:444)
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:710)
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:726)
    at SokoDB.SokoDBManager.<init>(SokoDBManager.java:29)
    at SokoDB.SokoDBManager.<clinit>(SokoDBManager.java:21)
    ... 54 more

它与SimpleStringProperty有关吗? 可能是这个错误的原因,我该如何解决? 感谢

1 个答案:

答案 0 :(得分:1)

You want Hibernate to "see" the properties as having the underlying types String and int, not the types used for implementing observability by JavaFX (StringProperty and IntegerProperty).

If you place the Column annotation on the fields, Hibernate will use an AccessType of FIELD, i.e. it will match the type based on the type of the field. To use an AccessType of PROPERTY, in which Hibernate looks at the get/set methods, not the fields, annotate the get methods instead. You can also explicitly specify the access type with the Access annotation.

Also, as an aside, note that you have a bug in the implementation of your entity. If you call the default constructor, and then a set method (which is exactly what Hibernate will do), you get a null pointer exception as you never instantiate the property instances. It's best to make these final and instantiate them inline.

@Entity(name="SokoTable")

// the next line is optional if you annotate the get methods (as done below):
@Access("AccessType.PROPERTY")

public class Score implements Serializable{

    private final IntegerProperty id = new SimpleIntegerProperty() ; 

    private final StringProperty userName = new SimpleStringProperty() ;
    private final StringProperty levelName = new SimpleStringProperty() ;
    private final IntegerProperty steps = new SimpleIntegerProperty() ;
    private final IntegerProperty time = new SimpleIntegerProperty() ;

    public Score(){ 
    }
    public Score(String userName, String levelName, int steps, int time) {
        super();
        setUserName(userName);
        setLevelName(levelName);
        setSteps(steps);
        setTime(time);
    }

    @Column(name="ID")
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    public int getId() {
        return id.get();
    }

    public void setId(int id) {
        this.id.set(id);
    }

    @Column(name="Username")
    public String getUserName() {
        return userName.get();
    }
    public void setUserName(String userName) {
        this.userName.set(userName);
    }
    @Column(name="Level")
    public String getLevelName() {
        return levelName.get();
    }
    public void setLevelName(String levelName) {
        this.levelName.set(levelName);
    }
    @Column(name="Steps")
    public int getSteps() {
        return steps.get();
    }
    public void setSteps(int steps) {
        this.steps.set(steps);
    }
    @Column(name="Time")
    public int getTime() {
        return time.get();
    }
    public void setTime(int time) {
        this.time.set(time);
    }   
}

Have a look at this blog post for more details.