Использовать идентификатор объекта JPA без аннотации @GeneratedValue

#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.