Я хотел бы внести свой вклад в один общий сценарий (в Python 3) и изучить несколько подходов к нему.
Встроенная функция open () принимает либо относительный или абсолютный путь в качестве первого аргумента. Относительный путь трактуется как относительно текущего рабочего каталога , хотя поэтому рекомендуется передать абсолютный путь к файлу.
Проще говоря, если вы запустите файл сценария с в следующем коде не гарантируется, что файл example.txt
будет создан в том же каталоге, где находится файл сценария:
with open('example.txt', 'w'):
pass
Чтобы исправить этот код, нам нужно получить путь к сценарий и сделать его абсолютным. Чтобы гарантировать абсолютный путь, мы просто используем функцию os.path.realpath () . Чтобы получить путь к скрипту, есть несколько общих функций, которые возвращают различные результаты:
os.getcwd()
os.path.realpath('example.txt')
sys.argv[0]
__file__
Обе функции os.getcwd () и os.path.realpath () возвращают результаты на основе текущего рабочего каталога . Вообще не то, что мы хотим. Первым элементом списка sys.argv является путь корневого сценария (сценарий, который вы запускаете), независимо от того, вызываете ли вы этот список в самом корневом скрипте или в любой из его модулей. Это может пригодиться в некоторых ситуациях. Переменная __ file __ содержит путь к модулю, из которого он был вызван.
Следующий код правильно создает файл example.txt
в том же каталоге, где скрипт находится:
filedir = os.path.dirname(os.path.realpath(__file__))
filepath = os.path.join(filedir, 'example.txt')
with open(filepath, 'w'):
pass
Подобно Hibernate Criteria API, JPA 2.0 Criteria API особенно удобен для динамического построения запросов для обработки случаев, когда структура запроса изменяется в зависимости от условий выполнения.
Но это еще не все. Будучи более подробным, чем API критериев Hibernate, API критериев JPA позволяет создавать типизированные запросы (если вы используете API метамодели). Ниже пример:
EntityManager em = ...
QueryBuilder qb = em.getQueryBuilder();
CriteriaQuery<Person> c = qb.createQuery(Person.class);
Root<Person> p = c.from(Person.class);
Predicate condition = qb.gt(p.get(Person_.age), 20);
c.where(condition);
TypedQuery<Person> q = em.createQuery(c);
List<Person> result = q.getResultList();
В приведенном выше фрагменте кода следующее может вызвать ошибку компиляции, например:
Predicate condition = qb.gt(p.get(Person_.age, "xyz"));
Если вам интересно, Person_
является статическим, созданным экземпляром, каноническим классом метамодели , соответствующий исходному классу сущностей Person
(сгенерированному процессором аннотаций). Он обеспечивает строго типизированную альтернативу подходу, основанному на отражении во время выполнения:
Field field = Person.class.getField("age");
Плюсы:
Минусы:
В целом, я чувствую себя более комфортно с JPQL, но безопасность типов Criteria API является основным отличием от JPQL (а также Hibernate Criteria API).
JPA 2.0 Criteria API - это объектно-ориентированный API для построения запросов. Я думаю, что это может сыграть хорошую роль, когда у вас есть динамический запрос , который может стать более читаемым следующим образом
cq.select(...)
.where(...)
.orderBy(...)
.groupBy(...);
Но при использовании статического запроса предпочитают использовать внешний, поддерживаемый и читаемый файл
<entity-mappings>
...
<named-query name="ORDER">
<query>
<![CDATA[
from
Order
]]>
</query>
</named-query>
<named-query name="ORDER_WITH_LINE_ITEM">
<query>
<![CDATA[
from
Order o
inner join fetch
o.lineItemList
]]>
</query>
</named-query>
...
</entity-mappings>
Если у вас есть модульное приложение, используйте один XML-файл для каждого модуля следующим образом
br
com
ar
moduleA
model
repository
moduleA.xml
moduleB
model
repository
moduleB.xml
moduleC
model
repository
moduleC.xml
Затем вы определяете свой элемент mappinf-file
<mapping-file>br/com/ar/moduleA/model/repository/moduleA.xml</mapping-file>
<mapping-file>br/com/ar/moduleB/model/repository/moduleB.xml</mapping-file>
<mapping-file>br/com/ar/moduleC/model/repository/moduleC.xml</mapping-file>
JPA 2 Criteria можно использовать в статически типизированной форме, если вы создадите метамодель сущности. Он более многословен, чем JPQL, но является статически типизированным и поддерживает динамическое построение запросов напрямую.
Преимущества статически типизированного языка запросов в том, что вы можете отлавливать больше ошибок во время компиляции, а также использовать такие возможности IDE, как автозаполнение.