Я новичок в спящем режиме, изучаю документ, сохраняющий постоянный объект
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




Я думаю, что вам нужно установить значение 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
То же самое и с телефоном.
Нет, вы можете просто сохранить телефон для существующего человека, установив в телефоне действительного человека (с идентификатором) и выполнив em.persist (phone). В приведенном выше примере телефон спасен человеком из-за каскада.
ID человека, установленный вручную, может быть сохранен, но как и вышеупомянутая операция. Я вижу журнал телефона, а не номер телефона, поэтому get person_id имеет значение null, может быть ошибка каскада?
да. создать эту структуру таблицы. но не может создать ограничение внешнего ключа, только создать person_id в таблице phone
Добавьте аннотацию @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' не может быть нулевым, это странно
Какая у вас база данных?
база данных - mysql 8.0.13
Нет Каскада от телефона к человеку, настаивайте на человеке, а не на телефоне.
изменить человека также добавить каскад на телефон, который не может работать. только пропуск - phone.setPerson(person) будет работать
Позвольте нам продолжить обсуждение в чате.
Поскольку у вас нет типа генерации на вашем @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, да, добавили в сервис
не может работать. может телефон должен добавить phone.setPerson(person) добавить реф?
вам нужно, чтобы поле id обеих таблиц автоматически увеличивалось в базе данных и можно было использовать merge () вместо persist ()
сохранить ошибку с помощью merge (). phone not ref person, поэтому телефон не может получить person_id
Person (id, username) Phone (id, number, person_id (FK)) это ваша структура таблицы? тогда делайте так, как я делюсь. Я тестировал, что этот код работает
Я не создаю ограничение внешнего ключа для телефонного стола. только дать person_id ?
нужна еще какая-то конфигурация?
Позвольте нам продолжить обсуждение в чате.
нет, вам нужно создать внешний ключ. Иначе не получится. Вот почему вы получаете ошибку. Добавьте внешний ключ, а затем напишите код, которым я поделился. Он обязательно будет работать.
Добавьте внешний ключ, а затем напишите код, которым я поделился. Он обязательно будет работать.
надо дать разнонаправленному человеку и телефон спасет? ?