一对多的连接列为空休眠

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一对多的连接列为空休眠相关的知识,希望对你有一定的参考价值。

[我正在学习休眠,并且尝试在休眠中实现一对多关系(使用mysql和spring jpa的spring boot),并且遇到了我花了3个小时的运行时错误。

一对多关系中两个表的连接列为空

一对多:(部门可以有很多员工)

package com.example.hibernateDemo.models;

import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;

@Entity
@Table(name = "departments")
public class Department {

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

    @Column(name = "category")
    private String category;

    @OneToMany(mappedBy = "department", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<Employee> employees;

    @Column(name = "number_of_employees")
    private int numberOfEmployees;

    public Department() {
    }
    // getters and setters as well as one more constructor

员工多对多:

package com.example.hibernateDemo.models;

import javax.persistence.*;

@Entity
@Table(name = "employees")
public class Employee {

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

    @Column(name = "name")
    private String name;

    @Column(name = "hours_of_work_per_day")
    private int hoursOfWorkPerDay;

    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name="department_id", nullable=false, referencedColumnName = "id")
    private Department department;

    public Employee() {
    }
    // getters and setters as well as constructor

application.properties:

## Spring DATASOURCE (DataSourceAutoConfiguration & DataSourceProperties)
spring.datasource.url = jdbc:mysql://localhost:3306/demo
spring.datasource.username = ?{username}
spring.datasource.password = ?{password}
## Hibernate Properties
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect
spring.jpa.hibernate.ddl-auto = update

SpringBootApplication:

import org.springframework.data.jpa.repository.config.EnableJpaRepositories;

import java.util.ArrayList;
import java.util.List;

@SpringBootApplication
@ComponentScan
@EnableJpaRepositories("com.example.hibernateDemo.Repositories") // important for enabling JpaRepository
public class HibernateDemoApplication {


    public static void main(String[] args) {
        ApplicationContext context = SpringApplication.run(HibernateDemoApplication.class, args);
        List<Employee> employeeList = new ArrayList<>();
        employeeList.add(new Employee("david", 8));
        employeeList.add(new Employee("jordan", 12));
        Department department = new Department("software engineers", employeeList);
        DepartmentRepository serviceDepartment = context.getBean(DepartmentRepository.class);
        serviceDepartment.save(department);
        System.out.println("inserted");
    }

}

控制台输出:

  .   ____          _            __ _ _
 /\ / ___'_ __ _ _(_)_ __  __ _    
( ( )\___ | '_ | '_| | '_ / _` |    
 \/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.2.5.RELEASE)

2020-03-25 19:54:08.563  INFO 7935 --- [           main] c.e.h.HibernateDemoApplication           : Starting HibernateDemoApplication on abu with PID 7935 (/home/yoav/hibernateDemo/target/classes started by yoav in /home/yoav/hibernateDemo)
2020-03-25 19:54:08.566  INFO 7935 --- [           main] c.e.h.HibernateDemoApplication           : No active profile set, falling back to default profiles: default
2020-03-25 19:54:09.352  INFO 7935 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA repositories in DEFAULT mode.
2020-03-25 19:54:09.446  INFO 7935 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 84ms. Found 5 JPA repository interfaces.
2020-03-25 19:54:10.539  INFO 7935 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2020-03-25 19:54:10.554  INFO 7935 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2020-03-25 19:54:10.554  INFO 7935 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.31]
2020-03-25 19:54:10.635  INFO 7935 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2020-03-25 19:54:10.635  INFO 7935 --- [           main] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 1938 ms
2020-03-25 19:54:10.984  INFO 7935 --- [           main] o.hibernate.jpa.internal.util.LogHelper  : HHH000204: Processing PersistenceUnitInfo [name: default]
2020-03-25 19:54:11.043  INFO 7935 --- [           main] org.hibernate.Version                    : HHH000412: Hibernate ORM core version 5.4.12.Final
2020-03-25 19:54:11.354  INFO 7935 --- [           main] o.hibernate.annotations.common.Version   : HCANN000001: Hibernate Commons Annotations {5.1.0.Final}
2020-03-25 19:54:11.543  INFO 7935 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
2020-03-25 19:54:12.593  INFO 7935 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.
2020-03-25 19:54:12.655  INFO 7935 --- [           main] org.hibernate.dialect.Dialect            : HHH000400: Using dialect: org.hibernate.dialect.MySQL5InnoDBDialect
2020-03-25 19:54:17.417  INFO 7935 --- [           main] o.h.e.t.j.p.i.JtaPlatformInitiator       : HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
2020-03-25 19:54:17.442  INFO 7935 --- [           main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
2020-03-25 19:54:20.370  WARN 7935 --- [           main] JpaBaseConfiguration$JpaWebConfiguration : spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning
2020-03-25 19:54:20.629  INFO 7935 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2020-03-25 19:54:20.983  INFO 7935 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2020-03-25 19:54:20.984  INFO 7935 --- [           main] c.e.h.HibernateDemoApplication           : Started HibernateDemoApplication in 13.242 seconds (JVM running for 13.636)
2020-03-25 19:54:21.238  WARN 7935 --- [           main] o.h.engine.jdbc.spi.SqlExceptionHelper   : SQL Error: 1048, SQLState: 23000
2020-03-25 19:54:21.238 ERROR 7935 --- [           main] o.h.engine.jdbc.spi.SqlExceptionHelper   : Column 'department_id' cannot be null
Exception in thread "main" org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:298)
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:255)
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:528)
 // AND MORE A LOT MORE
答案

您必须在子方面同步关系:

public static void main(String[] args) {
    ApplicationContext context = SpringApplication.run(HibernateDemoApplication.class, args);
    List<Employee> employeeList = new ArrayList<>();
    employeeList.add(new Employee("david", 8));
    employeeList.add(new Employee("jordan", 12));
    Department department = new Department("software engineers", employeeList);
    employeeList.forEach(e -> e.setDepartment(department)); // this line was missing
    DepartmentRepository serviceDepartment = context.getBean(DepartmentRepository.class);
    serviceDepartment.save(department);
    System.out.println("inserted");
}

子方是关系的所有者,因为这是外键所在的位置。

以上是关于一对多的连接列为空休眠的主要内容,如果未能解决你的问题,请参考以下文章

如何使用注释在休眠中进行一对一映射

休眠一对多注释外键空

从孩子保存时,休眠一对多双向连接会提供新的父母

如何使用同一列休眠设置多个一对多关系

查询具有两个一对多集合的休眠实体

时间戳的休眠搜索查询返回空列表