Для більшості java рограмістів сьогодні Hibernate == ORM. проте є ряд інших, не менш цікавих ORM, які можуть виявитися куди більш підходящим для вашого проекту, ніж улюблений Хібернейт.
Хочу звернути вашу увагу на EclipseLink, який пішов від ораклівського TopLink і сьогодні являє більш ніж підтримку персістенсу через JPA, але також JAXB, JCA та SDO (простими словами – можна працювати з XML, веб-сервісами чи но-скл базами). Але я сфокусуюся саме на ORM стороні цього рішення, і без дискутування чому ORM це погано і треба обережно совати його до свого проекту:)
Пропоную розглянути, як EclipseLink може допомогти, якщо на проекті Оракл СКБД
Отже, більшість знайомі з Хібернейтом, або з JPA in general. Хочу поділитися своїм досвідом використання EclipseLink, після інтенсивної роботи з Hibernate.
Перший плюс EclipseLink – це етелонна реалізація JPA (хоча це привносить і свої мінуси). Другий, і найбільш вагомий плюс – велика кількість Оракл-орієнтед плюшек, про які піде нижче – отже, якщо на вашому проекті Оракл і ви не плануєте підтримути якісь інші СКБД, то вам прямий шлях до використання EclipseLink, а не Хібернейт. І по-третє, статус з багами в кожному з проектів (as for July 26, 2011):
Name – Number of bugs – Number of blockers – The oldest blocker
Hibernate – 156 – 49 – 29/Sep/2006
EclipseLink – 15 – 3 – 04/Jun/2010
(!) Перед використанням слід обов”язково ознайомитися з інструкцією по використання, бо на вас чекатимуть різноманітні підводні камені. Один з найбільш підступних – це кеш другого рівня, який по замовчуваню увімкнений (це WeakHashMap)
Ну а тепер про обіцяні плюшки для Ораклу:
1) EclipseLink вміє вписувати хінти до кверів,
коли під”єднаний до Оракла, а також має АПІ який дозволяє вам самостійно додавати хінти: наприклад, з банально
Query query = em.createQuery("SELECT e FROM Employee e ORDER BY e.lastName ASC, e.firstName ASC");
query.setFirstResult(5);
query.setMaxResults(5);
List<Employee> emps = query.getResultList();
Ви отримаєте ось такий SQL запит (і одразу біндінг, без додаткових налаштувань логування як у хібернейту)
SELECT * FROM (SELECT /*+ FIRST_ROWS */ a.*, ROWNUM rnum FROM (
SELECT t0.EMP_ID AS EMP_ID1, t1.EMP_ID AS EMP_ID2, t0.F_NAME AS F_NAME3, t0.L_NAME AS L_NAME4, t0.START_TIME AS START_TIME5,
t0.END_TIME AS END_TIME6, t0.GENDER AS GENDER7, t1.SALARY AS SALARY8, t0.VERSION AS VERSION9, t0.START_DATE AS START_DATE10,
t0.END_DATE AS END_DATE11, t0.MANAGER_ID AS MANAGER_ID12, t0.ADDR_ID AS ADDR_ID13
FROM EMPLOYEE t0, SALARY t1
WHERE (t1.EMP_ID = t0.EMP_ID) ORDER BY t0.L_NAME ASC, t0.F_NAME ASC) a WHERE ROWNUM <= ?) WHERE rnum > ?
bind => [10, 5]
Як бачите, підказка оптимізатору самостійно з”явилася в запиті
2) Підтримка ієрархічних запитів оракла
Не певен щодо перекладу, мова йде про Hierarchical Queries http://docs.oracle.com/cd/B19306_01/server.102/b14200/queries003.htm
ReadAllQuery raq = new ReadAllQuery(Employee.class);
// Specifies a START WITH expression
Expression startExpr = expressionBuilder.get("id").equal(new Integer(1));
// Specifies a CONNECT BY expression
Expression connectBy = expressionBuilder.get("managedEmployees");
// Specifies an ORDER SIBLINGS BY vector
Vector order = new Vector();
order.addElement(expressionBuilder.get("lastName"));
order.addElement(expressionBuilder.get("firstName"));
raq.setHierarchicalQueryClause(startExpr, connectBy, order);
Vector employees = uow.executeQuery(raq);
Буде перетворено на щось типу
SELECT * FROM EMPLOYEE START WITH ID=1 CONNECT BY PRIOR ID=MANAGER_ID ORDER SIBLINGS BY LAST_NAME, FIRST_NAME
Безціна функціональність, якщо доводеться багато оперувати з ієрархічними структурами
3) Підтримка Oracle Flashback Transaction Query
Ніколи не використовував цей функціонал, і чесно кажу навіть не уявляю, кому він може стати в нагоді (хто знає – поділіться досвідом)
4) Альтернативний спосіб викликати stored procedures, відміний від Хібернейтівського
Тобто, в хібернейті сторед процедуру можна описати, наприклад в hbm.xml чи jpa @NamedStoredProcedureQueryтоді як на додачу до JPA-way, EclipseLink підтримує ще й StoredFunctionCall клас для динамічного формування виклику до деякої сторед процедури, а-ля:
StoredFunctionCall functionCall = new StoredFunctionCall();
functionCall.setProcedureName("CHECK_VALID_EMPLOYEE");
functionCall.addNamedArgument("EMP_ID");
functionCall.setResult("FUNCTION_RESULT", String.class);
ValueReadQuery query = new ValueReadQuery();
query.setCall(functionCall);
query.addArgument("EMP_ID");
List args = new ArrayList();
args.addElement(new Integer(44));
String valid = (String) session.executeQuery(query, args);
Ще одна корисна штукенція, наче підтримується для всіх СКБД, це АПІ для “репортинг запитів”. Тобто, якщо вам треба заюзати в коді AVG, SUM і тд, то не треба писати SQL (чи інші його варіації) – можно просто використати ReportQuery, який дозволяє побудувати таку кверю через маніпулювання методами
ReportQuery query = new ReportQuery(Employee.class, emp);
query.addMaximum("max-salary", emp.get("salary"));
query.addAverage("average-salary", emp.get("salary"));
query.addAttribute("city", emp.get("address").get("city"));
на цьому огляд важливих фіч EclipseLink можна завершити
Роблячи вибір, слід пам”ятатти що Хібернейт має власні специфічні плюшки, і слід зважити який функціонал вам буде більш потрібний