Статьи

Учебник JPA — Настройка JPA в среде Java SE

JPA расшифровывается как Java Persistence API, который в основном представляет собой спецификацию, описывающую способ сохранения данных в постоянном хранилище, обычно в базе данных. Мы можем думать о нем как о чем-то похожем на инструменты ORM , такие как Hibernate , за исключением того, что это официальная часть спецификации Java EE (и она также поддерживается в Java SE). Есть много причин изучать инструмент ORM, такой как JPA. Я не буду вдаваться в подробности этого, потому что в Интернете уже есть много постов, которые прекрасно отвечают на этот вопрос, например, этот или этот . Однако мы также должны помнить, что это не единственная волшебная пуля, которая решит все наши проблемы.
Когда я только начинал с JPA, у меня были реальные трудности с его настройкой, потому что большинство статей в Интернете написаны только для среды Java EE, тогда как я пытался использовать ее в среде Java SE. Я надеюсь, что эта статья будет полезна для тех, кто хочет сделать то же самое в будущем.
В этом примере мы будем использовать Maven для настройки наших необходимых зависимостей. Поскольку JPA является только спецификацией, нам также потребуется реализация. Есть много хороших реализаций JPA, доступных бесплатно (например, EclipseLink, Hibernate и т. Д.). Для этой статьи я решил использовать Hibernate. Что касается базы данных, я буду использовать MySQL. Давайте сначала создадим простой проект Maven. Я создал мой, используя быстрый старт архетипа из командной строки. Если вы не знаете, как это сделать, вы можете следовать этому руководству .
Хорошо, давайте теперь получим зависимости для JPA. Включите в ваш файл pom.xml следующие строки:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
<dependency>
  <groupId>javax.persistence</groupId>
  <artifactId>persistence-api</artifactId>
  <version>1.0.2</version>
</dependency>
<dependency>
  <groupId>org.hibernate</groupId>
  <artifactId>hibernate-entitymanager</artifactId>
  <version>4.3.6.Final</version>
  <exclusions>
    <exclusion>
      <groupId>org.hibernate.javax.persistence</groupId>
      <artifactId>hibernate-jpa-2.1-api</artifactId>
    </exclusion>
  </exclusions>
</dependency>

Первая зависимость определяет стандартный интерфейс JPA, а вторая — реализацию. Включение зависимостей JPA таким способом желательно, поскольку оно дает нам свободу без особых проблем переключать реализацию, специфичную для поставщика, в будущем ( подробности см. Здесь ). Однако мы не сможем использовать последнюю версию API таким образом, потому что версия API 1.0.2 является последней версией, выпущенной как независимый JAR. На момент написания этой статьи последняя версия спецификации JPA была 2.1, которая не доступна независимо (хотя есть много запросов на это). Если мы хотим использовать его сейчас, то единственными возможными вариантами являются выбор JAR-файла для конкретного поставщика или использование сервера приложений, который предоставляет API вместе с его реализацией. Я решил использовать спецификацию API, предоставленную Hibernate. В этом случае будет достаточно только следующей зависимости:

1
2
3
4
5
<dependency>
  <groupId>org.hibernate</groupId>
  <artifactId>hibernate-entitymanager</artifactId>
  <version>4.3.6.Final</version>
</dependency>

Следующим шагом является включение зависимости для MySQL. Включите в ваш файл pom.xml следующие строки:

1
2
3
4
5
<dependency>
  <groupId>mysql</groupId>
  <artifactId>mysql-connector-java</artifactId>
  <version>5.1.31</version>
</dependency>

После включения остальных зависимостей (например, jUnit, Hamcrest и т. Д.) Полный файл pom.xml выглядит следующим образом:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
 
  <modelVersion>4.0.0</modelVersion>
 
  <groupId>com.keertimaan.javasamples</groupId>
  <artifactId>jpa-example</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>
 
  <name>jpa-example</name>
  <url>http://www.codesod.com</url>
 
  <properties>
    <java.version>1.8</java.version>
    <hibernate.version>4.3.6.Final</hibernate.version>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>
 
  <dependencies>
    <!-- JPA -->
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-entitymanager</artifactId>
      <version>${hibernate.version}</version>
    </dependency>
 
    <!-- For connection pooling -->
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-c3p0</artifactId>
      <version>${hibernate.version}</version>
    </dependency>
 
    <!-- Database -->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.31</version>
    </dependency>
 
    <!-- Test -->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
      <exclusions>
        <exclusion>
          <groupId>org.hamcrest</groupId>
          <artifactId>hamcrest-core</artifactId>
        </exclusion>
      </exclusions>
    </dependency>
    <dependency>
      <groupId>org.hamcrest</groupId>
      <artifactId>hamcrest-all</artifactId>
      <version>1.3</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
 
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>2.5.1</version>
        <configuration>
          <source>${java.version}</source>
          <target>${java.version}</target>
          <compilerArgument>-Xlint:all</compilerArgument>
          <showWarnings>true</showWarnings>
          <showDeprecation>true</showDeprecation>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

Теперь пришло время настроить нашу базу данных. Я буду использовать следующую схему во всех моих будущих примерах JPA, которые я нашел из этой превосходной онлайн-книги :

Схема базы данных

Схема базы данных

Создайте эквивалентную базу данных, следуя приведенной выше схеме в вашей локальной установке MySQL. Нашим следующим шагом будет создание файла persistence.xml, который будет содержать информацию о нашей базе данных для использования JPA. По умолчанию JPA ожидает, что этот файл находится в пути к классам в папке META-INF . Для нашего проекта maven я создал этот файл в папке project_root / src / main / resources / META-INF :

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
 
 
  version="2.1">
 
  <persistence-unit name="jpa-example" transaction-type="RESOURCE_LOCAL">
  <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
 
  <properties>
    <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost/jpa_example" />
    <property name="javax.persistence.jdbc.user" value="root" />
    <property name="javax.persistence.jdbc.password" value="my_root_password" />
    <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />
 
    <property name="hibernate.show_sql" value="true" />
    <property name="hibernate.format_sql" value="true" />
    <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect" />
    <property name="hibernate.hbm2ddl.auto" value="validate" />
 
    <!-- Configuring Connection Pool -->
    <property name="hibernate.c3p0.min_size" value="5" />
    <property name="hibernate.c3p0.max_size" value="20" />
    <property name="hibernate.c3p0.timeout" value="500" />
    <property name="hibernate.c3p0.max_statements" value="50" />
    <property name="hibernate.c3p0.idle_test_period" value="2000" />
    </properties>
  </persistence-unit>
</persistence>

Приведенный выше файл требует некоторых объяснений, если вы являетесь абсолютным новичком в JPA. В моей следующей статье я постараюсь объяснить это как можно больше, но для запуска этого примера вам потребуется изменить только первые три значения свойств в соответствии с вашей средой (а именно: имя базы данных, имя пользователя и пароль). Также запомните значение атрибута name элемента persistence-unit . Это значение будет использовано для создания экземпляра нашего экземпляра EntityManagerFactory позже в коде.
Хорошо, теперь давайте создадим объект для проверки нашей конфигурации. Создайте класс с именем Address со следующим содержимым:

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
 
@Entity
@Table(name = "address")
public class Address {
  @Id
  @GeneratedValue
  private Integer id;
 
  private String street;
  private String city;
  private String province;
  private String country;
  private String postcode;
 
  /**
   * @return the id
   */
  public Integer getId() {
    return id;
  }
 
  /**
   * @param id the id to set
   */
  public Address setId(Integer id) {
    this.id = id;
    return this;
  }
 
  /**
   * @return the street
   */
  public String getStreet() {
    return street;
  }
 
  /**
   * @param street the street to set
   */
  public Address setStreet(String street) {
    this.street = street;
    return this;
  }
 
  /**
   * @return the city
   */
  public String getCity() {
    return city;
  }
 
  /**
   * @param city the city to set
   */
  public Address setCity(String city) {
    this.city = city;
    return this;
  }
 
  /**
   * @return the province
   */
  public String getProvince() {
    return province;
  }
 
  /**
   * @param province the province to set
   */
  public Address setProvince(String province) {
    this.province = province;
    return this;
  }
 
  /**
   * @return the country
   */
  public String getCountry() {
    return country;
  }
 
  /**
   * @param country the country to set
   */
  public Address setCountry(String country) {
    this.country = country;
    return this;
  }
 
  /**
   * @return the postcode
   */
  public String getPostcode() {
    return postcode;
  }
 
  /**
   * @param postcode the postcode to set
   */
  public Address setPostcode(String postcode) {
    this.postcode = postcode;
    return this;
  }
}

Этот класс был правильно сопоставлен с адресной таблицей, и его экземпляры полностью готовы для сохранения в базе данных. Теперь давайте создадим вспомогательный класс с именем PersistenceManager со следующим содержимым:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
 
public enum PersistenceManager {
  INSTANCE;
 
  private EntityManagerFactory emFactory;
 
  private PersistenceManager() {
    // "jpa-example" was the value of the name attribute of the
    // persistence-unit element.
    emFactory = Persistence.createEntityManagerFactory("jpa-example");
  }
 
  public EntityManager getEntityManager() {
    return emFactory.createEntityManager();
  }
 
  public void close() {
    emFactory.close();
  }
}

Теперь давайте напишем пример кода персистентности в нашем методе Main, чтобы проверить все:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
import javax.persistence.EntityManager;
 
public class Main {
  public static void main(String[] args) {
    Address address = new Address();
    address.setCity("Dhaka")
        .setCountry("Bangladesh")
        .setPostcode("1000")
        .setStreet("Poribagh");
 
    EntityManager em = PersistenceManager.INSTANCE.getEntityManager();
    em.getTransaction()
        .begin();
    em.persist(address);
    em.getTransaction()
        .commit();
 
    em.close();
    PersistenceManager.INSTANCE.close();
  }
}

Если вы проверите свою базу данных, вы увидите, что новая запись была вставлена ​​в вашу адресную таблицу. В этой статье объясняется, как настроить JPA без использования каких-либо других сред, таких как Spring. Однако для настройки JPA очень хорошая идея использовать Spring, поскольку в этом случае нам не нужно беспокоиться об управлении менеджерами сущностей, транзакциями и т. Д. Помимо настройки JPA, Spring также очень хорош для многих других целей . Вот и все на сегодня. В следующей статье я постараюсь максимально подробно объяснить файл persistence.xml и соответствующие значения конфигурации. Будьте на связи!

  • Полный код можно найти на github .
Ссылка: Учебник JPA — Настройка JPA в среде Java SE от нашего партнера по JCG Саима Ахмеда из блога Codesod .