это добавить или изменить функциональность, не влияя на существующую функциональность ядра системы.
Давайте возьмем простой пример. Предположим, у вашей компании есть основной продукт для отслеживания всех пользователей в спортивном клубе. В вашей архитектуре продукта у вас есть модель предметной области, представленная JPA POJO. Модель предметной области содержит много POJO, включая, конечно, User POJO.
|
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
|
package com.alex.staveley.persistence/** * User entity. Represents Users in the Sports Club. * * Note: The SQL to generate a table for this in MySQL is: * * CREATE TABLE USER (ID INT NOT NULL auto_increment, NAME varchar(255) NOT NULL, * PRIMARY KEY (ID)) ENGINE=InnoDB; */@Entitypublic class User { /* Surrogate Key - automatically generated by DB. */ @GeneratedValue(strategy=GenerationType.IDENTITY) @Id private int id; private String name; public int getId() { return id; } public void setName(String name) { this.name=name; } public String getName() { return name; }} |
Некоторым покупателям нравится ваш продукт, но перед покупкой им необходимо выполнить некоторые настройки. Например,
один клиент хочет, чтобы атрибут места рождения был добавлен к пользователю и хотел, чтобы это сохранялось Логическое место для этого атрибута — конечно — в пользовательском POJO, но ни один другой клиент не хочет этот атрибут. Ну так что ты делаешь?
Вы делаете определенный класс User только для этого клиента, а затем меняете его только для них? Что происходит
когда вы меняете класс Product User? Что произойдет, если другой клиент хочет другую настройку?
Или передумает? Вы чувствуете, что все станет грязно?
К счастью, одна реализация JPA: Eclipselink помогает здесь. Выпуск 2.3 (доступный с июня 2011 года, последний выпуск — техническое обслуживание 2.3.2, выпущенное совсем недавно, 9 декабря 2011 года) включает в себя некоторые функции, которые отлично подходят для сценариев этого типа. Давайте уточним. Просто добавив аннотацию @VirtualAccessmethods Eclipselink к POJO, мы сообщаем Eclipselink, что POJO может иметь некоторые дополнительные ( также известные как виртуальные ) атрибуты. Вам не нужно указывать какие-либо из этих дополнительных атрибутов в коде, иначе они не будут очень виртуальными ! Вам просто нужно указать универсальный метод получения и установки для обслуживания их получения и настройки. Вам также нужно где-то хранить их в памяти, что-то вроде старого доброго hashmap, что, конечно, должно быть временным, потому что мы не сохраняем сам hashmap. Примечание: их не нужно хранить в HashMap, это просто популярный выбор!
Давайте посмотрим на нашего обновленного пользователя, который теперь расширяем!
|
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
|
@Entity@VirtualAccessMethodspublic class User { /* Surrogate Key - automatically generated by DB. */ @GeneratedValue(strategy=GenerationType.IDENTITY) @Id private int id; private String name; @Transient private Map<String, Object> extensions = new HashMap(); public int getId() { return id; } public void setName(String name) { this.name=name; } public String getName() { return name; } public <t> T get(String name) { return (T) extensions.get(name); } public Object set(String name, Object value) { return extensions.put(name, value); } } |
Так это все? Ну, есть немного больше магии. Вы должны рассказать eclipselink о ваших дополнительных атрибутах. Более конкретно: каковы их имена и типы данных.
Вы делаете это путем обновления вашего eclipselink-orm.xml, который находится в той же папке META-INF, в которой находится файл persistent.xml.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
|
<?xml version="1.0" encoding="UTF-8"?> xsi:schemaLocation="http://www.eclipse.org/eclipselink/xsds/persistence/orm version="2.1"> <entity class="com.alex.staveley.persistence.User"> <attributes> <basic name="thebirthplace" attribute-type="String" access="VIRTUAL"> <column name="birthplace"/> <access-methods get-method="get" set-method="set"/> </basic> </attributes> </entity> </entity-mappings> |
Теперь эта конфигурация просто утверждает, что у сущности User есть дополнительный атрибут, который в java — «thebirthplace», и он является виртуальным. Это означает, что он не определен явно в POJO, но если бы мы отлаживали вещи, мы увидели бы атрибут с именем «thebirthplace» в памяти.
Эта конфигурация также утверждает, что соответствующий столбец базы данных для атрибута является местом рождения.
И eclipselink может получить и установить этот метод, используя общие методы get / set.
Вы хотите проверить это?
Хорошо добавьте столбец в таблицу базы данных. В MySql это будет:
изменить таблицу пользователя добавить столбец место рождения varchar (64)
Затем запустите этот простой тест:
|
01
02
03
04
05
06
07
08
09
10
|
@Testpublic void testCreateUser() { User user = new User(); user.setName("User1Name"); user.set("thebirthplace", "donabate"); entitymanager.getTransaction().begin(); entitymanager.persist(user); entitymanager.getTransaction().commit(); entitymanager.close();} |
Так что теперь мы можем иметь один пользовательский POJO в нашем коде продукта, который является расширяемым. Каждый клиент может иметь свои собственные атрибуты, добавленные к пользователю — по своему усмотрению. И, конечно же, каждый клиент отделен от
всех остальных клиентов очень легко, просто убедившись, что расширения каждого клиента находятся в определенном файле eclipslink-orm.xml. Помните, что вы можете называть эти файлы по своему усмотрению, и если вы не используете имена по умолчанию, просто обновите файл persistence.xml, чтобы указать, какие имена вы используете .
Этот подход означает, что когда мы хотим обновить Пользователя в нашем продукте, нам нужно обновить только один и только Пользователь POJO ( потому что мы убедились, что есть только один ). Но когда необходимо добавить определенные атрибуты для конкретных клиентов, мы не затрагиваем код POJO пользователя. Мы просто вносим изменения в XML и не должны ничего перекомпилировать из основного продукта. И, конечно же, в любое время легко увидеть, какие настройки есть у любого клиента, просто взглянув на соответствующий файл eclipselink-orm.file.
Вы Ха Счастливого продолжения!
Рекомендации:
- Расширение ваших JPA POJO от нашего партнера JCG Алекса Стейвли в техническом блоге Дублина
- http://wiki.eclipse.org/EclipseLink/UserGuide/JPA/Advanced_JPA_Development/Extensible_Entities
- http://www.eclipse.org/eclipselink/
Статьи по Теме :