W duchu bezpieczeństwa typu związanego z CriteriaQuery JPA 2.0 posiada również API do obsługi reprezentacji encji przez Metamodel .
Czy ktoś jest świadomy w pełni funkcjonalnej implementacji tego API (do generowania metamodelu w przeciwieństwie do ręcznego tworzenia klas metamodelu)? Byłoby wspaniale, gdyby ktoś również znał kroki konfigurowania tego w Eclipse (zakładam, że jest to tak proste, jak skonfigurowanie procesora adnotacji, ale nigdy nie wiadomo).
EDYCJA: Właśnie natknąłem się na Hibernate JPA 2 Metamodel Generator . Ale problem pozostaje, ponieważ nie mogę znaleźć żadnych linków do pobrania słoika.
EDYCJA 2: Minęło trochę czasu, odkąd zadałem to pytanie, ale pomyślałem, że wrócę i dodam link do projektu Hibernate JPA Model Generator na SourceForge
Proszę spojrzeć na przykład jpa-metamodels-with-maven .
Hibernować
org.hibernate.org:hibernate-jpamodelgen
.org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor
.Hibernacja jako zależność
<dependency> <groupId>org.hibernate.orm</groupId> <artifactId>hibernate-jpamodelgen</artifactId> <version>${version.hibernate-jpamodelgen}</version> <scope>provided</scope> </dependency>
Hibernuj jako procesor
<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 jako zależność
<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 jako procesor
<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 jako zależność
<dependencies> <dependency> <groupId>org.eclipse.persistence</groupId> <artifactId>org.eclipse.persistence.jpa.modelgen.processor</artifactId> <scope>provided</scope> </dependency>
EclipseLink jako procesor
<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 jako zależność
<dependencies> <dependency> <groupId>org.datanucleus</groupId> <artifactId>datanucleus-jpa-query</artifactId> <scope>provided</scope> </dependency> </dependencies>
DataNucleus jako procesor
<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>
źródło
something is recommended
bezIMHO
? Nie reprezentuję w imieniu nikogo innego.persistence.xml
, prawda?Wsparcie Eclipse JPA 2.0 przez Dali (które jest zawarte w "Eclipse IDE for JEE Developers") ma własny generator metamodeli zintegrowany z Eclipse.
Powinno to działać na każdym dostawcy JPA, ponieważ wygenerowane klasy są standardowe.
Zobacz także tutaj .
źródło
W przypadku eclipselink do wygenerowania metamodelu wystarczy tylko następująca zależność. Nic więcej nie jest potrzebne.
<dependency> <groupId>org.eclipse.persistence</groupId> <artifactId>org.eclipse.persistence.jpa.modelgen.processor</artifactId> <version>2.5.1</version> <scope>provided</scope> </dependency>
źródło
<exclude-unlisted-classes>false</exclude-unlisted-classes>
w persisetence.xmlpersistence.xml
Dla Hibernate jako dostawcy, który jest najczęściej używanym IMHO:
W przypadku narzędzi do budowania, takich jak Gradle, Maven, musisz mieć słoik Hibernate JPA 2 Metamodel Generator w ścieżce klas i poziomie kompilatora> = 1.6, czyli wszystko, czego potrzebujesz, aby zbudować projekt, a metamodel zostanie wygenerowany automatycznie.
W przypadku środowiska IDE Eclipse 1. przejdź do Projekt-> Właściwości-> Kompilator Java-> Przetwarzanie adnotacji i włącz je. 2. Rozwiń Annotation Processing-> Factory Path-> Add External Jar dodaj Hibernate JPA 2 Metamodel Generator jar sprawdź nowo dodany jar i powiedz OK. Wyczyść i zbuduj gotowe!
Link Hibernate JPA 2 Metamodel Generator link z repozytorium maven https://mvnrepository.com/artifact/org.hibernate/hibernate-jpamodelgen
źródło
<dependencies> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-jpamodelgen</artifactId> <scope>compile</scope> </dependency> </dependencies>
wystarczyło dodanie do pom.xml.Załóżmy, że nasza aplikacja wykorzystuje następujące
Post
,PostComment
,PostDetails
orazTag
podmioty, które tworzą jeden-do-wielu, jeden-na-jeden, a wiele do wielu relacji tabeli :Jak wygenerować metamodel kryteriów JPA
hibernate-jpamodelgen
Narzędzie dostarczane przez Hibernate ORM może być używany do skanowania jednostek projektowych i generowanie kryteria WZP metamodel. Wszystko, co musisz zrobić, to dodać następujące elementyannotationProcessorPath
do pliku konfiguracyjnegomaven-compiler-plugin
Mavenapom.xml
:Teraz, gdy projekt jest kompilowany, możesz zobaczyć, że w
target
folderze generowane są następujące klasy Java:Oznacz encję Metamodel
Jeśli
Tag
jednostka jest mapowana w następujący sposób:@Entity @Table(name = "tag") public class Tag { @Id private Long id; private String name; //Getters and setters omitted for brevity }
Tag_
Klasa Metamodel generowany jest tak:@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
Służy do podstawowychid
iname
Tag
WZP atrybutów jednostki.Opublikuj Metamodel encji
Post
Jednostka jest odwzorowany tak:@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 }
Plik
Post
Jednostka ma dwa podstawowe atrybuty,id
ititle
, jeden-do-wielucomments
kolekcji, jeden-do-jednegodetails
stowarzyszenia oraz wiele-do-wielutags
kolekcji.Post_
Klasa Metamodel generowany jest w następujący sposób:@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"; }
Podstawowe
id
ititle
atrybuty, a takżedetails
powiązanie jeden do jednego , są reprezentowane przezSingularAttribute
chwilę,comments
atags
kolekcje i są reprezentowane przez WZPListAttribute
.Encja PostDetails Metamodel
Plik
PostDetails
Jednostka jest odwzorowany tak:@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 }
Wszystkie atrybuty encji będą reprezentowane przez JPA
SingularAttribute
w powiązanymPostDetails_
klasie 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"; }
Jednostka PostComment Metamodel
PostComment
Są odwzorowywane w sposób następujący:@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 }
Wszystkie atrybuty encji są reprezentowane przez JPA
SingularAttribute
w powiązanejPostComments_
klasie 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"; }
Korzystanie z metamodelu kryteriów JPA
Bez metamodelu JPA zapytanie Criteria API, które musi pobrać
PostComment
jednostki przefiltrowane według powiązanegoPost
tytułu, wyglądałoby tak: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();
Zauważ, że użyliśmy
post
literału String podczas tworzeniaJoin
wystąpienia i użyliśmytitle
literału String podczas odwoływania się doPost
title
.Metamodel JPA pozwala nam uniknąć zakodowanych na stałe atrybutów encji, co ilustruje poniższy przykład:
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();
Lub, powiedzmy, że chcemy pobrać projekcję DTO podczas filtrowania plików
Post
title
iPostDetails
createdOn
atrybuty.Możemy użyć Metamodelu podczas tworzenia atrybutów złączenia, a także podczas budowania aliasów kolumn projekcji DTO lub podczas odwoływania się do atrybutów encji, które musimy filtrować:
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();
Fajnie, prawda?
źródło
Ok, bazując na tym co tutaj przeczytałem, zrobiłem to z EclipseLink w ten sposób i nie musiałem wstawiać zależności procesora do projektu, tylko jako
annotationProcessorPath
element wtyczki kompilatora.<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>
źródło