Springboot:如何使用Spring Data JPA保存嵌套关联

时间:2018-03-11 06:47:16

标签: hibernate spring-boot spring-data-jpa spring-rest

我有两个模型,即公司和用户公司有很多用户。 当我保存公司时,我需要自动保存用户。 有没有一种方法可以让JPA实现这样的目标?

以下是我的模特:

//公司模式

@Entity
public class Company {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @NotNull
    @Size(min = 4, max = 100)
    private String name;

    @Size(max = 500)
    private String description;

    @OneToMany(mappedBy = "company",cascade = CascadeType.ALL)
    private List<User> users = new ArrayList<>();

    public Company(){};

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public List<User> getUsers() {
        return users;
    }

    public void setUsers(List<User> users) {
        this.users = users;
    }
}

//用户模型

@Entity
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Column(length = 50, unique = true)
    @NotNull
    @Size(min = 4, max = 50)
    private String username;

    @Column(length = 50)
    @NotNull
    @Size(min = 8, max = 50)
    private String password;

    @Column(length = 50)
    @NotNull
    @Size(min = 4, max = 50)
    private String firstName;

    @Column(length = 50)
    @NotNull
    @Size(min = 4, max = 50)
    private String lastName;

    @Column(length = 50, unique = true)
    @NotNull
    @Size(min = 4, max = 50)
    private String email;

    private Boolean enabled;

    @Temporal(TemporalType.TIMESTAMP)
    @NotNull
    private Date lastPasswordReset;

    @Column(nullable = false, updatable = false)
    @Temporal(TemporalType.TIMESTAMP)
    @CreatedDate
    private Date createdAt;

    @Column(nullable = false)
    @Temporal(TemporalType.TIMESTAMP)
    @LastModifiedDate
    private Date updatedAt;

    @ManyToMany(fetch = FetchType.EAGER)
    @JoinTable(
            name = "user_authority",
            joinColumns = {@JoinColumn(name = "user_id", referencedColumnName = "id")},
            inverseJoinColumns = {@JoinColumn(name = "authority_id", referencedColumnName = "id")})
    private List<Authority> authorities;

    @ManyToOne(optional = false, fetch = FetchType.LAZY, cascade = CascadeType.REMOVE)
private Company company;

.... Followed by getters and setters
}

因此客户端发送一个请求有效负载,其中包含嵌套的JSON对象,如:

"company":{  
   "name":"Evil Corp",
   "description":"test",
   "users":[  
      {  
         "userName":"xyz",
         "password":"abc"         //folllowed by other attributes
      }
   ]
}

//公司控制器

@RestController
@RequestMapping("/api/v1/company")
public class CompanyController {

    @Autowired
    ICompanyService companyService;

    @RequestMapping(value = "/create", method = RequestMethod.POST)
    public ResponseEntity<Company> create(@RequestBody Company company){
        System.out.println("Request Recieved");
        company = companyService.save(company);
        return ResponseEntity.ok(company);
    }
}

//服务

@Service
public class CompanyService implements ICompanyService {

    @Autowired
    CompanyRepository companyRepository;

    @Override
    public Company save(Company company) {
        return companyRepository.save(company);
    }
}

当我尝试保存时,我遇到以下异常:

Hibernate: insert into user (company_id, created_at, email, enabled, first_name, last_name, last_password_reset, password, updated_at, username, id) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
2018-03-11 15:15:57.814  WARN 7733 --- [nio-8080-exec-2] o.h.engine.jdbc.spi.SqlExceptionHelper   : SQL Error: 1048, SQLState: 23000
2018-03-11 15:15:57.816 ERROR 7733 --- [nio-8080-exec-2] o.h.engine.jdbc.spi.SqlExceptionHelper   : Column 'company_id' cannot be null
2018-03-11 15:15:57.853  INFO 7733 --- [nio-8080-exec-2] o.h.e.j.b.internal.AbstractBatchImpl     : HHH000010: On release of batch it still contained JDBC statements
2018-03-11 15:15:57.881 ERROR 7733 --- [nio-8080-exec-2] o.h.i.ExceptionMapperStandardImpl        : HHH000346: Error during managed flush [org.hibernate.exception.ConstraintViolationException: could not execute statement]

那么如何保存嵌套关联? 保存公司后,我是否需要手动设置user_id字段?我在使用 Rails 时已经完成了这样的事情。 Spring Boot上也存在这样的事情吗?

1 个答案:

答案 0 :(得分:0)

公司ID是用户表中的外键,因此在将父对象和子对象保存在一起之前,请确保子对象应设置父对象。

例如,在您的情况下 - 在用户实体中有多对一的关系,如

@ManyToOne(optional = false, fetch = FetchType.LAZY, cascade = 
  CascadeType.REMOVE)
 private Company company;

将此公司对象设置为用户对象,然后在将公司对象保存到数据库时自动插入其子对象。 您已使用 cascade = CascadeType.ALL ,因此它应插入子对象。