Customer customer = new Customer("Энтони", "Балла", "[email protected]");
Address address = new Address("Ризердаун Роуд", "Лондон", "8QE", "Англия");
customer.setAddress(address);
tx.begin();
em.persist(customer);
em.persist(address);
tx.commit();
assertNotNull(customer.getId());
assertNotNull(address.getId());
В листинге 6.7 customer и address — это всего лишь два объекта, которые располагаются в памяти виртуальной машины Java. Они оба станут сущностями, которые находятся под управлением, когда менеджер сущностей (переменная em) примет их в расчет, обеспечив постоянство (em.persist(customer)). На данном этапе оба объекта окажутся подходящими для вставки в базу данных. Когда произойдет фиксация транзакции (tx.commit()), информация будет сброшена в базу данных, строка, касающаяся адреса, будет вставлена в таблицу ADDRESS, а строка, которая касается клиента, — в таблицу CUSTOMER. Поскольку Customer является владельцем связи, его таблица содержит внешний ключ, ссылающийся на ADDRESS. Выражения assertNotNull обеспечат проверку того, что обе сущности получили сгенерированные идентификаторы (благодаря поставщику постоянства, а также аннотациям @Id и @GeneratedValue).
Обратите внимание на порядок методов persist(): сначала обеспечивается постоянство Customer, а затем — постоянство Address. Если бы этот порядок был иным, то результат все равно оказался бы тем же. Ранее менеджер сущностей был охарактеризован как кэш первого уровня. Пока не произойдет фиксации транзакции, данные остаются в памяти, а доступ к базе данных отсутствует. Менеджер сущностей кэширует данные и, когда готов, сбрасывает их в том порядке, в каком ожидает основная база данных (с соблюдением ограничений целостности). Поскольку внешний ключ располагается в таблице CUSTOMER, сначала будет выполнен оператор insert для ADDRESS, а затем — для CUSTOMER.
Большинство сущностей в этой главе не реализуют интерфейс Serializable. Причина этого заключается в том, что сущностям не требуется быть сериализуемыми для того, чтобы оказалось возможным обеспечение их постоянства в базе данных. Они передаются по ссылке от одного метода к другому, и, когда необходимо обеспечить их постоянство, вызывается метод EntityManager.persist(). Но если вам потребуется передать сущности по значению (удаленный вызов, внешний EJB-контейнер и т. д.), то они должны будут реализовывать маркерный (не содержащий методов) интерфейс java.io.Serializable. Этот интерфейс говорит компилятору, что он должен позаботиться о том, чтобы все поля, связанные с классом-сущностью, обязательно были сериализуемыми. Благодаря этому любой экземпляр можно будет сериализовать в байтовый поток и передать с использованием удаленного вызова методов (Remote Method Invocation — RMI).
Для поиска сущности по ее идентификатору вы можете использовать два метода. Первый — EntityManager.find(), имеющий два параметра: класс-сущность и уникальный идентификатор (листинг 6.8). Если сущность удастся найти, то она будет возвращена; если сущность не удастся найти, то будет возвращено значение null.
Customer customer = em.find(Customer.class, 1234L)
if (customer!= null) {
··// Обработать объект
}