Làm thế nào để tạo Metamodel thực thể JPA?


94

Trên tinh thần an toàn kiểu được liên kết với CriteriaQuery JPA 2.0 cũng có một API để hỗ trợ biểu diễn Metamodel của các thực thể.

Có ai biết về việc triển khai đầy đủ chức năng của API này (để tạo Metamodel thay vì tạo các lớp metamodel theo cách thủ công) không? Sẽ thật tuyệt vời nếu ai đó cũng biết các bước thiết lập điều này trong Eclipse (tôi cho rằng nó đơn giản như thiết lập bộ xử lý chú thích, nhưng bạn không bao giờ biết).

CHỈNH SỬA: Chỉ cần tình cờ xem Hibernate JPA 2 Metamodel Generator . Nhưng vấn đề vẫn còn vì tôi không thể tìm thấy bất kỳ liên kết tải xuống nào cho jar.

CHỈNH SỬA 2: Một thời gian đã trôi qua kể từ khi tôi hỏi câu hỏi này, nhưng tôi nghĩ rằng tôi sẽ quay lại và thêm một liên kết đến dự án Trình tạo mô hình Hibernate JPA trên SourceForge

Câu trả lời:


87

Sẽ thật tuyệt vời nếu ai đó cũng biết các bước để thiết lập điều này trong Eclipse (Tôi cho rằng nó đơn giản như thiết lập bộ xử lý chú thích, nhưng bạn không bao giờ biết)

Vâng, đúng vậy. Dưới đây là các triển khai và hướng dẫn cho các triển khai JPA 2.0 khác nhau:

EclipseLink

Ngủ đông

OpenJPA

DataNucleus


Triển khai Hibernate mới nhất hiện có tại:

Một triển khai Hibernate cũ hơn ở:


1
Liên kết DataNucleus đã chết.
Karl Richter

1
Liên kết Hibernate cũng đã chết
Freelancer

43

Hãy xem jpa-metamodels-with-maven-example .

Ngủ đông

  • Chúng tôi cần org.hibernate.org:hibernate-jpamodelgen.
  • Lớp bộ xử lý là org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor.

Ngủ đông như một phụ thuộc

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

Ngủ đông như một bộ xử lý

      <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

  • Chúng tôi cần org.apache.openjpa:openjpa.
  • Lớp bộ xử lý là org.apache.openjpa.persistence.meta.AnnotationProcessor6.
  • OpenJPA dường như yêu cầu phần tử bổ sung <openjpa.metamodel>true<openjpa.metamodel>.

OpenJPA như một phụ thuộc

  <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 như một bộ xử lý

      <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

  • Chúng tôi cần org.eclipse.persistence:org.eclipse.persistence.jpa.modelgen.processor.
  • Lớp bộ xử lý là org.eclipse.persistence.internal.jpa.modelgen.CanonicalModelProcessor.
  • EclipseLink yêu cầu persistence.xml.

EclipseLink như một phụ thuộc

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

EclipseLink làm bộ xử lý

    <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

  • Chúng tôi cần org.datanucleus:datanucleus-jpa-query.
  • Lớp bộ xử lý là org.datanucleus.jpa.query.JPACriteriaProcessor.

DataNucleus như một phụ thuộc

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

DataNucleus như một bộ xử lý

      <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
Chỉ cần được rõ ràng, những thứ tạo ra có thể được sử dụng với EclipseLink, ngay cả khi bạn sử dụng chế độ ngủ đông để tạo ra nó, tôi couldnt tạo mô hình meta từ netbeans 8 và đã phải tạo ra một dự án thử nghiệm maven để tạo ra công cụ của tôi
Kalpesh Soni

@ymajoros Có bị cấm, trong SO, nói something is recommendedkhông có IMHO? Tôi không đại diện cho bất kỳ ai khác.
Jin Kwon

1
BTW, xem câu trả lời của Sorter cho EclipseLink. Đây là cấu hình tôi đã sử dụng trong nhiều năm và nó hoạt động hoàn hảo. stackoverflow.com/questions/3037593/…
ymajoros

Không phải là thực hiện này cụ thể tôi cố gắng sử dụng Hibernate tạo metamodel với EclipseLink và nhận NullPointerException
Michał Ziobro

@ymajoros Vẫn cần một persistence.xml, phải không?
Jin Kwon

20

Hỗ trợ JPA 2.0 của Eclipse thông qua Dali (được bao gồm trong "Eclipse IDE dành cho các nhà phát triển JEE") có bộ tạo siêu mô hình riêng được tích hợp với Eclipse.

  1. Chọn dự án của bạn trong Trình khám phá gói
  2. Đi tới Thuộc tính -> Hộp thoại JPA
  3. Chọn nguồn thư mục từ Canonical metamodel (JPA 2.0) nhóm
  4. Nhấp vào nút Áp dụng để tạo các lớp siêu mô hình trong thư mục nguồn đã chọn

nhập mô tả hình ảnh ở đây

Điều này sẽ hoạt động trên bất kỳ nhà cung cấp JPA nào vì các lớp được tạo là tiêu chuẩn.

Cũng xem tại đây .


Có cách nào để bắt đầu quá trình này không? Điều này không tạo ra siêu mô hình cho tôi một cách đáng tin cậy
vào

6

Đối với liên kết nhật thực, chỉ phụ thuộc sau là đủ để tạo siêu mô hình. Không cần gì khác.

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


@Barthelomeus ghi chú của bạn là sai . EclipseLink 2.5.1+ sẽ tạo ra lớp metamodel cho các tổ chức chưa niêm yết cũng vậy, chỉ cần chỉ định <exclude-unlisted-classes>false</exclude-unlisted-classes>trong persisetence.xml
Michele Mariotti

Lưu ý rằng EclipseLink sẽ không tạo ra mà không cầnpersistence.xml
Jin Kwon

5

Đối với Hibernate là nhà cung cấp IMHO phổ biến nhất:

Trong trường hợp xây dựng các công cụ như Gradle, Maven, bạn cần có jar Hibernate JPA 2 Metamodel Generator trong classpath và cấp trình biên dịch> = 1.6, đó là tất cả những gì bạn cần để xây dựng dự án và metamodel sẽ được tạo tự động.

Trong trường hợp IDE Eclipse 1. goto Project-> Properties-> Java Compiler-> Annotation Processing và bật nó lên. 2. Mở rộng Xử lý chú thích-> Đường dẫn nhà máy-> Thêm Jar bên ngoài thêm jar Hibernate JPA 2 Metamodel Generator, hãy kiểm tra jar mới được thêm vào và nói OK. Làm sạch và xây dựng xong!

Liên kết liên kết jar Hibernate JPA 2 Metamodel Generator từ kho maven https://mvnrepository.com/artifact/org.hibernate/hibernate-jpamodelgen


Trong trường hợp của tôi, thêm <dependencies> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-jpamodelgen</artifactId> <scope>compile</scope> </dependency> </dependencies>vào pom.xml là đủ.
Lu55

Tôi có cần cả hai cấu hình khi sử dụng maven và Eclipse không?
Melkor

mặc dù hibernate-jpamodelgen đã được thêm vào pom, tôi phải làm điều này và nó hoạt động
Freelancer

3

Vì đây là một câu hỏi rất phổ biến, tôi đã viết bài báo này , dựa trên câu trả lời này.

Hãy giả sử ứng dụng của chúng tôi sử dụng những điều sau đây Post , PostComment, PostDetails, và Tagcác tổ chức, hình thành nên một one-to-many, one-to-one, và nhiều-nhiều mối quan hệ bảng :

Siêu mô hình tiêu chí JPA

Cách tạo Siêu mô hình tiêu chí JPA

Công hibernate-jpamodelgencụ do Hibernate ORM cung cấp có thể được sử dụng để quét các thực thể dự án và tạo Siêu mô hình tiêu chí JPA. Tất cả những gì bạn cần làm là thêm phần sau annotationProcessorPathvào tệp cấu hình maven-compiler-pluginMaven pom.xml:

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

Bây giờ, khi dự án được biên dịch, bạn có thể thấy rằng trong targetthư mục, các lớp Java sau được tạo:

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

Thẻ Metamodel thực thể

Nếu Tagthực thể được ánh xạ như sau:

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

    @Id
    private Long id;

    private String name;

    //Getters and setters omitted for brevity
}

Các Tag_ Metamodel được tạo như sau:

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

Các SingularAttribute được sử dụng cho các cơ sở idname Tagcác thuộc tính thực thể JPA.

Đăng thực thể Metamodel

Các Postthể được ánh xạ như thế này:

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

Thực Postthể có hai thuộc tính cơ bản idtitlemột-nhiềucomments tập hợp một , detailsliên kết một-một và tagstập hợp nhiều-nhiều .

Các Post_ Metamodel được tạo như sau:

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

Cơ bản idtitlecác thuộc tính, cũng như one-to-one detailshiệp hội, được đại diện bởi một SingularAttributetrong khicomments và các tagstập hợp được đại diện bởi JPA ListAttribute.

Thực thể PostDetails Metamodel

Thực PostDetailsthể được ánh xạ như thế này:

@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ất cả các thuộc tính thực thể sẽ được biểu thị bằng JPA SingularAttributetrong PostDetails_lớp Metamodel được liên kết :

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

Thực thể PostComment Metamodel

Các PostCommentđược ánh xạ như sau:

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

Và, tất cả các thuộc tính thực thể được đại diện bởi JPA SingularAttributetrong PostComments_lớp Metamodel được liên kết :

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

Sử dụng siêu mô hình tiêu chí JPA

Nếu không có Siêu mô hình JPA, truy vấn API tiêu chí cần tìm nạp các PostCommentthực thể được lọc theo Posttiêu đề được liên kết của chúng sẽ trông giống như sau:

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

Lưu ý rằng chúng tôi đã sử dụng postký tự Chuỗi khi tạo Joincá thể và chúng tôi đã sử dụng titleký tự Chuỗi khi tham chiếuPost title .

JPA Metamodel cho phép chúng tôi tránh các thuộc tính thực thể mã hóa cứng, như được minh họa bằng ví dụ sau:

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

Viết các truy vấn JPA Criteria API dễ dàng hơn nhiều nếu bạn đang sử dụng một công cụ hoàn thành mã như Codota. Kiểm tra bài viết này để biết thêm chi tiết về plugin Codota IDE.

Hoặc, giả sử chúng tôi muốn tìm nạp một phép chiếu DTO trong khi lọc Post titlecác PostDetails createdOnthuộc tính và.

Chúng ta có thể sử dụng Metamodel khi tạo các thuộc tính nối, cũng như khi xây dựng bí danh cột chiếu DTO hoặc khi tham chiếu đến các thuộc tính thực thể mà chúng ta cần lọc:

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

Tuyệt, phải không?


0

Được rồi, dựa trên những gì tôi đã đọc ở đây, tôi đã làm điều đó với EclipseLink theo cách này và tôi không cần đặt bộ xử lý phụ thuộc vào dự án, chỉ như một annotationProcessorPathphần tử của plugin trình biên dịch.

    <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>
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.