В предыдущей главе я подробно рассказал вам об основах объектно-реляционного отображения (Object-Relational Mapping — ORM), которое по сути является отображением сущностей в таблицах и атрибутов в столбцах. Я также поведал вам о конфигурации в порядке исключения, которая позволяет поставщику JPA отображать сущность в таблицу базы данных с использованием всех правил по умолчанию. Однако такие правила не всегда оказываются подходящими, особенно если вы отображаете свою доменную модель в существующую базу данных. JPA сопутствует богатый набор метаданных, благодаря чему вы можете настраивать отображение.
В этой главе я рассмотрю элементарное отображение, а также сконцентрируюсь на более сложных отображениях, таких как отображение связей, композиции и наследования. Доменная модель состоит из объектов, которые взаимодействуют друг с другом. У объектов и баз данных имеются разные способы сохранения информации о связях (ссылок в объектах и внешних ключей в базах данных). Наследование не является чертой, которая от природы имеется у реляционных баз данных, и, следовательно, отображение не столь очевидно. В этой главе я тщательно разберу некоторые подробности и приведу примеры, демонстрирующие то, как следует отображать атрибуты, связи и наследования из доменной модели в базе данных.
Элементарное отображение
Способ, которым Java обрабатывает данные, значительно отличается, если сравнивать его с подходом к обработке информации, используемым реляционными базами данных. В случае с Java мы применяем классы для описания как атрибутов для размещения данных, так и методов для доступа и манипулирования данными. Определив класс, мы можем создать столько его экземпляров, сколько нам потребуется, указав ключевое слово new. В реляционной базе данных информация хранится в структурах (столбцах и строках), не являющихся объектными, а динамическое поведение представляет собой хранимую функциональность вроде триггеров таблиц и хранимых процедур, которые не связаны тесно со структурами данных так, как с объектами. Иногда отображение Java-объектов в основной базе данных может быть легким, при этом могут применяться правила по умолчанию. А иной раз эти правила не отвечают вашим нуждам и приходится настраивать отображение. Аннотации элементарного отображения сосредоточены на настройке требуемой таблицы, первичного ключа и столбцов и позволяют вам модифицировать определенные соглашения об именовании или типизацию (речь может идти о не имеющем значения null столбце, длине и т. д.).
Таблицы
Согласно правилам отображения с использованием подхода «конфигурация в порядке исключения» имена сущности и таблицы должны совпадать (сущность Book будет отображаться в таблице BOOK, сущность AncientBook — в таблице ANCIENTBOOK и т. д.). Это, возможно, будет устраивать вас в большинстве ситуаций, однако вам может потребоваться отобразить свои данные в другой таблице или даже отобразить одну сущность в нескольких таблицах.
Аннотация @javax.persistence.Table дает возможность изменять значения по умолчанию, связанные с определенной таблицей. Например, вы можете указать имя таблицы, в которой будут храниться данные, каталог и схему базы данных. Вы также можете определить уникальные ограничения для таблицы с помощью аннотации @UniqueConstraint в сочетании с @Table. Если пренебречь аннотацией @Table, то имя таблицы будет соответствовать имени сущности. Если вы захотите изменить имя с BOOK на T_BOOK, то поступите так, как показано в листинге 5.1.
@Entity
@Table(name = "t_book")
public class Book {
@Id
··private Long id;
··private String title;
··private Float price;
··private String description;
··private String isbn;
··private Integer nbOfPage;
··private Boolean illustrations;
··// Конструкторы, геттеры, сеттеры
}
Я включил в аннотацию @Table имя таблицы в нижнем регистре (t_book). По умолчанию большинство баз данных будут отображать имя сущности в имя таблицы в верхнем регистре (именно так дело обстоит в случае с Derby), если только вы не сконфигурируете их на соблюдение регистра.