Java 双向实体关系使用Spring保存id null

Java 双向实体关系使用Spring保存id null,java,spring,Java,Spring,我正在用JpaRepository学习Spring boot,这个问题让我停滞不前。 我正在尝试保存一个对象列表,但它们以id null保存双向关系中的所有对象,我看到了很多示例,所有这些都很有效,即使我有另一个项目,具有相同的示例,但不同的实体,效果很好,我希望我已经正确地表达了我的问题 一门课 @Entity @Table(name="producto") public class Producto { @Id @GeneratedValue(strategy = Gene

我正在用JpaRepository学习Spring boot,这个问题让我停滞不前。 我正在尝试保存一个对象列表,但它们以id null保存双向关系中的所有对象,我看到了很多示例,所有这些都很有效,即使我有另一个项目,具有相同的示例,但不同的实体,效果很好,我希望我已经正确地表达了我的问题

一门课

@Entity
@Table(name="producto")
public class Producto {

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

    // there are more attributes but i'm hiding It to show less code to  try this more easier to see

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name="proveedor_id")
    private Proveedor proveedor;

// getters and setter

// constructor empty and others constructors

@Entity
@Table(name="proveedores")
public class Proveedor {
   @Id
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   @Column(name="id")
   private Long id;


   @OneToMany(mappedBy = "proveedor", cascade = CascadeType.ALL)
   private List<Producto> listaProducto =  new ArrayList<Producto>();

// getters and setter

// constructor empty and others constructors

另一个类

@Entity
@Table(name="producto")
public class Producto {

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

    // there are more attributes but i'm hiding It to show less code to  try this more easier to see

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name="proveedor_id")
    private Proveedor proveedor;

// getters and setter

// constructor empty and others constructors

@Entity
@Table(name="proveedores")
public class Proveedor {
   @Id
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   @Column(name="id")
   private Long id;


   @OneToMany(mappedBy = "proveedor", cascade = CascadeType.ALL)
   private List<Producto> listaProducto =  new ArrayList<Producto>();

// getters and setter

// constructor empty and others constructors

@实体
@表(name=“proveedores”)
公共类证明器{
@身份证
@GeneratedValue(策略=GenerationType.IDENTITY)
@列(name=“id”)
私人长id;
@OneToMany(mappedBy=“proveedor”,cascade=CascadeType.ALL)
private List listaProducto=new ArrayList();
//接球手和接球手
//构造函数为空,其他构造函数为空
这是测试

   @Test
   void addProveedorConProductos() {
   Proveedor test = new Proveedor();
   List<Producto> lista = new ArrayList<Producto>();
       lista.add(new Producto("bbb","pruebaTest2",123,null,null,null));
       lista.add(new Producto("a","pruebaTest21111",123,null,null,null));
       test = new Proveedor("pruebaTestCase", 12345,lista);
       assertNotNull(proveedor.save(test));

   }

@测试
void addProveedorConProductos(){
Proveedor测试=新Proveedor();
List lista=new ArrayList();
添加(新产品(“bbb”,“pruebaTest2”,123,null,null,null));
添加(新产品(“a”,“pruebaTest21111”,123,null,null,null));
测试=新的验证人(“pruebaTestCase”,12345,lista);
assertNotNull(proveedor.save(test));
}
结果

   @Test
   void addProveedorConProductos() {
   Proveedor test = new Proveedor();
   List<Producto> lista = new ArrayList<Producto>();
       lista.add(new Producto("bbb","pruebaTest2",123,null,null,null));
       lista.add(new Producto("a","pruebaTest21111",123,null,null,null));
       test = new Proveedor("pruebaTestCase", 12345,lista);
       assertNotNull(proveedor.save(test));

   }


所有保存都可以,但id\u Proveeder保存为空,这是结果的图像

我认为您需要先保存Producto。 然后,在数据库中调用Producto上的find,可以将Producto添加到provedor中,希望您能解决这个问题。 就像这样:

productoRepository.save(new Producto("bbb","pruebaTest2",123,null,null,null));
productoRepository.save(new Producto("a","pruebaTest21111",123,null,null,null)));
List<Producto> lista = productoRepository.findAll();
proveedorRepository.save(new Proveedor("pruebaTestCase", 12345, lista);
productoRepository.save(新产品(“bbb”、“pruebaTest2”、123、null、null、null));
save(新产品(“a”、“pruebaTest21111”、123、null、null、null));
List lista=productoRepository.findAll();
proveedorRepository.save(新Proveedor(“pruebaTestCase”,12345,lista);

我已经实施了与您情况相同的项目。您可以参考我的代码,希望您有更多的想法来解决您的问题

第一步:创建角色实体与用户实体有很多关系

package com.tvp.springrest.role;

import java.util.List;

import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.Table;

import com.tvp.springrest.user.User;

import lombok.Data;

@Entity
@Data
@Table(name = "role")
public class Role {

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

@Enumerated(EnumType.STRING)
private ERole name;

@ManyToMany(mappedBy = "roles")
private List<User> users;

public Role(ERole name) {
    this.name = name;
}

public Role() {
}

}
package com.tvp.springrest.user;

import java.util.HashSet;
import java.util.Set;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;

import com.tvp.springrest.role.Role;

import lombok.Data;

@Entity
@Data
@Table(name = "users",
uniqueConstraints = {
    @UniqueConstraint(columnNames = "username"),
    @UniqueConstraint(columnNames =  "email")
}
)
public class User {

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

@NotBlank
@Size(max = 20)
private String username;

@NotBlank
@Size(max = 50)
@Email
private String email;

@NotBlank
@Size(max = 120)
private String password;

@ManyToMany
@JoinTable(name = "user_role",
    joinColumns =  @JoinColumn(name = "user_id"),
    inverseJoinColumns = @JoinColumn(name = "role_id")
)
private Set<Role> roles = new HashSet<>();

public User(@NotBlank @Size(max = 20) String username, @NotBlank @Size(max = 50) @Email String email,
        @NotBlank @Size(max = 120) String password) {
    this.username = username;
    this.email = email;
    this.password = password;
}

public User() {
}

public User(@NotBlank @Size(max = 20) String username, @NotBlank @Size(max = 50) @Email String email,
        @NotBlank @Size(max = 120) String password, Set<Role> roles) {
    this.username = username;
    this.email = email;
    this.password = password;
    this.roles = roles;
}

}
package com.tvp.springrest.role;

import java.util.Optional;

import org.springframework.stereotype.Repository;
import org.springframework.data.jpa.repository.JpaRepository;

@Repository
public interface RoleRepository extends JpaRepository<Role, Long> {
  Optional<Role> findByName(ERole name);
}
第二步:创建用户实体

package com.tvp.springrest.role;

import java.util.List;

import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.Table;

import com.tvp.springrest.user.User;

import lombok.Data;

@Entity
@Data
@Table(name = "role")
public class Role {

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

@Enumerated(EnumType.STRING)
private ERole name;

@ManyToMany(mappedBy = "roles")
private List<User> users;

public Role(ERole name) {
    this.name = name;
}

public Role() {
}

}
package com.tvp.springrest.user;

import java.util.HashSet;
import java.util.Set;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;

import com.tvp.springrest.role.Role;

import lombok.Data;

@Entity
@Data
@Table(name = "users",
uniqueConstraints = {
    @UniqueConstraint(columnNames = "username"),
    @UniqueConstraint(columnNames =  "email")
}
)
public class User {

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

@NotBlank
@Size(max = 20)
private String username;

@NotBlank
@Size(max = 50)
@Email
private String email;

@NotBlank
@Size(max = 120)
private String password;

@ManyToMany
@JoinTable(name = "user_role",
    joinColumns =  @JoinColumn(name = "user_id"),
    inverseJoinColumns = @JoinColumn(name = "role_id")
)
private Set<Role> roles = new HashSet<>();

public User(@NotBlank @Size(max = 20) String username, @NotBlank @Size(max = 50) @Email String email,
        @NotBlank @Size(max = 120) String password) {
    this.username = username;
    this.email = email;
    this.password = password;
}

public User() {
}

public User(@NotBlank @Size(max = 20) String username, @NotBlank @Size(max = 50) @Email String email,
        @NotBlank @Size(max = 120) String password, Set<Role> roles) {
    this.username = username;
    this.email = email;
    this.password = password;
    this.roles = roles;
}

}
package com.tvp.springrest.role;

import java.util.Optional;

import org.springframework.stereotype.Repository;
import org.springframework.data.jpa.repository.JpaRepository;

@Repository
public interface RoleRepository extends JpaRepository<Role, Long> {
  Optional<Role> findByName(ERole name);
}
package com.tvp.springrest.user;
导入java.util.HashSet;
导入java.util.Set;
导入javax.persistence.Entity;
导入javax.persistence.GeneratedValue;
导入javax.persistence.GenerationType;
导入javax.persistence.Id;
导入javax.persistence.JoinColumn;
导入javax.persistence.JoinTable;
导入javax.persistence.ManyToMany;
导入javax.persistence.Table;
导入javax.persistence.UniqueConstraint;
导入javax.validation.constraints.Email;
导入javax.validation.constraints.NotBlank;
导入javax.validation.constraints.Size;
导入com.tvp.springrest.role.role;
导入龙目数据;
@实体
@资料
@表(name=“users”,
唯一约束={
@UniqueConstraint(columnNames=“username”),
@UniqueConstraint(columnNames=“电子邮件”)
}
)
公共类用户{
@身份证
@GeneratedValue(策略=GenerationType.IDENTITY)
私人长id;
@不空白
@尺寸(最大值=20)
私有字符串用户名;
@不空白
@尺寸(最大值=50)
@电子邮件
私人字符串电子邮件;
@不空白
@尺寸(最大值=120)
私有字符串密码;
@许多
@JoinTable(name=“user\u role”,
joinColumns=@JoinColumn(name=“user\u id”),
inverseJoinColumns=@JoinColumn(name=“role\u id”)
)
私有集角色=新HashSet();
公共用户(@NotBlank@Size(max=20)字符串用户名,@NotBlank@Size(max=50)@Email字符串电子邮件,
@NotBlank@Size(最大值=120)字符串密码){
this.username=用户名;
this.email=电子邮件;
this.password=密码;
}
公共用户(){
}
公共用户(@NotBlank@Size(max=20)字符串用户名,@NotBlank@Size(max=50)@Email字符串电子邮件,
@NotBlank@Size(最大值=120)字符串密码,设置角色){
this.username=用户名;
this.email=电子邮件;
this.password=密码;
this.roles=角色;
}
}
第三步:您需要为角色和用户实体创建存储库

package com.tvp.springrest.role;

import java.util.List;

import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.Table;

import com.tvp.springrest.user.User;

import lombok.Data;

@Entity
@Data
@Table(name = "role")
public class Role {

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

@Enumerated(EnumType.STRING)
private ERole name;

@ManyToMany(mappedBy = "roles")
private List<User> users;

public Role(ERole name) {
    this.name = name;
}

public Role() {
}

}
package com.tvp.springrest.user;

import java.util.HashSet;
import java.util.Set;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;

import com.tvp.springrest.role.Role;

import lombok.Data;

@Entity
@Data
@Table(name = "users",
uniqueConstraints = {
    @UniqueConstraint(columnNames = "username"),
    @UniqueConstraint(columnNames =  "email")
}
)
public class User {

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

@NotBlank
@Size(max = 20)
private String username;

@NotBlank
@Size(max = 50)
@Email
private String email;

@NotBlank
@Size(max = 120)
private String password;

@ManyToMany
@JoinTable(name = "user_role",
    joinColumns =  @JoinColumn(name = "user_id"),
    inverseJoinColumns = @JoinColumn(name = "role_id")
)
private Set<Role> roles = new HashSet<>();

public User(@NotBlank @Size(max = 20) String username, @NotBlank @Size(max = 50) @Email String email,
        @NotBlank @Size(max = 120) String password) {
    this.username = username;
    this.email = email;
    this.password = password;
}

public User() {
}

public User(@NotBlank @Size(max = 20) String username, @NotBlank @Size(max = 50) @Email String email,
        @NotBlank @Size(max = 120) String password, Set<Role> roles) {
    this.username = username;
    this.email = email;
    this.password = password;
    this.roles = roles;
}

}
package com.tvp.springrest.role;

import java.util.Optional;

import org.springframework.stereotype.Repository;
import org.springframework.data.jpa.repository.JpaRepository;

@Repository
public interface RoleRepository extends JpaRepository<Role, Long> {
  Optional<Role> findByName(ERole name);
}
package com.tvp.springrest.role;
导入java.util.Optional;
导入org.springframework.stereotype.Repository;
导入org.springframework.data.jpa.repository.JpaRepository;
@存储库
公共接口角色库扩展了JPA角色库{
可选findByName(ERole名称);
}
用户

package com.tvp.springrest.user;

import java.util.Optional;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface UserRepository extends JpaRepository<User, Long>{

Optional<User> findByUsername(String username);

Boolean existsByUsername(String username);

Boolean existsByEmail(String name);

}
package com.tvp.springrest.user;
导入java.util.Optional;
导入org.springframework.data.jpa.repository.JpaRepository;
导入org.springframework.stereotype.Repository;
@存储库
公共接口用户存储库扩展了JpaRepository{
可选findByUsername(字符串用户名);
布尔existsByUsername(字符串用户名);
布尔existsByEmail(字符串名称);
}
之后,您可以为数据库创建数据:

package com.tvp.springrest;

import java.util.HashSet;
import java.util.Set;

import com.tvp.springrest.employee.EmployeeRepository;
import com.tvp.springrest.order.OrderRepository;
import com.tvp.springrest.role.ERole;
import com.tvp.springrest.role.Role;
import com.tvp.springrest.role.RoleRepository;
import com.tvp.springrest.user.User;
import com.tvp.springrest.user.UserRepository;

import org.springframework.boot.CommandLineRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import lombok.extern.slf4j.Slf4j;

@Configuration
public class LoadDatabase {

@Bean
CommandLineRunner initDatabase(
  RoleRepository roleRepository, UserRepository userRepository) {
return args -> {

  roleRepository.save(new Role(ERole.ADMIN));
  roleRepository.save(new Role(ERole.MODERATOR));
  roleRepository.save(new Role(ERole.USER));

  Set<Role> roles = new HashSet<>();
  roles.add(roleRepository.findByName(ERole.ADMIN).get());
  roles.add(roleRepository.findByName(ERole.MODERATOR).get());
  roles.add(roleRepository.findByName(ERole.USER).get());

  Set<Role> roles1 = new HashSet<>();
  roles1.add(roleRepository.findByName(ERole.USER).get());

  Set<Role> roles2 = new HashSet<>();
  roles2.add(roleRepository.findByName(ERole.MODERATOR).get());

  userRepository.save(new User("test1", "test1@gmail.com", "123456", roles));
  userRepository.save(new User("test2", "test2@gmail.com", "123456", roles1));
  userRepository.save(new User("test3", "test3@gmail.com", "123456", roles2));

};
}

}
package com.tvp.springrest;
导入java.util.HashSet;
导入java.util.Set;
导入com.tvp.springrest.employee.EmployeeRepository;
导入com.tvp.springrest.order.OrderRepository;
导入com.tvp.springrest.role.ERole;
导入com.tvp.springrest.role.role;
导入com.tvp.springrest.role.rolerepositionary;
导入com.tvp.springrest.user.user;
导入com.tvp.springrest.user.UserRepository;
导入org.springframework.boot.CommandLineRunner;
导入org.springframework.context.annotation.Bean;
导入org.springframework.context.annotation.Configuration;
导入lombok.extern.slf4j.slf4j;
@配置
公共类装入数据库{
@豆子
CommandLineRunner初始化数据库(
角色存储角色存储,用户存储库用户存储库){
返回参数->{
roleRepository.save(新角色(ERole.ADMIN));
roleRepository.save(新角色(ERole.版主));
保存(新角色(ERole.USER));
Set roles=new HashSet();
roles.add(roleRepository.findByName(ERole.ADMIN.get());
roles.add(roleRepository.findByName(ERole.MODERATOR.get());
roles.add(roleRepository.findByName(ERole.USER.get());
Set roles1=新的HashSet();
roles1.add(roleRepository.findByName(ERole.USER.get());
Set roles2=新的HashSet();
角色2.add(roleRepository.findByName(ERole.版主)