ВЪВЕДЕТЕ изявление в JPA

1. Общ преглед

В този бърз урок ще научим как да изпълним INSERT израз върху JPA обекти .

За повече информация относно хибернацията като цяло, вижте нашето изчерпателно ръководство за JPA с пролет и въведение в Spring Data с JPA за дълбоки гмуркания в тази тема.

2. Персистиращи обекти в JPA

В JPA всеки обект, преминаващ от преходно към управлявано състояние, се обработва автоматично от EntityManager .

На EntityManager проверява дали дадено лице вече съществува и след това да реши дали трябва да се добавят или актуализирани. Поради това автоматично управление, т той само изявления, позволени от JPA са SELECT, UPDATE и DELETE.

В примерите по-долу ще разгледаме различни начини за управление и заобикаляне на това ограничение.

3. Определяне на общ модел

Сега нека започнем с дефиниране на прост обект, който ще използваме в този урок:

@Entity public class Person { @Id private Long id; private String firstName; private String lastName; // standard getters and setters, default and all-args constructors }

Също така, нека дефинираме клас на хранилище, който ще използваме за нашите реализации:

@Repository public class PersonInsertRepository { @PersistenceContext private EntityManager entityManager; }

Освен това ще приложим анотацията @Transactional за автоматично обработване на транзакции до пролетта. По този начин няма да се притесняваме за създаването на транзакции с нашия EntityManager, извършването на промените ни или извършването на откат ръчно в случай на изключение.

4. createNativeQuery

За ръчно създадени заявки можем да използваме метода EntityManager # createNativeQuery . Позволява ни да създаваме всякакъв тип SQL заявки, не само такива, поддържани от JPA. Нека добавим нов метод към нашия клас на хранилище:

@Transactional public void insertWithQuery(Person person) { entityManager.createNativeQuery("INSERT INTO person (id, first_name, last_name) VALUES (?,?,?)") .setParameter(1, person.getId()) .setParameter(2, person.getFirstName()) .setParameter(3, person.getLastName()) .executeUpdate(); }

С този подход трябва да дефинираме буквална заявка, включваща имена на колоните и да зададем съответните им стойности.

Вече можем да тестваме нашето хранилище:

@Test public void givenPersonEntity_whenInsertedTwiceWithNativeQuery_thenPersistenceExceptionExceptionIsThrown() { Person person = new Person(1L, "firstname", "lastname"); assertThatExceptionOfType(PersistenceException.class).isThrownBy(() -> { personInsertRepository.insertWithQuery(PERSON); personInsertRepository.insertWithQuery(PERSON); }); }

В нашия тест всяка операция се опитва да вмъкне нов запис в нашата база данни. Тъй като се опитахме да вмъкнем две обекти с един и същ идентификатор , втората операция за вмъкване се проваля, като хвърля PersistenceException .

Принципът тук е същият, ако използваме @Query на Spring Data .

5. упорстват

В предишния ни пример създадохме заявки за вмъкване, но трябваше да създадем буквални заявки за всеки обект. Този подход не е много ефективен и води до много примерни кодове.

Вместо това можем да използваме метода persist от EntityManager .

Както в нашия предишен пример, нека разширим нашия клас на хранилище с персонализиран метод:

@Transactional public void insertWithEntityManager(Person person) { this.entityManager.persist(person); }

Сега можем да тестваме отново нашия подход :

@Test public void givenPersonEntity_whenInsertedTwiceWithEntityManager_thenEntityExistsExceptionIsThrown() { assertThatExceptionOfType(EntityExistsException.class).isThrownBy(() -> { personInsertRepository.insertWithEntityManager(new Person(1L, "firstname", "lastname")); personInsertRepository.insertWithEntityManager(new Person(1L, "firstname", "lastname")); }); }

За разлика от използването на собствени заявки, ние не трябва да посочваме имена на колони и съответни стойности . Вместо това EntityManager се справя с това вместо нас.

В горния тест очакваме също да бъде хвърлен EntityExistsException вместо неговия суперклас PersistenceException, който е по-специализиран и изхвърлен от persist .

От друга страна, в този пример трябва да сме сигурни, че извикваме метода за вмъкване всеки път с нов екземпляр на Person. В противен случай той вече ще се управлява от EntityManager, което води до операция по актуализиране.

6. Заключение

В тази статия илюстрирахме начини за извършване на операции за вмъкване на JPA обекти. Разгледахме примери за използване на собствена заявка, както и използване на EntityManager # persist за създаване на потребителски INSERT изрази.

Както винаги, пълният код, използван в тази статия, е достъпен в GitHub.