Подтвердить что ты не робот

Как использовать аннотации Hibernate @ManyToOne и @OneToMany для ассоциаций

Я изучаю Spring, Hibernate, Maven, используя этот учебник: Chad Lung: проект с использованием Netbeans 7, JUnit, Maven, HSQLDB, Spring и Hibernate. Он работает нормально, но мне нужно сделать отношения "один ко многим" (у одного сотрудника есть много задач). Я пробовал много примеров, но до сих пор не могу понять, как заставить мой код работать:

Employee.java:

package com.giantflyingsaucer.simplespringhibernate.entity;

import javax.persistence.*;
import java.io.Serializable;
import java.util.List;

@Entity
@Table(name = "Employees")
public class Employee implements Serializable {

    private Integer employeeId;
    private List<Task> tasks;

    @Id
    @Column(name = "idEmployees", nullable=false)
    public Integer getEmployeeId() {
        return this.employeeId;
    }

    public void setEmployeeId(Integer employeeId) {
        this.employeeId = employeeId;
    }

    @OneToMany(fetch = FetchType.LAZY)
    @JoinColumn(name="idEmployees")
    public List<Task> getTasks() {
        return tasks;
    }
}

Task.java:

package com.giantflyingsaucer.simplespringhibernate.entity;

import javax.persistence.*;
import java.io.Serializable;

@Entity
@Table(name = "Tasks")
public class Task implements Serializable {

    private Integer taskId;
    private Employee employee;


    @Id
    @Column(name = "idTasks", nullable=false)
    public Integer getTaskId() {
        return this.taskId;
    }

    public void setTaskId(Integer taskId) {
        this.taskId = taskId;
    }

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "TasksIdEmployees")
    public Employee getEmployee() {return employee;}

}

DB-config.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
">
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
    destroy-method="close">

    <property name="driverClass">
        <value>${jdbc.driver.className}</value>
    </property>
    <property name="jdbcUrl">
        <value>${jdbc.url}</value>
    </property>
    <property name="user">
        <value>${jdbc.username}</value>
    </property>
    <property name="password">
        <value>${jdbc.password}</value>
    </property>
</bean>
<bean id="sessionFactory"
    class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
    <property name="dataSource">
        <ref bean="dataSource" />
    </property>
    <property name="packagesToScan" value="com.giantflyingsaucer.simplespringhibernate.entity" />
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">${jdbc.hibernate.dialect}</prop>
            <prop key="hibernate.hbm2ddl.auto">update</prop>
            <prop key="hibernate.show_sql">false</prop>
        </props>
    </property>
</bean>
<bean id="transactionManager"
    class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory">
        <ref bean="sessionFactory" />
    </property>
</bean>
<tx:annotation-driven />

Таблицы MySQL:

CREATE TABLE employees (
`idEmployees` int(11) NOT NULL,
PRIMARY KEY (`idEmployees`)
);

CREATE TABLE tasks (
`idTasks` int(11) NOT NULL,
`TasksIdEmployees` int(11) DEFAULT NULL,
PRIMARY KEY (`idTasks`),
KEY `FkTasksEmployees_idx` (`TasksIdEmployees`),
CONSTRAINT `FkTasksEmployees` FOREIGN KEY (`TasksIdEmployees`) REFERENCES `employees`   (`idEmployees`) ON DELETE NO ACTION ON UPDATE NO ACTION
);

Спасибо большое!

Я нашел ответ на автогенерирование файлов сопоставления и POJO в NetBeans:

// Employee.java:
    @OneToMany(fetch = FetchType.LAZY, mappedBy = "employees")
    public List<Task> getTasks() {
        return this.tasks;
    }

    public void setTasks(List<Task> tasks) {
        this.tasks = tasks;
    }

// Task.java:
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "TasksIdEmployees")
public Employee getEmployees() {
    return this.employee;
}

public void setEmployees(Employee employee) {
    this.employee = employee;
}
4b9b3361

Ответ 1

Что не так:

@OneToMany(fetch = FetchType.LAZY)
@JoinColumn(name="idEmployees")
public List<Task> getTasks() {
    return tasks;
}

И это неправильно по двум причинам.

  • @JoinColumn(name="idEmployees") означает: этот OneToMany сопоставляется с использованием столбца объединения (то есть внешнего ключа) с именем idEmployees. Но столбец соединения не называется idEmployees. idEmployees является основным ключом таблицы Employee. Имя столбца объединения TasksIdEmployees. Помещение правильного имени сделает правильное отображение для однонаправленной ассоциации OneToMany. Но ассоциация двунаправленная, что приводит к второй причине...

  • В двунаправленной связи нет необходимости (и это ошибка) повторять информацию сопоставления с обеих сторон ассоциации. Одна сторона (большая сторона) должна быть владельцем ассоциации и определять отображение. Другая сторона должна быть обратной стороной, просто говоря: идите на другую сторону, как эта ассоциация отображается. Это делается с использованием атрибута mappedBy, который сообщает Hibernate имя поля или свойства на другой стороне, которая является владельцем ассоциации:

    @OneToMany(mappedBy = "employee")
    public List<Task> getTasks() {
        return tasks;
    }
    

Обратите внимание, что LAZY является значением по умолчанию для ассоциаций toMany, поэтому его необязательно указывать.