Статьи

Учебник JPA: Составление карт сущностей — часть 1

В этой статье я расскажу о процедуре сопоставления сущностей в JPA. Что касается моих примеров, я буду использовать ту же схему, что и в одной из моих предыдущих статей .

В двух моих предыдущих статьях я объяснил, как настроить JPA в среде Java SE. Я не собираюсь писать процедуру установки для веб-приложения, потому что большинство обучающих программ в Интернете делают именно это. Итак, давайте перейдем непосредственно к объектному реляционному сопоставлению или сопоставлению сущностей

Википедия определяет реляционное сопоставление объектов следующим образом:

Объектно-реляционное отображение (ORM, O / RM и O / R mapping) в информатике — это метод программирования для преобразования данных между несовместимыми системами типов в объектно-ориентированных языках программирования. По сути, это создает «базу данных виртуальных объектов», которую можно использовать из языка программирования. Доступны как бесплатные, так и коммерческие пакеты, которые выполняют объектно-реляционное отображение, хотя некоторые программисты предпочитают создавать свои собственные инструменты ORM.

Как правило, отображение — это процесс, посредством которого вы предоставляете необходимую информацию о вашей базе данных в инструмент ORM. Затем инструмент использует эту информацию для чтения / записи объектов в базу данных. Обычно вы указываете своему инструменту ORM имя таблицы, в которую будет сохранен объект определенного типа. Вы также предоставляете имена столбцов, которым будут сопоставлены свойства объекта. Отношения между различными типами объектов также должны быть указаны. Все эти задачи кажутся множеством задач, но, к счастью, JPA следует так называемому подходу «Соглашение о конфигурации», что означает, что если вы примете использовать значения по умолчанию, предоставляемые JPA, вам придется настраивать очень маленькие части вашего Приложения.

Чтобы правильно отобразить тип в JPA, вам необходимо сделать следующее:

  1. Пометьте свой класс аннотацией @Entity. Эти классы называются сущностями.
  2. Отметьте один из методов свойства / получателя класса с помощью аннотации @Id.

Вот и все. Ваши объекты готовы для сохранения в базе данных, потому что JPA автоматически настраивает все другие аспекты отображения. Это также показывает увеличение производительности, которое вы можете получить, используя JPA. Вам не нужно вручную заполнять ваши объекты каждый раз, когда вы запрашиваете базу данных, что избавляет вас от написания большого количества стандартного кода.

Давайте посмотрим на пример. Рассмотрим следующую сущность 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
import javax.persistence.Entity;
import javax.persistence.Id;
 
@Entity
public class Address {
  @Id
  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;
  }
}

Теперь, основываясь на вашей среде, вы можете или не можете добавить это объявление сущности в свой файл persistence.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
import com.keertimaan.javasamples.jpaexample.entity.Address;
import javax.persistence.EntityManager;
import com.keertimaan.javasamples.jpaexample.persistenceutil.PersistenceManager;
 
public class Main {
  public static void main(String[] args) {
    EntityManager em = PersistenceManager.INSTANCE.getEntityManager();
 
    Address address = new Address().setId(1)
        .setCity("Dhaka")
        .setCountry("Bangladesh")
        .setPostcode("1000")
        .setStreet("Poribagh");
    em.getTransaction()
        .begin();
    em.persist(address);
    em.getTransaction()
        .commit();
    System.out.println("addess is saved! It has id: " + address.getId());
 
    Address anotherAddress = new Address().setId(2)
        .setCity("Shinagawa-ku, Tokyo")
        .setCountry("Japan")
        .setPostcode("140-0002")
        .setStreet("Shinagawa Seaside Area");
    em.getTransaction()
        .begin();
    em.persist(anotherAddress);
    em.getTransaction()
        .commit();
    em.close();
    System.out.println("anotherAddress is saved! It has id: " + anotherAddress.getId());
 
    PersistenceManager.INSTANCE.close();
  }
}

Давайте сделаем шаг назад и подумаем, что нам нужно было сделать, если бы мы использовали простой JDBC для настойчивости. Нам пришлось вручную писать запросы вставки и отображать каждый из атрибутов в соответствующие столбцы для обоих случаев, что потребовало бы большого количества кода.

Важный момент, на который следует обратить внимание в этом примере, — это способ установки идентификатора сущностей. Этот подход будет работать только для коротких примеров, подобных этому, но для реальных приложений это не хорошо. Как правило, вы хотите использовать, скажем, автоматически увеличивающиеся столбцы идентификаторов или последовательности базы данных для генерации значений идентификаторов для ваших сущностей. В моем примере я использую базу данных MySQL, и все мои столбцы идентификаторов настроены на автоматическое увеличение. Чтобы отразить это в моей модели сущностей, я могу использовать дополнительную аннотацию под названием @GeneratedValue в свойстве id. Это сообщает JPA, что значение id для этого объекта будет автоматически сгенерировано базой данных во время вставки, и он должен извлечь этот идентификатор после вставки, используя команду select.

С вышеуказанными модификациями мой класс сущности становится примерно таким:

01
02
03
04
05
06
07
08
09
10
11
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.GeneratedValue;
 
@Entity
public class Address {
  @Id
  @GeneratedValue
  private Integer id;
 
  // Rest of the class code........

И процедура вставки становится такой:

01
02
03
04
05
06
07
08
09
10
Address anotherAddress = new Address()
    .setCity("Shinagawa-ku, Tokyo")
    .setCountry("Japan")
    .setPostcode("140-0002")
    .setStreet("Shinagawa Seaside Area");
em.getTransaction()
    .begin();
em.persist(anotherAddress);
em.getTransaction()
    .commit();

Как JPA выяснил, какую таблицу использовать для сохранения объектов Address? Оказывается, это довольно просто:

  1. Когда в отображении нет явной информации о таблице, JPA пытается найти таблицу, имя которой совпадает с именем сущности.
  2. Имя объекта может быть явно указано с помощью атрибута «name» аннотации @Entity. Если атрибут name не найден, JPA предполагает имя по умолчанию для объекта.
  3. По умолчанию имя объекта — это простое имя (не полностью определенное имя) класса объекта, в нашем случае это Address. Таким образом, имя нашей сущности определяется как «Адрес».
  4. Поскольку имя нашей сущности — «Адрес», JPA пытается найти, есть ли в базе данных таблица с именем «Адрес» (помните, что в большинстве имен таблиц базы данных дел регистр не учитывается). Из нашей схемы мы видим, что это действительно так.

Итак, как JPA выяснил, какие столбцы использовать для сохранения значений свойств для объектов адреса?

На данный момент, я думаю, вы сможете легко догадаться об этом. Если вы не можете, следите за обновлениями моего следующего поста!

До скорого.

[Полный рабочий код можно найти на github .]