休眠一对多关系java.sql.SQLIntegrityConstraintViolationException:列'person_id'不能为null

时间:2018-11-23 15:48:32

标签: java spring hibernate spring-mvc

我是新来的休眠者,学习文档保存持久对象

以下hibernate doc是一对多的人与电话的关系

const handleSaveToPC = jsonData => {
  const fileData = JSON.stringify(jsonData);
  const blob = new Blob([fileData], {type: "text/plain"});
  const url = URL.createObjectURL(blob);
  const link = document.createElement('a');
  link.download = 'filename.json';
  link.href = url;
  link.click();
}

我是坚持不懈的人,请添加一部手机以免出错

@Entity
@Table(name = "phone")
public class Phone {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;

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

    @ManyToOne(fetch = FetchType.LAZY)
    private Person person;

  //omit setter and getter
}

@Entity
@Table(name = "person")
public class Person {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;
    private String username;

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "person")
    private List<Phone> phones = new ArrayList<>();
   //omit getter and setter 
}

这是坚持不懈的

@Test
public void say() {
    Person person = new Person();
    person.setUsername("aaaa");

    Phone phone = new Phone();
    phone.setNumber("111");

    person.getPhones().add(phone);

    personService.save(person);
}

更新服务代码,服务只是保存人

public class PersonDaoImpl implements PersonDao {
    @PersistenceContext
    private EntityManager entityManager;

    @Override
    public void save(Person person) {
        entityManager.persist(person);
}

错误信息:

@Service(value = "personService")
public class PersonServiceImpl implements PersonService {
    @Autowired
    private PersonDao personDao;

    @Transactional
    @Override
    public void save(Person person) {
        personDao.save(person);
    }
}

erro img info

5 个答案:

答案 0 :(得分:2)

添加@GeneratedValue批注以指定两个实体的主键都将填充到代码之外。

@Entity
@Table(name = "phone")
public class Phone {

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

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

    @JoinColumn("person_id")
    @ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private Person person;

  //omit setter and getter
}


public class Person {
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private long id;
    private String username;

    @OneToMany(mappedBy = "person")
    private List<Phone> phones = new ArrayList<>();
   //omit getter and setter 
}

另外,由于没有从PersonPhone的级联配置,因此需要持久保存Phone对象而不是Person对象。如果您不能这样做,请将CascadeType上的Person切换为无,并将级联放置在Phone上,如上所示。

您还应该在@JoinColumn实体上添加Phone注释,以便hibernate知道外键列。

答案 1 :(得分:1)

您错过了一些东西。您可以尝试一下。

人员实体

@Entity
public class Person {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;
    private String username;

    @OneToMany(mappedBy = "person")
    private List<Phone> phones = new ArrayList<>();

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public long getId() {
        return id;
    }

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

    public List<Phone> getPhones() {
        return phones;
    }

    public void setPhones(List<Phone> phones) {
        this.phones = phones;
    }
    //omit getter and setter
}

电话实体

@Entity
@Table(name = "phone")
public class Phone {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

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

    @ManyToOne(cascade = CascadeType.PERSIST)
    private Person person;

    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number;
    }

    public Person getPerson() {
        return person;
    }

    public void setPerson(Person person) {
        this.person = person;
    }

    public long getId() {
        return id;
    }

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

    //ommit setter and getter
}

电话道

public interface PhoneDao {
    public Phone save(Phone phone);
}

PhoneDaoImpl

@Repository
public class PhoneDaoImpl implements PhoneDao {
    @PersistenceContext
    private EntityManager entityManager;

    @Override
    public Phone save(Phone phone) {

        return entityManager.merge(phone);
    }
}

PersonDaoImpl

@Repository
public class PersonDaoImpl implements PersonDao{
    @PersistenceContext
    private EntityManager entityManager;

    @Override
    public Person save(Person person) {

        return entityManager.merge(person);
    }
}

测试方法

@Test
    @Transactional
    @Commit
    public void say()
    {
        Phone phone = new Phone();
        phone.setNumber("jghjkhk");

        Person person = new Person();
        person.setUsername("7576");

        phone.setPerson(person);
        Phone pers = phoneDao.save(phone);
        Assert.assertNotNull(pers);
    }

立即尝试。它将起作用。

答案 2 :(得分:0)

我认为您需要设置person-> id的值,然后还使用getter方法将id传递给您的电话对象,而不是传递person对象

答案 3 :(得分:0)

通常人们已经使用代理键自动休眠设置实体的ID。

public class Person {
    @Id @GeneratedValue   // should pick an appropriate strategy here
    private long id;

由于您没有,所以您必须添加它或自己设置它。

 Person p = new Person();
 p.setId(1);   // hopefully unique

电话也一样。

答案 4 :(得分:0)

由于您的@Id上没有任何生成类型,并且id是主键,不能为null,因此您必须在id字段上设置id的值或具有@GeneratedValue注释,并将策略设置为Auto或身份。

您还可以生成自己的序列。

此外,您需要对Phone类进行相同的操作。