Одиночный класс составного картирования с Hibernate - PullRequest
1 голос
/ 09 июня 2011

Интересно, как отобразить составной шаблон одного класса с аннотациями в Hibernate? Человеческий объект может содержать детей, и у каждого ребенка могут быть свои дети. Спасибо.

Класс человеческого домена:

@Entity
public class Human implements Serializable
{
    private Human parent;

    @ManyToOne
    @JoinColumn(name = "parent_id")
    public Human getParent()
    {
        return parent;
    }

    public void setParent(Human parent)
    {
        this.parent = parent;
    }

    private List<Human> children = new ArrayList<Human>();

    @OneToMany(mappedBy = "parent", targetEntity = Human.class, fetch=FetchType.EAGER, cascade=CascadeType.ALL)
    public List<Human> getChildren()
    {
        return children;
    }

    @Id
    @GeneratedValue
    private Long id = null;

    private int version = 0;
    private String name;
    private int age;

    public String getName()
    {
        return name;
    }

    public void setName(String name)
    {
        this.name = name;
    }

    public int getAge()
    {
        return age;
    }

    public void setAge(int age)
    {
        this.age = age;
    }

    @OneToMany(mappedBy = "parent", targetEntity = Human.class, fetch=FetchType.EAGER, cascade=CascadeType.ALL)
    public void addChild(Human child)
    {
        child.setParent(this);
        children.add(child);    
    }
}

Основной класс:

public class Main
{

    /**
     * @param args
     */
    public static void main(String[] args)
    {
        System.out.println("start");
        Main main = new Main();
        main.run();
        main.run();
        System.out.println("stop");
    }

    public void run()
    {
        Session session = HibernateUtil.getSessionFactory().getCurrentSession();//.openSession();
        Transaction tx = session.beginTransaction();

        int len = 2;
        for (int i = 0; i < len; i++)
        {
            Human human = new Human();
            human.setName("name" + i);
            human.setAge(i);

            session.save(human);

            int clen = 2;
            for (int j = 0; j < clen; j++)
            {
                Human child = new Human();
                child.setName("cname" + j);
                child.setAge(j);

                human.addChild(child);
                session.save(child);
            }
        }

        tx.commit();
    }
}

Сообщение об ошибке:

INFO: Running hbm2ddl schema export
Jun 8, 2011 6:02:30 PM org.hibernate.tool.hbm2ddl.SchemaExport execute
INFO: exporting generated schema to database
Jun 8, 2011 6:02:30 PM org.hibernate.tool.hbm2ddl.SchemaExport create
SEVERE: Unsuccessful: create table human (id bigint not null auto_increment, age integer, name varchar(255), parent tinyblob, version integer, primary key (id))
Jun 8, 2011 6:02:30 PM org.hibernate.tool.hbm2ddl.SchemaExport create
SEVERE: Table 'human' already exists
Jun 8, 2011 6:02:30 PM org.hibernate.tool.hbm2ddl.SchemaExport create
SEVERE: Unsuccessful: alter table human add index FK5F0612DEE744FD6 (id), add constraint FK5F0612DEE744FD6 foreign key (id) references human (id)
Jun 8, 2011 6:02:30 PM org.hibernate.tool.hbm2ddl.SchemaExport create
SEVERE: Duplicate key name 'FK5F0612DEE744FD6'
Jun 8, 2011 6:02:30 PM org.hibernate.tool.hbm2ddl.SchemaExport execute
INFO: schema export complete
Hibernate: insert into human (age, name, parent, version) values (?, ?, ?, ?)
Jun 8, 2011 6:02:30 PM org.hibernate.util.JDBCExceptionReporter logExceptions
WARNING: SQL Error: 1054, SQLState: 42S22
Jun 8, 2011 6:02:30 PM org.hibernate.util.JDBCExceptionReporter logExceptions
SEVERE: Unknown column 'parent' in 'field list'
Exception in thread "main" org.hibernate.exception.SQLGrammarException: could not insert: [human.humanoid.Human]
    at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:90)
    at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
    at org.hibernate.id.insert.AbstractReturningDelegate.performInsert(AbstractReturningDelegate.java:64)

HibernateUtil класс:

public class HibernateUtil
{
    private static final SessionFactory sessionFactory;

    static
    {
        try
        {
            AnnotationConfiguration config = new AnnotationConfiguration();
            config.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQLDialect");
            config.setProperty("hibernate.connection.driver_class", "com.mysql.jdbc.Driver");
            config.setProperty("hibernate.connection.url", "jdbc:mysql://localhost/test");
            config.setProperty("hibernate.connection.username", "root");
            config.setProperty("hibernate.connection.password", "");
            config.setProperty("hibernate.connection.pool_size", "1");
            config.setProperty("hibernate.connection.autocommit", "true");
            config.setProperty("hibernate.cache.provider_class", "org.hibernate.cache.NoCacheProvider");
            config.setProperty("hibernate.hbm2ddl.auto", "create");
            config.setProperty("hibernate.show_sql", "true");
            config.setProperty("hibernate.transaction.factory_class", "org.hibernate.transaction.JDBCTransactionFactory");
            config.setProperty("hibernate.current_session_context_class", "thread");

            config.addAnnotatedClass(Human.class);

            sessionFactory = config.buildSessionFactory();
        }
        catch (Throwable ex)
        {
            System.err.println("Initial SessionFactory creation failed." + ex);
            throw new ExceptionInInitializerError(ex);
        }
    }

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

1 Ответ

1 голос
/ 09 июня 2011

Вам обязательно нужно удалить @OneToMany из метода addChild. Это ничего не добавляет, но может сбрасывать Hibernate. Попробуйте и опубликуйте результаты.


Обновление. Вот почему это не удается. Вы устанавливаете @Id в поле parent. Это заставляет Hibernate смотреть на все поля для сопоставления вместо свойств, указанных через getters / setters. Следовательно, он игнорирует вашу аннотацию @JoinColumn и обрабатывает поле parent как отображение столбца с именем по умолчанию parent.

Переместите все свои аннотации либо в получатели, либо в поля, и это должно решить проблему с неправильным отображением имени столбца.

...