Упорство Полиглота было в новостях с некоторого времени. Начатый знаменитой записью Фаулера с конца 2011 года, я вижу еще более интересные идеи. Последним был внутренний студенческий проект компании, в котором мы использовали Scala в качестве бэкэнда, сохраняющего данные в MongoDB, Derby и Solar. Я не большой поклонник Scala и вспомнил растущую поддержку EclipseLink для баз данных NoSQL. Учитывая, что я просто должен был попробовать это.
Когда начать?
Самая большая проблема — недостающие примеры. Вы найдете совсем немного о том, как изменить контейнеры данных (NoSQL или RDBMS) с EclipseLink, но вы не найдете ни одного, который бы точно использовал обе технологии без проблем. Благодаря Шону Смиту и Гуннару Вагенкрнехту у нас есть замечательная беседа на JavaOne о постоянстве Polyglot: EclipseLink JPA для NoSQL, Relational и Beyond, которая говорит именно об этом. К сожалению, источники до сих пор нигде не были переданы, и мне пришлось восстановить это из беседы. Так, кредиты идут для Шона и Гуннара для этого.
Волшебное решение называется « Персональная композиция» . Вам нужен один блок персистентности для каждого контейнера данных. Это выглядит как следующий основной пример. У вас есть пара сущностей в каждом PU, и композитный PU является зонтиком.
Поехали
Вы должны иметь MongoDB на месте, прежде чем вы начнете этот маленький учебник пример. Запустите NetBeans и создайте два Java-проекта. Давайте назовем их polyglot-persistence-nosql-pu и polyglot-persistence -ational-pu. Поместите следующие объекты в nosql-pu: Customer, Address, Order и OrderLine. (В основном взяты из
EclipseLink nosql examples ) и поместите сущность Product в рациональный-pu.
Отдельные продукты поступают в Дерби, а все остальные объекты сохраняются в MongoDB. Интересная часть, где OrderLine имеет отношение один к одному с продуктом:
|
1
2
|
@OneToOne(cascade = {CascadeType.REMOVE, CascadeType.PERSIST})private Product product; |
Это точка, где оба мира объединяются. Подробнее об этом позже.
Оба PU должны иметь тип транзакции = ‘RESOURCE_LOCAL’ и должны содержать следующую строку в файле persistence.xml:
|
1
|
<property name='eclipselink.composite-unit.member' value='true'/> |
Не забудьте добавить конкретную конфигурацию БД. Для MongoDB это
|
1
2
3
|
<property name='eclipselink.nosql.property.mongo.port' value='27017'/><property name='eclipselink.nosql.property.mongo.host' value='localhost'/><property name='eclipselink.nosql.property.mongo.db' value='mydb'/> |
Для дерби это примерно так:
|
1
2
3
4
|
<property name='javax.persistence.jdbc.url' value='jdbc:derby://localhost:1527/mydb'/><property name='javax.persistence.jdbc.password' value='sa'/><property name='javax.persistence.jdbc.driver' value='org.apache.derby.jdbc.ClientDriver'/><property name='javax.persistence.jdbc.user' value='sa'/> |
Теперь нам нужно что-то, чтобы связать эти два PU вместе. Комбинированный pu находится в образце модуля polyglot-persistence-web и выглядит так:
|
1
2
3
4
5
6
7
8
9
|
<persistence-unit name='composite-pu' transaction-type='RESOURCE_LOCAL'> <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider> <jar-file>\lib\polyglot-persistence-rational-pu-1.0-SNAPSHOT.jar</jar-file> <jar-file>\lib\polyglot-persistence-nosql-pu-1.0-SNAPSHOT.jar</jar-file> <properties> <property name='eclipselink.composite-unit' value='true'/> </properties></persistence-unit></persistence> |
Не упустите путь к файлу jar. Мы собираемся упаковать это в военный архив, и поэтому nosql-pu иational-pu перейдут в папку WEB-INF / lib. Как видите, мой пример — сборка с maven. Убедитесь, что вы используете последнюю зависимость EclipseLink. Даже GlassFish 3.1.2.2 все еще поставляется с более низкой версией. Поддержка MongoDB была добавлена начиная с 2.4.
|
1
2
3
4
5
|
<dependency> <groupId>org.eclipse.persistence</groupId> <artifactId>eclipselink</artifactId> <version>2.4.1</version> </dependency> |
Кроме того, вам также необходимо перевернуть загрузчики классов GlassFish:
|
1
|
<class-loader delegate='false'/> |
Не беспокойся о деталях. Я все ставлю на
github.com/myfear так что вы можете сами в дальнейшем разобраться в полном примере.
Тестирование это
Давайте сделаем несколько очень кратких испытаний с ним. Создайте симпатичный маленький сервлет Демо и вставьте в него составной пу. Создайте EntityManager из него и получите транзакцию. Теперь начните создавать продукты, клиента, заказ и отдельные строки заказа. Все просто JPA. Больше никакой магии здесь:
|
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
|
@PersistenceUnit(unitName = 'composite-pu') private EntityManagerFactory emf;protected void processRequest() // [...] { EntityManager em = emf.createEntityManager(); em.getTransaction().begin(); // Products go into RDBMS Product installation = new Product('installation'); em.persist(installation); Product shipping = new Product('shipping'); em.persist(shipping); Product maschine = new Product('maschine'); em.persist(maschine); // Customer into NoSQL Customer customer = new Customer(); customer.setName('myfear'); em.persist(customer); // Order into NoSQL Order order = new Order(); order.setCustomer(customer); order.setDescription('Pinball maschine'); // Order Lines mapping NoSQL --- RDBMS order.addOrderLine(new OrderLine(maschine, 2999)); order.addOrderLine(new OrderLine(shipping, 59)); order.addOrderLine(new OrderLine(installation, 129)); em.persist(order); em.getTransaction().commit(); String orderId = order.getId(); em.close(); |
Если вы установите правильные свойства ведения журнала, вы увидите, что происходит:
Пара последовательностей присваивается созданным объектам Product (GeneratedValue). Сущность Customer сохраняется в Mongo с MappedInteraction. Объекты отображаются на коллекции в MongoDB.
|
1
2
3
4
5
6
|
FINE: Executing MappedInteraction()spec => nullproperties => {mongo.collection=CUSTOMER, mongo.operation=INSERT}input => [DatabaseRecord(CUSTOMER._id => 5098FF0C3D9F5D2CCB3CFECFCUSTOMER.NAME => myfear)] |
После этого вы видите, что продукты вставляются в Derby и снова MappedInteraction, который перетаскивает Заказ в MongoDB. Действительно крутая часть внизу на линии заказов:
|
01
02
03
04
05
06
07
08
09
10
|
ORDER.ORDERLINES => [DatabaseRecord( LINENUMBER => 1 COST => 2999.0 PRODUCT_ID => 3), DatabaseRecord( LINENUMBER => 2 COST => 59.0 PRODUCT_ID => 2), DatabaseRecord( LINENUMBER => 3 COST => 129.0 PRODUCT_ID => 1)] |
У строк заказа есть объект, у которого есть product_id, который был создан для связанных сущностей продукта. В дальнейшем вы также можете найти соответствующий Заказ и перебрать товары и получить их описания:
|
1
|
Order order2 = em.find(Order.class, orderId); |
|
1
2
3
|
for (OrderLine orderLine : order2.getOrderLines()) { String desc = orderLine.getProduct().getDescription(); } |
Хорошая маленькая демонстрация выглядит так:
Спасибо Шон, спасибо Гуннар за этот хороший маленький пример. Теперь зайдите на github.com/myfear и запачкайте руки 🙂
Ссылка: Постоянство Polyglot: EclipseLink с MongoDB и Derby от нашего партнера по JCG Маркуса Эйзела (Markus Eisele) из блога Enterprise Software Development с Java .


