TransWikia.com

Помогите разобраться с Hibernate exception'ами

Stack Overflow на русском Asked by IngeniousTom on December 19, 2020

Работаю над приложением по обмену вещами между пользователями в Java + Hibernate + Maven.
Написал все необходимые классы и интерфейсы, настроил Hibernate по своему пониманию.
Но приложение не запускается – в потоке логов выдает одно предупреждение следующего вида:
INFO: HHH000206: hibernate.properties not found
После этого программа завершает работу, выкинув исключение:
Initial SessionFactory creation failed.org.hibernate.MappingException: An association from the table disk refers to an unmapped class: User.

Выкладываю структуру проекта и кода, чтобы можно было разобраться:

Схема данных в БД:

введите сюда описание изображения

SQL-код структуры таблиц:

CREATE TABLE IF NOT EXISTS user (
  id INT GENERATED BY DEFAULT AS IDENTITY 
                                        (START WITH 1, INCREMENT BY 1) NOT NULL,
  name varchar(30) NOT NULL,
  lastName varchar(45) NOT NULL,
  patronym varchar(30) NOT NULL,
  birthdate date NOT NULL,
  email varchar(120) NOT NULL,
  password varchar(45) NOT NULL,
  PRIMARY KEY (id)
);  

CREATE TABLE disk (
  id int GENERATED BY DEFAULT AS IDENTITY 
                                         (START WITH 1, INCREMENT BY 1) NOT NULL,
  name varchar(120) NOT NULL,
  idhost int NOT NULL,
  PRIMARY KEY (id),
  CONSTRAINT fk_disk_user FOREIGN KEY (idhost) REFERENCES user (id) ON DELETE NO ACTION ON UPDATE NO ACTION
);

CREATE TABLE IF NOT EXISTS takenitem (
  idDisk int NOT NULL,
  idUser int NOT NULL,
  PRIMARY KEY (idDisk, idUser),
  CONSTRAINT fk_takenitem_disk FOREIGN KEY (idDisk) REFERENCES disk (id) ON DELETE NO ACTION ON UPDATE NO ACTION,
  CONSTRAINT fk_takenitem_user FOREIGN KEY (idUser) REFERENCES user (id) ON DELETE NO ACTION ON UPDATE NO ACTION
);

POJO:

public class User {
    int id;
    String name;
    String lastname;
    String patronym;
    Date birthdate;
    String email;
    String password;

    //Конструкторы...
    //Геттеры и сеттеры...
}

public class Disk {
    int id;
    User host;
    String name;

    //Конструкторы...
    //Геттеры и сеттеры...
}

public class TakenItem {
    Disk disk;
    User user;

    //Конструкторы...
    //Геттеры и сеттеры...
}

HibernateUtil

import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class HibernateUtil {
    private static final SessionFactory sessionFactory;
    static {
        try {
            sessionFactory = new Configuration().configure()
                    .buildSessionFactory();
        } catch (Throwable ex) {
            System.err.println("Initial SessionFactory creation failed." + ex);
            throw new ExceptionInInitializerError(ex);
        }
    }

    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }
}

Файлы маппингов:

User.hbm.xml

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

<hibernate-mapping>
    <class name="com.alikinartyom.User" table="user">
        <id name="id" type="int">
            <column name="id"/>
            <generator class="native"/>
        </id>
        <property name="name" type="string">
            <column name="name" length="30" not-null="true"/>
        </property>
        <property name="lastname" type="string">
            <column name="lastname" length="45" not-null="true"/>
        </property>
        <property name="patronym" type="string">
            <column name="patronym" length="30" not-null="true"/>
        </property>
        <property name="birthdate" type="date">
            <column name="birthdate" not-null="true"/>
        </property>
        <property name="email" type="string">
            <column name="email" length="120" not-null="true"/>
        </property>
        <property name="password" type="string">
            <column name="password" length="45" not-null="true"/>
        </property>
    </class> 
</hibernate-mapping>

Disk.hbm.xml

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

<hibernate-mapping>
    <class name="com.alikinartyom.Disk" table="disk">
        <id name="id" type="int">
            <column name="id"/>
            <generator class="native"/>
        </id>
        <property name="name" type="string">
            <column name="name" length="120" not-null="true"/>
        </property>
        <many-to-one name="host" column="idhost" class="User" cascade="all" not-null="true">
        </many-to-one>
    </class>
</hibernate-mapping>

TakenItem.hbm.xml

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

<hibernate-mapping>
    <class name="com.alikinartyom.TakenItem" table="takenitem">
        <composite-id>
            <key-property name="disk" column="idDisk"/>
            <key-property name="user" column="idUser"/>
        </composite-id>
        <one-to-one name="disk" class="com.alikinartyom.Disk" cascade="all"/>
        <many-to-one name="user" column="idUser" class="com.alikinartyom.User" cascade="all"/>
    </class>
</hibernate-mapping>

hibernate.cfg.xml

<hibernate-configuration>
    <session-factory>
        <!-- Database connection settings -->
        <property name="hibernate.connection.driver_class">org.hsqldb.jdbcDriver</property>
        <property name="hibernate.connection.url">jdbc:hsqldb:mem:testdb</property>
        <property name="hibernate.connection.username">SA</property>
        <property name="hibernate.connection.password"></property>

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

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

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

        <!-- Mapping files -->
        <mapping resource="TakenItem.hbm.xml"/>
        <mapping resource="Disk.hbm.xml"/>
        <mapping resource="User.hbm.xml"/>
    </session-factory>
</hibernate-configuration>

Вызов:

public class Main {
    public static void main(String[] args) {
        UserDAO userDAO = new UserDAOHibernateImpl();

        System.out.println("Application started:");
        System.out.println("getting all user in table "users":");
        List<User> userList = userDAO.getAllUsers();
        for (User user : userList) {
            System.out.println(user);
        }
    }
}

Ошибка вылетает при создании фабрики в методе userDAO.getAllUsers();

public List<User> getAllUsers() {
        Session session = HibernateUtil.getSessionFactory().openSession();
        List<User> allUsers = null;
        Transaction tx = null;
        try{
            tx = session.beginTransaction();
            Query query = session.createSQLQuery("SELECT * from user");
            allUsers = query.list();
            tx.commit();
        }catch (HibernateException e) {
            if (tx!=null) tx.rollback();
            e.printStackTrace();
        }finally {
            session.close();
        }
        return allUsers;
    }

Вопросы:

1) Почему не работает программа и как это можно исправить?
Обратите внимание, что таблица takenitem является связующей и в ней всего 2 поля, каждое из которых является внешним ключом из своей внешней таблицы. К тому же оба ключа еще вместе образуют составной первичный ключ в текущей таблице.
Правильно ли я описал связи? Если нет – напишите как правильно. Это касается и других фалов маппинга.

2) Если не трудно, то объясните про назначение атрибутов cascade (и его значений), constrained, foreing key в маппинге связей.

One Answer

Я сделал как вы сказали - появилась новая ошибка:

Initial SessionFactory creation failed.org.hibernate.MappingException: Repeated column in mapping for entity: com.alikinartyom.TakenItem column: idUser (should be mapped with insert="false" update="false").

Добавьте следующее ( посмотрите как на XML, я использую анотации)

public class TakenItem {
    Integer idUser ;

    @Basic
    @Column(name = "idUser", nullable = true, insertable = false, updatable = false)
    public Integer getIdUser() {
        return idUser;
    }

    //Конструкторы...
    //сеттеры...
}

Answered by Oleg Ostroumov on December 19, 2020

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP