#java #mysql #spring #jpa
#java #mysql #весна #jpa
Вопрос:
Я работаю с. spring-boot-starter-data-jpa
Должен ли я использовать аннотацию @GeneratedValue
для своего идентификатора объекта, если мой код работает без него, и автоматически генерировать ПЕРВИЧНЫЙ КЛЮЧ в mysqldb?
Когда я запускаю тест, в таблице sqltable появляется новая строка с идентификатором со следующим значением AUTO_INCREMENT, при этом каждый раз передается идентификатор 0.
Сущность
@Data
@Entity
@RequiredArgsConstructor
@NoArgsConstructor(access = AccessLevel.PRIVATE, force = true)
public class Person {
@Id
// @GeneratedValue(strategy = GenerationType.IDENTITY)// use or not - the same effect
private int id;
@NonNull
private String name;
@NonNull
private String surname;
}
Репозиторий
public interface PersonRepository extends CrudRepository<Person, Integer> {
Person findByNameAndSurname(String name, String surname);
}
Тестирование
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringRestInventoryPersistenceTests {
@Autowired
private PersonRepository personRepository;
@Test
public void personPersist() {
Person person = new Person("John", "Smith");
assertTrue(person.getId() == 0);
personRepository.save(person);
assertTrue(person.getId() == 0);
Person person2 = personRepository.findByNameAndSurname("John", "Smith");
assertEquals(person.getName(), person2.getName());
}//test passed
Таблица MySQL
CREATE TABLE `person` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) NOT NULL,
`surname` varchar(20) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=21 DEFAULT CHARSET=utf8
Комментарии:
1. Из-за назначенного по умолчанию генератора
2. Ваш тест никогда не проверяет, что у вашего объекта есть идентификатор, в чем весь смысл GeneratedValue .
3. Как следует из предыдущего комментария, пожалуйста, добавьте утверждение перед сохранением, что идентификатор для person равен 0, и утверждение после сохранения, что оно не равно 0. Вероятно, вы обнаружите, что вам нужна аннотация. Если нет, это все равно хорошая практика для переносимости.
Ответ №1:
Я также столкнулся с той же проблемой, я добавил генератор последовательностей в БД, скажем, «IdGenerator», а затем добавить
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator="idGenerator")
,
@SequenceGenerator(name='dbname' , sequenceName="idGenerator")
Это будет принимать значения из генератора последовательностей, созданного в БД
Ответ №2:
Я понял причину такого поведения. Без аннотации @GeneratedValue идентификатор не генерируется автоматически, а идентификатор со значением 0 всегда передается в базу данных mysql. В этом случае mysql генерирует значение идентификатора из AUTO_INCREMENT. Это поведение по умолчанию.
Чтобы отключить это поведение, вы можете установить следующий параметр:
УСТАНОВИТЬ SQL_MODE=’NO_AUTO_VALUE_ON_ZERO’
Затем после второго вызова метода тестирования personPersist() мы получаем ошибку. В этом случае мы не можем сгенерировать идентификатор в базе данных mysql без аннотации @GeneratedValue.