Отношение "один ко многим" в спящем режиме java.sql.SQLIntegrityConstraintViolationException: столбец 'person_id' не может иметь значение null

Я новичок в спящем режиме, изучаю документ, сохраняющий постоянный объект

followed спящий документ это отношения между человеком и телефоном "один ко многим"

@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);
    }
}

информация об ошибке:

    23:35:47.059 [main] DEBUG org.hibernate.engine.spi.ActionQueue - Executing identity-insert immediately
23:35:47.062 [main] DEBUG org.hibernate.SQL - 
    insert 
    into
        phone
        (number, person_id) 
    values
        (?, ?)
23:35:47.297 [main] DEBUG org.hibernate.engine.jdbc.spi.SqlExceptionHelper - could not execute statement [n/a]
java.sql.SQLIntegrityConstraintViolationException: Column 'person_id' cannot be null

Отношение &quot;один ко многим&quot; в спящем режиме java.sql.SQLIntegrityConstraintViolationException: столбец &apos;person_id&apos; не может иметь значение null

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
0
1 179
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Я думаю, что вам нужно установить значение person-> id, а затем также использовать метод получения, чтобы передать идентификатор вашему объекту телефона вместо передачи объекта человека

Обычно люди в спящем режиме автоматически устанавливают идентификатор объекта с помощью суррогатного ключа.

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

Поскольку у вас этого нет, вы должны либо добавить его, либо установить самостоятельно.

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

То же самое и с телефоном.

надо дать разнонаправленному человеку и телефон спасет? ?

F___ 23.11.2018 17:43

Нет, вы можете просто сохранить телефон для существующего человека, установив в телефоне действительного человека (с идентификатором) и выполнив em.persist (phone). В приведенном выше примере телефон спасен человеком из-за каскада.

K.Nicholas 23.11.2018 17:46

ID человека, установленный вручную, может быть сохранен, но как и вышеупомянутая операция. Я вижу журнал телефона, а не номер телефона, поэтому get person_id имеет значение null, может быть ошибка каскада?

F___ 23.11.2018 18:28

да. создать эту структуру таблицы. но не может создать ограничение внешнего ключа, только создать person_id в таблице phone

F___ 23.11.2018 18:33
Ответ принят как подходящий

Добавьте аннотацию @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 
}

Кроме того, вам необходимо сохранить объект Person вместо объекта Phone, потому что не существует каскада, настроенного с Phone на Person. Если вы не можете этого сделать, отключите CascadeType на Person и установите каскад на Phone, как показано выше.

Вы также должны добавить аннотацию @JoinColumn к объекту Phone, чтобы спящий режим знал о столбце внешнего ключа.

после этого добавьте @GeneratedValue (strategy = GenerationType.IDENTITY) для обоих объектов, все равно получить столбец 'person_id' не может быть нулевым, это странно

F___ 23.11.2018 17:31

Какая у вас база данных?

Kevin Bowersox 23.11.2018 17:31

база данных - mysql 8.0.13

F___ 23.11.2018 17:34

Нет Каскада от телефона к человеку, настаивайте на человеке, а не на телефоне.

Kevin Bowersox 23.11.2018 17:35

изменить человека также добавить каскад на телефон, который не может работать. только пропуск - phone.setPerson(person) будет работать

F___ 23.11.2018 17:40

Позвольте нам продолжить обсуждение в чате.

F___ 23.11.2018 17:48

Поскольку у вас нет типа генерации на вашем @Id, а id является первичным ключом, который не может быть нулевым, вам нужно либо установить значение id, либо иметь аннотацию @GeneratedValue в вашем поле id и установить стратегию либо как Auto, либо как Identity.

Вы также можете создать собственную последовательность.

Также вам нужно сделать то же самое для класса Phone.

Вы что-то пропустили. Вы можете попробовать с этим.

Лицо Сущность

@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);
}

Телефон

@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);
    }

Попробуй сейчас. Это будет работать.

@transactional, да, добавили в сервис

F___ 23.11.2018 18:10

не может работать. может телефон должен добавить phone.setPerson(person) добавить реф?

F___ 23.11.2018 18:16

вам нужно, чтобы поле id обеих таблиц автоматически увеличивалось в базе данных и можно было использовать merge () вместо persist ()

flopcoder 23.11.2018 18:19

сохранить ошибку с помощью merge (). phone not ref person, поэтому телефон не может получить person_id

F___ 23.11.2018 18:26

Person (id, username) Phone (id, number, person_id (FK)) это ваша структура таблицы? тогда делайте так, как я делюсь. Я тестировал, что этот код работает

flopcoder 23.11.2018 18:37

Я не создаю ограничение внешнего ключа для телефонного стола. только дать person_id ?

F___ 23.11.2018 18:46

нужна еще какая-то конфигурация?

F___ 23.11.2018 18:47

Позвольте нам продолжить обсуждение в чате.

flopcoder 23.11.2018 18:47

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

flopcoder 23.11.2018 18:48

Добавьте внешний ключ, а затем напишите код, которым я поделился. Он обязательно будет работать.

flopcoder 23.11.2018 18:52

Другие вопросы по теме