В духе безопасности типов, связанной с CriteriaQuery, JPA 2.0 также имеет API для поддержки представления сущностей в метамодели .
Кто-нибудь знает о полностью функциональной реализации этого API (для создания метамодели, а не создания классов метамодели вручную)? Было бы здорово, если бы кто-то также знал, как это настроить в Eclipse (я предполагаю, что это так же просто, как настроить процессор аннотаций, но вы никогда не знаете).
РЕДАКТИРОВАТЬ: только что наткнулся на генератор метамодели Hibernate JPA 2 . Но проблема остается, так как я не могу найти ссылок для скачивания jar.
РЕДАКТИРОВАТЬ 2: Прошло некоторое время с тех пор, как я задал этот вопрос, но я подумал, что вернусь и добавлю ссылку на проект Hibernate JPA Model Generator на SourceForge
Пожалуйста, взгляните на jpa-metamodels-with-maven-example .
Спящий режим
org.hibernate.org:hibernate-jpamodelgen
.org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor
.Гибернация как зависимость
<dependency> <groupId>org.hibernate.orm</groupId> <artifactId>hibernate-jpamodelgen</artifactId> <version>${version.hibernate-jpamodelgen}</version> <scope>provided</scope> </dependency>
Гибернация как процессор
<plugin> <groupId>org.bsc.maven</groupId> <artifactId>maven-processor-plugin</artifactId> <executions> <execution> <goals> <goal>process</goal> </goals> <phase>generate-sources</phase> <configuration> <compilerArguments>-AaddGeneratedAnnotation=false</compilerArguments> <!-- suppress java.annotation --> <processors> <processor>org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor</processor> </processors> </configuration> </execution> </executions> <dependencies> <dependency> <groupId>org.hibernate.orm</groupId> <artifactId>hibernate-jpamodelgen</artifactId> <version>${version.hibernate-jpamodelgen}</version> </dependency> </dependencies> </plugin>
OpenJPA
org.apache.openjpa:openjpa
.org.apache.openjpa.persistence.meta.AnnotationProcessor6
.<openjpa.metamodel>true<openjpa.metamodel>
.OpenJPA как зависимость
<dependencies> <dependency> <groupId>org.apache.openjpa</groupId> <artifactId>openjpa</artifactId> <scope>provided</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <compilerArgs> <arg>-Aopenjpa.metamodel=true</arg> </compilerArgs> </configuration> </plugin> </plugins> </build>
OpenJPA как процессор
<plugin> <groupId>org.bsc.maven</groupId> <artifactId>maven-processor-plugin</artifactId> <executions> <execution> <id>process</id> <goals> <goal>process</goal> </goals> <phase>generate-sources</phase> <configuration> <processors> <processor>org.apache.openjpa.persistence.meta.AnnotationProcessor6</processor> </processors> <optionMap> <openjpa.metamodel>true</openjpa.metamodel> </optionMap> </configuration> </execution> </executions> <dependencies> <dependency> <groupId>org.apache.openjpa</groupId> <artifactId>openjpa</artifactId> <version>${version.openjpa}</version> </dependency> </dependencies> </plugin>
EclipseLink
org.eclipse.persistence:org.eclipse.persistence.jpa.modelgen.processor
.org.eclipse.persistence.internal.jpa.modelgen.CanonicalModelProcessor
.persistence.xml
.EclipseLink как зависимость
<dependencies> <dependency> <groupId>org.eclipse.persistence</groupId> <artifactId>org.eclipse.persistence.jpa.modelgen.processor</artifactId> <scope>provided</scope> </dependency>
EclipseLink как процессор
<plugins> <plugin> <groupId>org.bsc.maven</groupId> <artifactId>maven-processor-plugin</artifactId> <executions> <execution> <goals> <goal>process</goal> </goals> <phase>generate-sources</phase> <configuration> <processors> <processor>org.eclipse.persistence.internal.jpa.modelgen.CanonicalModelProcessor</processor> </processors> <compilerArguments>-Aeclipselink.persistencexml=src/main/resources-${environment.id}/META-INF/persistence.xml</compilerArguments> </configuration> </execution> </executions> <dependencies> <dependency> <groupId>org.eclipse.persistence</groupId> <artifactId>org.eclipse.persistence.jpa.modelgen.processor</artifactId> <version>${version.eclipselink}</version> </dependency> </dependencies> </plugin>
DataNucleus
org.datanucleus:datanucleus-jpa-query
.org.datanucleus.jpa.query.JPACriteriaProcessor
.DataNucleus как зависимость
<dependencies> <dependency> <groupId>org.datanucleus</groupId> <artifactId>datanucleus-jpa-query</artifactId> <scope>provided</scope> </dependency> </dependencies>
DataNucleus как процессор
<plugin> <groupId>org.bsc.maven</groupId> <artifactId>maven-processor-plugin</artifactId> <executions> <execution> <id>process</id> <goals> <goal>process</goal> </goals> <phase>generate-sources</phase> <configuration> <processors> <processor>org.datanucleus.jpa.query.JPACriteriaProcessor</processor> </processors> </configuration> </execution> </executions> <dependencies> <dependency> <groupId>org.datanucleus</groupId> <artifactId>datanucleus-jpa-query</artifactId> <version>${version.datanucleus}</version> </dependency> </dependencies> </plugin>
источник
something is recommended
безIMHO
? Я не представляю интересы кого-либо еще.persistence.xml
, не так ли?Поддержка Eclipse JPA 2.0 через Dali (которая включена в «Eclipse IDE для разработчиков JEE») имеет собственный генератор метамоделей, интегрированный с Eclipse.
Это должно работать с любым провайдером JPA, поскольку сгенерированные классы являются стандартными.
Также смотрите здесь .
источник
Для eclipselink для создания метамодели достаточно только следующей зависимости. Больше ничего не нужно.
<dependency> <groupId>org.eclipse.persistence</groupId> <artifactId>org.eclipse.persistence.jpa.modelgen.processor</artifactId> <version>2.5.1</version> <scope>provided</scope> </dependency>
источник
<exclude-unlisted-classes>false</exclude-unlisted-classes>
в persisetence.xmlpersistence.xml
Для Hibernate в качестве провайдера, который является наиболее распространенным IMHO:
В случае инструментов сборки, таких как Gradle, Maven, вам необходимо иметь банку генератора метамодели Hibernate JPA 2 в пути к классам и на уровне компилятора> = 1.6, это все, что вам нужно для сборки проекта, и метамодель будет сгенерирована автоматически.
В случае IDE Eclipse 1. перейдите в Project-> Properties-> Java Compiler-> Annotation Processing и включите его. 2. Разверните Обработка аннотаций-> Заводской путь-> Добавить внешний файл Jar, добавьте файл Hibernate JPA 2 Metamodel Generator jar, проверьте только что добавленный файл jar и скажите ОК. Очистка и сборка завершена!
Link Hibernate JPA 2 Metamodel Generator jar ссылка из репозитория maven https://mvnrepository.com/artifact/org.hibernate/hibernate-jpamodelgen
источник
<dependencies> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-jpamodelgen</artifactId> <scope>compile</scope> </dependency> </dependencies>
было достаточно добавления в pom.xml.Давайте предположим , наше приложение использует следующее
Post
,PostComment
,PostDetails
иTag
объекты, которые образуют один-ко-многим, один-к-одному и многие-ко-многим отношений таблицы :Как создать метамодель критериев JPA
hibernate-jpamodelgen
Инструмент , предоставляемый Hibernate ORM может быть использован для сканирования объектов проекта и создания JPA Критерии метамодели. Все , что вам нужно сделать , это добавить следующееannotationProcessorPath
кmaven-compiler-plugin
в Mavenpom.xml
конфигурационном файле:Теперь, когда проект скомпилирован, вы можете увидеть, что в
target
папке генерируются следующие классы Java:Метамодель объекта тега
Если
Tag
объект отображается следующим образом:@Entity @Table(name = "tag") public class Tag { @Id private Long id; private String name; //Getters and setters omitted for brevity }
Класс
Tag_
Metamodel создается следующим образом:@Generated(value = "org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor") @StaticMetamodel(Tag.class) public abstract class Tag_ { public static volatile SingularAttribute<Tag, String> name; public static volatile SingularAttribute<Tag, Long> id; public static final String NAME = "name"; public static final String ID = "id"; }
SingularAttribute
Используется для основныхid
иname
Tag
JPA атрибутов сущностей.Метамодель объекта публикации
Post
Объект отображается следующим образом:@Entity @Table(name = "post") public class Post { @Id private Long id; private String title; @OneToMany( mappedBy = "post", cascade = CascadeType.ALL, orphanRemoval = true ) private List<PostComment> comments = new ArrayList<>(); @OneToOne( mappedBy = "post", cascade = CascadeType.ALL, fetch = FetchType.LAZY ) @LazyToOne(LazyToOneOption.NO_PROXY) private PostDetails details; @ManyToMany @JoinTable( name = "post_tag", joinColumns = @JoinColumn(name = "post_id"), inverseJoinColumns = @JoinColumn(name = "tag_id") ) private List<Tag> tags = new ArrayList<>(); //Getters and setters omitted for brevity }
Post
Предприятие имеет два основных атрибутов,id
иtitle
, один-ко-многимcomments
коллекции, один-к-одномуdetails
ассоциации, и многие-ко-многимtags
коллекции.Класс
Post_
Metamodel создается следующим образом:@Generated(value = "org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor") @StaticMetamodel(Post.class) public abstract class Post_ { public static volatile ListAttribute<Post, PostComment> comments; public static volatile SingularAttribute<Post, PostDetails> details; public static volatile SingularAttribute<Post, Long> id; public static volatile SingularAttribute<Post, String> title; public static volatile ListAttribute<Post, Tag> tags; public static final String COMMENTS = "comments"; public static final String DETAILS = "details"; public static final String ID = "id"; public static final String TITLE = "title"; public static final String TAGS = "tags"; }
Основной
id
иtitle
атрибуты, а также один-к-одномуdetails
ассоциации, которые представлены вSingularAttribute
то время какcomments
иtags
коллекции представлены JPAListAttribute
.Метамодель сущности PostDetails
PostDetails
Объект отображается следующим образом:@Entity @Table(name = "post_details") public class PostDetails { @Id @GeneratedValue private Long id; @Column(name = "created_on") private Date createdOn; @Column(name = "created_by") private String createdBy; @OneToOne(fetch = FetchType.LAZY) @MapsId @JoinColumn(name = "id") private Post post; //Getters and setters omitted for brevity }
Все атрибуты сущности будут представлены JPA
SingularAttribute
в связанномPostDetails_
классе Metamodel:@Generated(value = "org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor") @StaticMetamodel(PostDetails.class) public abstract class PostDetails_ { public static volatile SingularAttribute<PostDetails, Post> post; public static volatile SingularAttribute<PostDetails, String> createdBy; public static volatile SingularAttribute<PostDetails, Long> id; public static volatile SingularAttribute<PostDetails, Date> createdOn; public static final String POST = "post"; public static final String CREATED_BY = "createdBy"; public static final String ID = "id"; public static final String CREATED_ON = "createdOn"; }
Метамодель объекта PostComment
PostComment
Отображаются следующим образом :@Entity @Table(name = "post_comment") public class PostComment { @Id private Long id; @ManyToOne(fetch = FetchType.LAZY) private Post post; private String review; //Getters and setters omitted for brevity }
И все атрибуты сущности представлены JPA
SingularAttribute
в связанномPostComments_
классе Metamodel:@Generated(value = "org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor") @StaticMetamodel(PostComment.class) public abstract class PostComment_ { public static volatile SingularAttribute<PostComment, Post> post; public static volatile SingularAttribute<PostComment, String> review; public static volatile SingularAttribute<PostComment, Long> id; public static final String POST = "post"; public static final String REVIEW = "review"; public static final String ID = "id"; }
Использование метамодели критериев JPA
Без метамодели JPA запрос API критериев, который должен получать
PostComment
объекты, отфильтрованные по их связанномуPost
заголовку, выглядел бы следующим образом:CriteriaBuilder builder = entityManager.getCriteriaBuilder(); CriteriaQuery<PostComment> query = builder.createQuery(PostComment.class); Root<PostComment> postComment = query.from(PostComment.class); Join<PostComment, Post> post = postComment.join("post"); query.where( builder.equal( post.get("title"), "High-Performance Java Persistence" ) ); List<PostComment> comments = entityManager .createQuery(query) .getResultList();
Обратите внимание, что мы использовали
post
строковый литерал при созданииJoin
экземпляра, и мы использовалиtitle
строковый литерал при ссылке наPost
title
.Метамодель JPA позволяет нам избежать жесткого кодирования атрибутов сущности, как показано в следующем примере:
CriteriaBuilder builder = entityManager.getCriteriaBuilder(); CriteriaQuery<PostComment> query = builder.createQuery(PostComment.class); Root<PostComment> postComment = query.from(PostComment.class); Join<PostComment, Post> post = postComment.join(PostComment_.post); query.where( builder.equal( post.get(Post_.title), "High-Performance Java Persistence" ) ); List<PostComment> comments = entityManager .createQuery(query) .getResultList();
Или, скажем , мы хотим принести проекцию DTO во время фильтрации
Post
title
и наPostDetails
createdOn
атрибуты.Мы можем использовать метамодель при создании атрибутов соединения, а также при создании псевдонимов столбцов проекции DTO или при ссылке на атрибуты сущности, которые нам нужно фильтровать:
CriteriaBuilder builder = entityManager.getCriteriaBuilder(); CriteriaQuery<Object[]> query = builder.createQuery(Object[].class); Root<PostComment> postComment = query.from(PostComment.class); Join<PostComment, Post> post = postComment.join(PostComment_.post); query.multiselect( postComment.get(PostComment_.id).alias(PostComment_.ID), postComment.get(PostComment_.review).alias(PostComment_.REVIEW), post.get(Post_.title).alias(Post_.TITLE) ); query.where( builder.and( builder.like( post.get(Post_.title), "%Java Persistence%" ), builder.equal( post.get(Post_.details).get(PostDetails_.CREATED_BY), "Vlad Mihalcea" ) ) ); List<PostCommentSummary> comments = entityManager .createQuery(query) .unwrap(Query.class) .setResultTransformer(Transformers.aliasToBean(PostCommentSummary.class)) .getResultList();
Круто, правда?
источник
Хорошо, исходя из того, что я здесь прочитал, я сделал это с помощью EclipseLink таким образом, и мне не нужно было помещать зависимость процессора в проект, только как
annotationProcessorPath
элемент плагина компилятора.<plugin> <artifactId>maven-compiler-plugin</artifactId> <configuration> <annotationProcessorPaths> <annotationProcessorPath> <groupId>org.eclipse.persistence</groupId> <artifactId>org.eclipse.persistence.jpa.modelgen.processor</artifactId> <version>2.7.7</version> </annotationProcessorPath> </annotationProcessorPaths> <compilerArgs> <arg>-Aeclipselink.persistencexml=src/main/resources/META-INF/persistence.xml</arg> </compilerArgs> </configuration> </plugin>
источник