JPA 엔티티 메타 모델을 생성하는 방법은 무엇입니까?


94

CriteriaQuery JPA 2.0 과 관련된 유형 안전성의 정신 으로 엔티티의 메타 모델 표현 을 지원하는 API도 있습니다 .

메타 모델 클래스를 수동으로 생성하는 대신 메타 모델을 생성하기 위해이 API의 완전한 기능 구현을 알고있는 사람이 있습니까? 누군가 Eclipse에서 이것을 설정하는 단계를 알고 있다면 멋질 것입니다 (나는 주석 프로세서를 설정하는 것만 큼 간단하다고 가정하지만 결코 알 수 없습니다).

편집 : Hibernate JPA 2 Metamodel Generator를 우연히 발견했습니다 . 그러나 항아리에 대한 다운로드 링크를 찾을 수 없기 때문에 문제가 남아 있습니다.

편집 2 :이 질문을 한 후 잠시 지났지 만 돌아와서 SourceForgeHibernate JPA Model Generator 프로젝트에 대한 링크를 추가 할 것이라고 생각했습니다.

답변:


87

누군가 Eclipse에서 이것을 설정하는 단계를 알고 있다면 멋질 것입니다 (주석 프로세서를 설정하는 것만 큼 간단하다고 가정하지만 결코 알 수 없습니다)

네, 그렇습니다. 다음은 다양한 JPA 2.0 구현에 대한 구현 및 지침입니다.

EclipseLink

최대 절전 모드

OpenJPA

DataNucleus


최신 Hibernate 구현은 다음에서 구할 수 있습니다.

이전 Hibernate 구현은 다음과 같습니다.


1
DataNucleus 링크가 작동하지 않습니다.
Karl Richter

1
Hibernate 링크도 죽었습니다
Freelancer

43

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는 추가 요소가 필요한 것 같습니다 <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입니다.
  • EclipseLink에는 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>

3
명확하게 말하면, 생성 된 항목은 eclipselink와 함께 사용할 수 있습니다. 최대 절전 모드를 사용하여 생성하더라도 netbeans 8에서 메타 모델을 생성 할 수
없었고

@ymajoros 그렇게 말하지 something is recommended않고 말하는 것이 금지되어 IMHO있습니까? 나는 다른 사람을 대신하여 대표하지 않습니다.
Jin Kwon

1
BTW, EclipseLink에 대한 Sorter의 답변을 참조하십시오. 이것은 내가 수년간 사용해온 구성이며 완벽하게 작동합니다. stackoverflow.com/questions/3037593/…
ymajoros

난은 EclipseLink와 최대 절전 모드 생성 된 메타 모델을 사용하여 NullPointerException이 얻으려고이 구현 고유의 것 아닌가요
마이클 Ziobro

@ymajoros 아직도 필요 persistence.xml하지 않습니까?
진 권

20

Dali ( "JEE 개발자 용 Eclipse IDE"에 포함됨)를 통한 Eclipse의 JPA 2.0 지원에는 Eclipse와 통합 된 자체 메타 모델 생성기가 있습니다.

  1. 패키지 탐색기 에서 프로젝트를 선택하십시오.
  2. 로 이동 속성 -> JPA 대화
  3. Canonical metamodel (JPA 2.0) 그룹 에서 소스 폴더 선택
  4. 적용 버튼을 클릭 하여 선택한 소스 폴더에 메타 모델 클래스를 생성합니다.

여기에 이미지 설명 입력

생성 된 클래스가 표준이므로 모든 JPA 공급자에서 작동합니다.

또한 여기를 참조 하십시오 .


프로세스를 직접 시작할 수있는 방법이 있습니까? 이것은 나를위한 메타 모델을 안정적으로 생성하지 못합니다
thatsIch

6

eclipselink의 경우 다음 종속성 만 메타 모델을 생성하는 데 충분합니다. 다른 것은 필요하지 않습니다.

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


@Barthelomeus 귀하의 메모는 거짓 입니다. EclipseLink가 2.5.1+ 단지 지정, 너무 비상장 개체에 대한 메타 모델 클래스를 생성합니다 <exclude-unlisted-classes>false</exclude-unlisted-classes>persisetence.xml에
미셸 마리오 티

참고 EclipseLink가 생성되지 않습니다없이persistence.xml
진 권

5

가장 일반적인 IMHO 인 공급자로서의 Hibernate의 경우 :

Gradle, Maven과 같은 빌드 도구의 경우 클래스 경로에 Hibernate JPA 2 Metamodel Generator jar가 있어야하고 컴파일러 수준> = 1.6이 필요합니다. 프로젝트를 빌드하면 메타 모델이 자동으로 생성됩니다.

IDE Eclipse의 경우 1. Project-> Properties-> Java Compiler-> Annotation Processing으로 이동하여 활성화합니다. 2. Annotation Processing-> Factory Path-> Add External Jar를 확장합니다. Add Hibernate JPA 2 Metamodel Generator jar가 새로 추가 된 jar를 확인하고 OK라고 말합니다. 청소 및 빌드 완료!

링크 Hibernate JPA 2 Metamodel Generator jar 링크 from maven repo 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에 추가 하는 것으로 충분했습니다.
Lu55

Maven과 Eclipse를 사용할 때 두 구성이 모두 필요합니까?
Melkor

hibernate-jpamodelgen이 pom에 추가되었지만이 작업을 수행해야했고 작동했습니다
Freelancer

3

이것은 매우 일반적인 질문이므로이 답변의 기반이되는이 기사를 작성 했습니다.

하자 우리의 응용 프로그램이 다음을 사용하는 가정 Post, PostComment, PostDetails, 및 Tag일대를 형성 기관, 일대일 및 다 대다 테이블 관계 :

JPA 기준 메타 모델

JPA 기준 메타 모델을 생성하는 방법

hibernate-jpamodelgen최대 절전 모드 ORM에서 제공하는 도구는 프로젝트 엔티티를 스캔하고 JPA 기준 메타 모델을 생성 할 수 있습니다. Maven 구성 파일 에 다음 annotationProcessorPath을 추가 maven-compiler-plugin하기 만하면 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>

이제 프로젝트가 컴파일되면 target폴더에서 다음 Java 클래스가 생성되는 것을 볼 수 있습니다 .

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

태그 엔티티 메타 모델

Tag엔티티가 다음과 같이 매핑 된 경우 :

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

    @Id
    private Long id;

    private String name;

    //Getters and setters omitted for brevity
}

Tag_메타 모델 클래스는 다음과 같이 생성됩니다

@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기본에 사용되는 idname TagJPA 엔티티 특성을가집니다.

엔터티 메타 모델 게시

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_다음과 같이 메타 모델 클래스가 생성됩니다

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

기본 idtitle특성뿐만 아니라 일대일 details연결하는로 표현된다 SingularAttribute그동안 commentstags모음은 JPA로 표시된다 ListAttribute.

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
}

모든 엔티티 속성은 SingularAttribute연관된 PostDetails_Metamodel 클래스 에서 JPA로 표시됩니다 .

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

그리고 모든 엔티티 속성은 SingularAttribute연관된 PostComments_Metamodel 클래스 에서 JPA 로 표시됩니다 .

@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 메타 모델이 없으면 PostComment연관된 Post제목으로 필터링 된 엔티티 를 가져와야하는 Criteria API 쿼리 는 다음과 같습니다.

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

Codota와 같은 코드 완성 도구를 사용하는 경우 JPA Criteria API 쿼리를 작성하는 것이 훨씬 쉽습니다. Codota IDE 플러그인에 대한 자세한 내용은 이 기사 를 확인하십시오 .

또는,하자 우리가 가져 싶은 말은 DTO 투영을 필터링하는 동안 Post titlePostDetails 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();

멋지죠?


0

좋아, 내가 여기서 읽은 내용을 기반으로 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>
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.