2016-08-11 3 views
0

У меня есть 2 стола & Vehicle, где один сотрудник может иметь несколько транспортных средств. Ниже отображение, что я определил:Hibernate - Иностранный ключ пуст при использовании mappedBy

Employee.java

@Entity(name = "emp_details") 
public class Employee { 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private int empId; 

    @OneToMany(cascade = CascadeType.ALL, mappedBy="employee") 
    private List<Vehicle> vehicles = new ArrayList<>(); 

    public int getEmpId() { 
     return empId; 
    } 

    public void setEmpId(int empId) { 
     this.empId = empId; 
    } 

    public List<Vehicle> getVehicles() { 
     return vehicles; 
    } 

    public void setVehicles(List<Vehicle> vehicles) { 
     this.vehicles = vehicles; 
    } 

} 

Vehicle.java

@Entity 
public class Vehicle { 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private int vehicleId; 

    @ManyToOne 
    @JoinColumn(name="empId") 
    private Employee employee; 

    private String name; 

    public Employee getEmployee() { 
     return employee; 
    } 

    public void setEmployee(Employee employee) { 
     this.employee = employee; 
    } 

    public int getVehicleId() { 
     return vehicleId; 
    } 

    public void setVehicleId(int vehicleId) { 
     this.vehicleId = vehicleId; 
    } 

    public String getName() { 
     return name; 
    } 

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

} 

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

public class HibernateTest { 

    public static void main(String[] args) { 
     Employee emp = new Employee(); 

     Vehicle vehicle = new Vehicle(); 
     vehicle.setName("Honda"); 
     emp.getVehicles().add(vehicle); 


     SessionFactory sFactory = new Configuration().configure().buildSessionFactory(); 
     Session session = sFactory.openSession(); 
     session.beginTransaction(); 
     session.save(emp); 
     session.getTransaction().commit(); 
     session.close(); 

     StandardServiceRegistryBuilder.destroy(sFactory.getSessionFactoryOptions().getServiceRegistry()); 

    } 

} 

Но когда я выполняю это, Vehicle.employee_id пуст. Я ожидал, что мой внешний ключ будет вставлен туда.

enter image description here

Что мне не хватает?

Спасибо

+1

Нельзя каскадировать от транспортного средства к сотруднику. Всегда каскадируйте только в одном направлении. – kaba713

ответ

1

Вы должны показать нам код, который сохраняется ваши объекты, но я думаю, что вы не устанавливая employee к vehicle.

Вам необходимо управлять обеими сторонами двунаправленной сущности. Ваш код должен выглядеть как этот

employee.getVehicles().add(vehicle); 
vehicle.setEmployee(employee); 

session.save(employee); 

UPDATE:

В этом случае Vehicle является владеющее сторона отношения, так как внешний ключ в таблице базы данных. Вы только что добавили новый автомобиль в список транспортных средств сотрудника. Когда вы работаете save, ничего не нужно менять в базе данных Employee, а операционные каскады save - Vehicle. Автомобиль не имеет свой набор персонала, он является недействительным, так что ставит null в empId колонки

Нижней линией, вы должны убедиться, что обе стороны двунаправленного отношения подключены правильно.

+0

Я добавил полный фрагмент кода. – reiley

+0

Как я подозревал в своем ответе. Добавьте 'vehicle.setEmployee (emp)' перед сохранением сотрудника. –

+0

Итак, вы говорите, помимо экономии транспортного средства у сотрудника, мне также нужно сэкономить сотрудника в транспортном средстве. Но я думал, что Hibernate достаточно умен, чтобы создать отношения, если он определен только одним способом. Пожалуйста, уточните для меня, это возможно. Спасибо. – reiley

0

Мне кажется, вам нужно изменить свой код. вы пропустите правило jpa организации. вы можете найти объект jpa. вы читаете описание для вас. ссылка: enter link description here

(Modified ваш Employee.java)

@Entity(name = "employee") 
public class Employee { 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private int idx; 

    @OneToMany(cascade = {CascadeType.ALL}, mappedBy = "employee") 
    private List<Vehicle> vehicle = new ArrayList<>(); 
    ... 
} 

(Изменив Vehicle.java)

@Entity 
public class Vehicle { 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private int idx; 

    @ManyToOne 
    @JoinColumn(name="employee_id") 
    private Employee employee; 
    ... 
} 
0

В вашем Сотрудника класса сущности, вы не использовали @column аннотацию на EmpId. В классе Vehicle вы ссылаетесь на Employee, используя @JoinColumn (name = "employee_id"), поэтому столбец employee_id должен существовать в таблице emp_details.Таким образом, вы должны изменить свой класс Employee к чему-то с

 @Id 
    @GeneratedValue 
    @Column(name="employee_id") 
    private int empId; 
+0

Нет. Это неправильно. Employee_id находится в таблице транспортного средства и ссылается на идентификатор в таблице сотрудников. Это не должно быть в таблице сотрудников. – kaba713

+0

@ kaba713 мой плохой ты прав. – skm

0

Вам нужно только каскадом onetoMany от Сотрудника Entity

+0

Тем не менее, это не решает мою проблему – reiley

+0

Как вы сохраняете свои данные? – kaba713

1

Если у вас есть двунаправленные отношения, вы должны установить связь с обеих сторон.

Это означает, что вам необходимо установить employee для вашего vehicle.

Вы можете сделать это по телефону

vehicle.setEmployee(emp); 

, а затем сохранить или обновить объект (если он не подключен к сессии уже).

Обычно для установки двунаправленных отношений вы предоставляете специальные методы в своих объектах.

public class Vehicle { 
    ... 
    public void setEmployee(Employee employee) { 
     this.employee = employee; 
     employee.addVehicle(this) 
    } 
    ... 
} 

public class Employee { 
    ... 
    public void addVehicle(Vehicle v) { 
      if(!vehicles.contains(v)) { 
      vehicles.add(v); 
      } 
      if(!this.equals(v.getEmployee()) { 
      v.setEmployee(this); 
      } 
    } 
    ... 
} 
Смежные вопросы