1. введение
В этом кратком руководстве мы рассмотрим использование хранимых процедур в Java Persistence API (JPA).
2. Настройка проекта
2.1. Настройка Maven
Сначала нам нужно определить следующие зависимости в вашем pom.xml :
- javax.javaee-api – поскольку он включает в себя API JPA
- реализация API JPA – в этом примере мы будем использовать Hibernate , но EclipseLink также будет приемлемой альтернативой
- a MySQL База данных
7.0 11.2.0.4 5.1.38 javax javaee-api ${jee.version} provided org.hibernate hibernate-core ${hibernate.version} mysql mysql-connector-java ${mysql.version}
2.2. Определение единицы Стойкости
Вторым шагом является создание src/main/resources/META-INF/persistence.xml файл – который содержит определения единиц сохранения:
org.hibernate.jpa.HibernatePersistenceProvider com.baeldung.jpa.model.Car
Все определенные свойства гибернации не нужны, если вы ссылаетесь на источник данных JNDI (среды JEE):
java:jboss/datasources/JpaStoredProcedure
2.3. Сценарий создания таблицы
Давайте теперь создадим Стол ( АВТОМОБИЛЬ ) – с тремя атрибутами: ID, МОДЕЛЬ и ГОД :
CREATE TABLE `car` ( `ID` int(10) NOT NULL AUTO_INCREMENT, `MODEL` varchar(50) NOT NULL, `YEAR` int(4) NOT NULL, PRIMARY KEY (`ID`) ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
Конечно, предполагалось, что схема БД и разрешения уже существуют.
2.4. Создание хранимых процедур в БД
Самым последним шагом перед переходом к коду java является создание хранимой процедуры в нашей базе данных MySQL:
DELIMITER $$ CREATE DEFINER=`root`@`localhost` PROCEDURE `FIND_CAR_BY_YEAR`(in p_year int) begin SELECT ID, MODEL, YEAR FROM CAR WHERE YEAR = p_year; end $$ DELIMITER ;
3. Хранимая процедура JPA
Теперь мы готовы использовать JPA для связи с базой данных и выполнения определенной нами хранимой процедуры.
Как только мы это сделаем, мы также сможем перебирать результаты в виде Списка автомобиля.
3.1. Юридическое Лицо Автомобиля
Под сущностью Car , которая будет сопоставлена с таблицей базы данных CAR менеджером сущностей.
Обратите внимание, что мы также определяем нашу хранимую процедуру непосредственно на объекте с помощью аннотации @NamedStoredProcedureQueries :
@Entity @Table(name = "CAR") @NamedStoredProcedureQueries({ @NamedStoredProcedureQuery( name = "findByYearProcedure", procedureName = "FIND_CAR_BY_YEAR", resultClasses = { Car.class }, parameters = { @StoredProcedureParameter( name = "p_year", type = Integer.class, mode = ParameterMode.IN) }) }) public class Car { private long id; private String model; private Integer year; public Car(String model, Integer year) { this.model = model; this.year = year; } public Car() { } @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "ID", unique = true, nullable = false, scale = 0) public long getId() { return id; } @Column(name = "MODEL") public String getModel() { return model; } @Column(name = "YEAR") public Integer getYear() { return year; } // standard setter methods }
3.2. Доступ к базе данных
Теперь, когда все определено и на месте, давайте напишем пару тестов, фактически использующих JPA для выполнения процедуры.
Мы собираемся вернуть все Автомобили в данный год :
public class StoredProcedureTest { private static EntityManagerFactory factory = null; private static EntityManager entityManager = null; @BeforeClass public static void init() { factory = Persistence.createEntityManagerFactory("jpa-db"); entityManager = factory.createEntityManager(); } @Test public void findCarsByYearWithNamedStored() { StoredProcedureQuery findByYearProcedure = entityManager.createNamedStoredProcedureQuery("findByYearProcedure"); StoredProcedureQuery storedProcedure = findByYearProcedure.setParameter("p_year", 2015); storedProcedure.getResultList() .forEach(c -> Assert.assertEquals(new Integer(2015), ((Car) c).getYear())); } @Test public void findCarsByYearNoNamedStored() { StoredProcedureQuery storedProcedure = entityManager .createStoredProcedureQuery("FIND_CAR_BY_YEAR",Car.class) .registerStoredProcedureParameter(1, Integer.class, ParameterMode.IN) .setParameter(1, 2015); storedProcedure.getResultList() .forEach(c -> Assert.assertEquals(new Integer(2015), ((Car) c).getYear())); } }
Обратите внимание, что во втором тесте мы больше не используем хранимую процедуру, которую мы определили для сущности . Вместо этого мы определяем процедуру с нуля.
Это может быть очень полезно, когда вам нужно использовать хранимые процедуры, но у вас нет возможности изменить свои сущности и перекомпилировать их.
4. Заключение
В этом уроке мы обсуждали использование хранимой процедуры с API сохранения Java.
Пример, используемый в этой статье, доступен в качестве примера проекта в GitHub .