JPA varlık Metamodeli nasıl oluşturulur?


97

CriteriaQuery ile ilişkili güvenlik türü ruhu çerçevesinde JPA 2.0 , varlıkların Metamodel temsilini desteklemek için bir API'ye de sahiptir .

Bu API'nin tamamen işlevsel bir uygulamasından haberdar olan var mı (metamodel sınıflarını manuel olarak oluşturmak yerine Metamodel oluşturmak için)? Birisi bunu Eclipse'de kurmanın adımlarını biliyorsa harika olurdu (bir açıklama işlemcisi kurmak kadar basit olduğunu varsayıyorum, ama asla bilemezsiniz).

DÜZENLEME: Hibernate JPA 2 Metamodel Generator ile karşılaştım . Ancak kavanoz için herhangi bir indirme bağlantısı bulamadığım için sorun devam ediyor.

DÜZENLEME 2: Bu soruyu sorduğumdan bu yana bir süre geçti, ancak geri dönüp SourceForge'daki Hibernate JPA Model Generator projesine bir bağlantı eklemeyi düşündüm

Yanıtlar:


88

Birisi bunu Eclipse'de kurma adımlarını da biliyorsa harika olurdu (bir açıklama işlemcisi kurmak kadar basit olduğunu varsayıyorum, ama asla bilemezsiniz)

Evet öyle. Çeşitli JPA 2.0 uygulamaları için uygulamalar ve talimatlar:

EclipseLink

Hazırda beklet

OpenJPA

DataNucleus


En son Hazırda Bekletme uygulaması şu adreste mevcuttur:

Daha eski bir Hazırda Bekletme uygulaması şu adrestedir:


1
DataNucleus bağlantısı öldü.
Karl Richter

1
Hazırda bekletme bağlantısı da öldü
Serbest

43

Lütfen jpa-metamodels-with-maven-example'a bir göz atın .

Hazırda beklet

  • İhtiyacımız var org.hibernate.org:hibernate-jpamodelgen.
  • İşlemci sınıfı org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor.

Bağımlılık olarak hazırda bekletme

    <dependency>
      <groupId>org.hibernate.orm</groupId>
      <artifactId>hibernate-jpamodelgen</artifactId>
      <version>${version.hibernate-jpamodelgen}</version>
      <scope>provided</scope>
    </dependency>

İşlemci olarak hazırda bekletme

      <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

  • İhtiyacımız var org.apache.openjpa:openjpa.
  • İşlemci sınıfı org.apache.openjpa.persistence.meta.AnnotationProcessor6.
  • OpenJPA ek eleman gerektiriyor gibi görünüyor <openjpa.metamodel>true<openjpa.metamodel>.

Bağımlılık olarak 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>

İşlemci olarak 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

  • İhtiyacımız var org.eclipse.persistence:org.eclipse.persistence.jpa.modelgen.processor.
  • İşlemci sınıfı org.eclipse.persistence.internal.jpa.modelgen.CanonicalModelProcessor.
  • EclipseLink gerektirir persistence.xml.

Bağımlılık olarak EclipseLink

  <dependencies>
    <dependency>
      <groupId>org.eclipse.persistence</groupId>
      <artifactId>org.eclipse.persistence.jpa.modelgen.processor</artifactId>
      <scope>provided</scope>
    </dependency>

Bir işlemci olarak 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

  • İhtiyacımız var org.datanucleus:datanucleus-jpa-query.
  • İşlemci sınıfı org.datanucleus.jpa.query.JPACriteriaProcessor.

Bir bağımlılık olarak DataNucleus

  <dependencies>
    <dependency>
      <groupId>org.datanucleus</groupId>
      <artifactId>datanucleus-jpa-query</artifactId>
      <scope>provided</scope>
    </dependency>
  </dependencies>

İşlemci olarak 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>

3
Daha açık olmak gerekirse, oluşturulan öğeler eclipselink ile kullanılabilir, onu oluşturmak için hazırda bekletme modunu kullansanız bile, netbeans 8'den meta model oluşturamadım ve eşyalarımı oluşturmak için bir maven test projesi oluşturmak zorunda kaldım
Kalpesh Soni

@ymajoros SO'da something is recommendedolmadan söylemek yasak mı IMHO? Başkası adına temsil etmiyorum.
Jin Kwon

1
BTW, Sıralayıcının EclipseLink için cevabına bakın. Yıllardır kullandığım konfigürasyon bu ve mükemmel çalışıyor. stackoverflow.com/questions/3037593/…
ymajoros

Bu uygulamaya özel değil mi? EclipseLink ile Hibernate tarafından oluşturulan metamodel'i kullanmaya ve NullPointerException almaya çalışıyorum
Michał Ziobro

@ymajoros Hala ihtiyacı var persistence.xml, değil mi?
Jin Kwon

20

Eclipse'in Dali aracılığıyla sunduğu JPA 2.0 desteği ("JEE Geliştiricileri için Eclipse IDE'ye dahil edilmiştir), Eclipse ile entegre edilmiş kendi metamodel oluşturucusuna sahiptir.

  1. Paket Gezgini'nde projenizi seçin
  2. Gidin Özellikleri -> JPA iletişim
  3. Canonical metamodel (JPA 2.0) grubundan kaynak klasörü seçin
  4. Seçili kaynak klasörde metamodel sınıfları oluşturmak için Uygula düğmesini tıklayın

görüntü açıklamasını buraya girin

Oluşturulan sınıflar standart olduğundan bu, herhangi bir JPA sağlayıcısı üzerinde çalışmalıdır.

Ayrıca buraya bakın .


Süreci kendiniz başlatmanın bir yolu var mı? Bu güvenilir benim için Metamodel üretmez
thatsIch

6

Eclipselink için, metamodel oluşturmak için yalnızca aşağıdaki bağımlılık yeterlidir. Başka hiçbir şeye gerek yok.

    <dependency>
        <groupId>org.eclipse.persistence</groupId>
        <artifactId>org.eclipse.persistence.jpa.modelgen.processor</artifactId>
        <version>2.5.1</version>
        <scope>provided</scope>
    </dependency>


@Barthelomeus notunuz yanlış . EclipseLink 2.5.1+, listelenmemiş varlıklar için de metamodel sınıfları oluşturacak, sadece <exclude-unlisted-classes>false</exclude-unlisted-classes>persisetence.xml'de belirtin
Michele Mariotti

Eclipselink'in olmadan oluşmayacağını unutmayınpersistence.xml
Jin Kwon

6

En yaygın IMHO olan sağlayıcı olarak Hazırda Bekletme için:

Gradle, Maven gibi araçların oluşturulması durumunda, sınıf yolunda Hibernate JPA 2 Metamodel Generator kavanozuna sahip olmanız gerekir ve derleyici seviyesi> = 1.6, ihtiyacınız olan tek şey projeyi oluşturmaktır ve metamodel otomatik olarak oluşturulacaktır.

IDE Eclipse durumunda 1. Proje-> Özellikler-> Java Derleyici-> Ek Açıklama İşleme'ye gidin ve etkinleştirin. 2. Ek Açıklama İşleme-> Fabrika Yolu-> Harici Kavanoz Ekle'yi genişletin, Hazırda Beklet JPA 2 Metamodel Oluşturucu kavanozu yeni eklenen kavanozu kontrol edin ve Tamam deyin. Clean and Build tamamlandı!

Bağlan Hibernate JPA 2 Metamodel Generator jar bağlantısı maven repo https://mvnrepository.com/artifact/org.hibernate/hibernate-jpamodelgen


Benim durumumda <dependencies> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-jpamodelgen</artifactId> <scope>compile</scope> </dependency> </dependencies>pom.xml'e eklemek yeterliydi.
Lu55

Maven ve Eclipse kullanırken her iki konfigürasyona da ihtiyacım var mı?
Melkor

pom'da hibernate-jpamodelgen eklenmiş olsa da, bunu yapmak zorunda kaldım ve işe yaradı
Serbest

Bu aynı zamanda kabul edilen cevap olmalıdır. Çok teşekkürler Sandeep
Shubham Arya

3

Bu çok yaygın bir soru olduğu için bu cevabın dayandığı bu makaleyi yazdım .

Uygulamamızın aşağıdakileri kullandığını varsayalım Post , PostComment, PostDetailsve Tagbir tane çoğa oluşturan kişiler, bire-bir ve birçok çoğa tablo ilişkileri :

JPA Ölçütleri Metamodeli

JPA Ölçütleri Metamodeli nasıl oluşturulur?

hibernate-jpamodelgenHazırda ORM tarafından sağlanan alet proje varlıkları tarama ve JPA Kriterlerini Metamodel üretmek için kullanılabilir. Tek yapmanız gereken tek şey aşağıdaki ekleyin annotationProcessorPathiçin maven-compiler-pluginMaven içinde pom.xmlyapılandırma dosyasının:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>${maven-compiler-plugin.version}</version>
    <configuration>
        <annotationProcessorPaths>
            <annotationProcessorPath>
                <groupId>org.hibernate</groupId>
                <artifactId>hibernate-jpamodelgen</artifactId>
                <version>${hibernate.version}</version>
            </annotationProcessorPath>
        </annotationProcessorPaths>
    </configuration>
</plugin>

Şimdi, proje derlendiğinde, targetklasörde aşağıdaki Java sınıflarının oluşturulduğunu görebilirsiniz:

> tree target/generated-sources/
target/generated-sources/
└── annotations
    └── com
        └── vladmihalcea
            └── book
                └── hpjp
                    └── hibernate
                        ├── forum
                        │   ├── PostComment_.java
                        │   ├── PostDetails_.java
                        │   ├── Post_.java
                        │   └── Tag_.java

Etiket varlığı Metamodel

Eğer Tagaşağıdaki gibi varlık eşleştirilmiş:

@Entity
@Table(name = "tag")
public class Tag {

    @Id
    private Long id;

    private String name;

    //Getters and setters omitted for brevity
}

Tag_Metamodel sınıfı böyle oluşturulur:

@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";
}

SingularAttributeTemel için kullanılır idve name TagJPA varlık öznitelikleri.

Gönderi varlığı Metamodel

PostVarlık böyle eşleştirilmiş:

@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
}

PostVarlık iki temel özelliklere sahiptir, idve title, bire-birçok commentskoleksiyon, bire-bir detailsilişki ve bir çok-çok sayıda tagskoleksiyon.

Post_Aşağıdaki gibi Metamodel sınıfı oluşturulur:

@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";
}

Temel idve titleözniteliklerin yanı sıra bire bir detailsilişki, bir SingularAttributesüre ile temsil edilir commentsve tagskoleksiyonları JPA tarafından temsil edilir ListAttribute.

PostDetails varlık Metamodel

PostDetailsVarlık böyle eşleştirilmiş:

@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
}

Tüm varlık öznitelikleri SingularAttribute, ilişkili PostDetails_Metamodel sınıfında JPA tarafından temsil edilecektir :

@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 varlığı Metamodel

Aşağıdaki PostCommentgibi eşlenir:

@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
}

Ve tüm varlık öznitelikleri SingularAttribute, ilişkili PostComments_Metamodel sınıfında JPA tarafından temsil edilir :

@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 Ölçütleri Metamodelini Kullanma

JPA Metamodel olmadan, PostCommentilişkili Postbaşlıklarına göre filtrelenen varlıkları getirmesi gereken bir Criteria API sorgusu şu şekilde görünür:

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();

Kullandığımız bu Bildirimi postoluştururken dize Joinörneği ve kullandığımız titlebaşvururken dize Post title.

JPA Metamodel, aşağıdaki örnekte gösterildiği gibi, varlık özniteliklerini sabit kodlamamıza izin verir:

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();

Codota gibi bir kod tamamlama aracı kullanıyorsanız, JPA Criteria API sorguları yazmak çok daha kolaydır. Check out bu makaleyi Codota IDE eklentisi hakkında daha fazla ayrıntı için.

Ya da, hadi biz bir getirme istediğini söylüyorsun DTO projeksiyonunu filtreleme süre Post titleve PostDetails createdOnözelliklerini.

Metamodeli birleştirme özniteliklerini oluştururken ve ayrıca DTO projeksiyon sütunu takma adlarını oluştururken veya filtrelememiz gereken varlık özniteliklerine referans verirken kullanabiliriz:

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();

Harika, değil mi?


0

Tamam, burada okuduğuma göre, EclipseLink ile bu şekilde yaptım ve işlemci bağımlılığını projeye koymam gerekmedi, sadece annotationProcessorPathderleyici eklentisinin bir öğesi olarak.

    <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>
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.