Tôi có cần các phần tử <class> trong Persence.xml không?


110

Tôi có tệp Persance.xml rất đơn giản:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0"
    xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">

    <persistence-unit name="eventractor" transaction-type="RESOURCE_LOCAL">
        <class>pl.michalmech.eventractor.domain.User</class>
        <class>pl.michalmech.eventractor.domain.Address</class>
        <class>pl.michalmech.eventractor.domain.City</class>
        <class>pl.michalmech.eventractor.domain.Country</class>

        <properties>
            <property name="hibernate.hbm2ddl.auto" value="validate" />
            <property name="hibernate.show_sql" value="true" />
        </properties>
    </persistence-unit>

</persistence>

Và nó hoạt động.

Nhưng khi tôi xóa <class>các phần tử, ứng dụng không thấy các thực thể (tất cả các lớp đều được chú thích bằng @Entity).

Có cơ chế tự động nào để quét @Entitycác lớp không?

Câu trả lời:


78

Persence.xml có một jar-filecái mà bạn có thể sử dụng. Từ hướng dẫn Java EE 5 :

<persistence>
    <persistence-unit name="OrderManagement">
        <description>This unit manages orders and customers.
            It does not rely on any vendor-specific features and can
            therefore be deployed to any persistence provider.
        </description>
        <jta-data-source>jdbc/MyOrderDB</jta-data-source>
        <jar-file>MyOrderApp.jar</jar-file>
        <class>com.widgets.Order</class>
        <class>com.widgets.Customer</class>
    </persistence-unit>
</persistence>

Tệp này xác định một đơn vị lâu dài có tên OrderManagement, đơn vị này sử dụng nguồn dữ liệu nhận biết JTA jdbc/MyOrderDB. Các phần tử jar-fileclasschỉ định các lớp bền vững được quản lý: lớp thực thể, lớp có thể nhúng và lớp cha được ánh xạ. Phần jar-filetử chỉ định các tệp JAR hiển thị cho đơn vị độ bền được đóng gói có chứa các lớp độ bền được quản lý, trong khi classphần tử đặt tên rõ ràng cho các lớp độ bền được quản lý.

Trong trường hợp Hibernate, hãy xem Chương 2. Thiết lập và cấu hình quá để biết thêm chi tiết.

CHỈNH SỬA: Trên thực tế, nếu bạn không phiền về việc không tuân thủ thông số kỹ thuật, Hibernate hỗ trợ tự động phát hiện ngay cả trong Java SE. Để làm như vậy, hãy thêm thuộc hibernate.archive.autodetectiontính:

<persistence-unit name="eventractor" transaction-type="RESOURCE_LOCAL">
  <!-- This is required to be spec compliant, Hibernate however supports
       auto-detection even in JSE.
  <class>pl.michalmech.eventractor.domain.User</class>
  <class>pl.michalmech.eventractor.domain.Address</class>
  <class>pl.michalmech.eventractor.domain.City</class>
  <class>pl.michalmech.eventractor.domain.Country</class>
   -->

  <properties>
    <!-- Scan for annotated classes and Hibernate mapping XML files -->
    <property name="hibernate.archive.autodetection" value="class, hbm"/>

    <property name="hibernate.hbm2ddl.auto" value="validate" />
    <property name="hibernate.show_sql" value="true" />
  </properties>
</persistence-unit>

13
Tôi hiểu rồi, nhưng các thực thể (@Entity) nằm trong dự án Maven riêng biệt, vì vậy tên tệp jar có thể thay đổi trên mọi bản dựng. Tôi đang tìm kiếm thứ gì đó để quét tất cả trong gói hoặc đường dẫn classpath cụ thể. Tôi chỉ lười gõ rất nhiều phần tử <class> trong tệp Persence.xml.
Michał Mech

Trên mọi bản dựng ?! Tôi thậm chí sẽ không hỏi tại sao nhưng ... bạn có thể sử dụng bộ lọc để giải quyết vấn đề này.
Pascal Thivent

Không phải ai cũng chính xác nhưng tôi muốn chống lại những thay đổi.
Michał Mech

5
Chủ đề cổ xưa, tôi biết, nhưng hãy xem jpa-maven-plugin .
Laird Nelson

Bạn có thể sử dụng phần tử <mapping-file> (chứa danh sách các thực thể) trong Persence.xml, vì vậy bạn có thể giữ nguyên tên của các tệp đã sử dụng và tích hợp chúng trong bản dựng của các lọ được tham chiếu.
med_alpa

44

Trong môi trường Java SE, theo đặc tả, bạn phải chỉ định tất cả các lớp như bạn đã làm:

Danh sách tất cả các lớp bền vững được quản lý được đặt tên phải được chỉ định trong môi trường Java SE để đảm bảo tính di động

Nếu không có ý định đưa các lớp bền vững có chú thích chứa trong gốc của đơn vị bền vững vào trong đơn vị bền, thì nên sử dụng phần tử loại trừ-không công khai-lớp. Phần tử loại trừ-không công khai-lớp không được thiết kế để sử dụng trong môi trường Java SE.

(JSR-000220 6.2.1.6)

Trong môi trường Java EE, bạn không phải thực hiện việc này vì nhà cung cấp quét các chú thích cho bạn.

Một cách không chính thức, bạn có thể thử đặt <exclude-unlisted-classes>false</exclude-unlisted-classes>trong Persence.xml của mình. Tham số này mặc định falsetrong EE và trueSE. Cả EclipseLinkToplink đều hỗ trợ điều này theo như tôi có thể nói. Nhưng bạn không nên dựa vào nó hoạt động trong SE, theo thông số kỹ thuật, như đã nêu ở trên.

Bạn có thể THỬ những điều sau (có thể có hoặc không hoạt động trong môi trường SE):

<persistence-unit name="eventractor" transaction-type="RESOURCE_LOCAL">
     <exclude-unlisted-classes>false</exclude-unlisted-classes>

    <properties>
            <property name="hibernate.hbm2ddl.auto" value="validate" />
            <property name="hibernate.show_sql" value="true" />
    </properties>
</persistence-unit>

2
<exclude-unlisted-classes>false</exclude-unlisted-classes>không làm việc với WildFly 8.2.1.Final + Hibernate 4.3.7
Andreas Dietrich

12

Tôi có cần các phần tử Lớp trong Persence.xml không?

Không, bạn không nhất thiết phải như vậy. Đây là cách bạn thực hiện trong Eclipse (Kepler đã thử nghiệm):

Nhấp chuột phải vào dự án, nhấp vào Thuộc tính , chọn JPA , trong quản lý lớp Persistence đánh dấu vào Khám phá các lớp được chú thích tự động .

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


9
Tại sao ủng hộ? OP thậm chí không đề cập đến Eclipse và câu trả lời này không cho thấy tính năng Eclipse này hoạt động gì để người ta có thể thực hiện điều đó mà không cần IDE.
Artem Novikov

2
@Artem Novikov: Tôi thấy điều này khá khắc nghiệt vì thường câu hỏi phát sinh từ các môi trường khác nhau và ở đây chúng tôi muốn trợ giúp hoặc đưa ra những gợi ý hữu ích! (như đối với tôi) Nó hữu ích vì Eclipse là một IDE phổ biến để phát triển như thế này và điều này không quá quan trọng, nhưng tôi đoán nó sẽ bao gồm tất cả các dự án không gian làm việc có liên quan (ví dụ: dự án của tôi tùy thuộc vào).
Andreas Dietrich

stackoverflow.com/questions/17951297/... đẹp lừa, nhưng dường như nó chỉ hoạt động nếu thực thể kết thúc trong cùng classloader như persistence.xml
Pierluigi Vernetto

@abbas Vui lòng hiển thị persistence.xmlmà Eclipse tạo ra.
Frans

12

Đối với những người chạy JPA trong Spring, từ phiên bản 3.1 trở đi, bạn có thể đặt packagesToScanthuộc tính dướiLocalContainerEntityManagerFactoryBean và loại bỏ hoàn toàn Persence.xml.

Đây là mức thấp nhất


Đã làm cho tôi! Kịch bản là mùa xuân 4 + hibernate + jpa2 + maven. Kiểm tra JUnit không tìm thấy các thực thể của tôi nhưng với cài đặt này, nó đã thực hiện công việc.
Thứ bảy,

8

Bạn có thể cung cấp jar-fileđường dẫn phần tử đến một thư mục với các lớp đã biên dịch. Ví dụ: tôi đã thêm một cái gì đó như vậy khi tôi chuẩn bị Persence.xml vào một số thử nghiệm tích hợp:

 <jar-file>file:../target/classes</jar-file>

Đây là những gì tôi đang tìm kiếm!
xtian

Cũng hoạt động với EclipseLink!
Bombe

8

đối với JPA 2+ điều này thực hiện thủ thuật

 <jar-file></jar-file>

quét tất cả các lọ trong chiến tranh để tìm các lớp @Entity được chú thích


2
bạn có thêm thông tin về điều này? nó hoạt động một cách tình cờ hay nó được viết trong thông số kỹ thuật? Có phụ thuộc vào việc thực hiện không?
markus

máy quét là trong lớp học kéo dài AbstractScannerImpl, hibernate - không có ý tưởng nếu nó lỗi hoặc tính năng, xin lỗi
eriskooo

1
Trong Java SE với Hibernate 5.1.2. Cuối cùng, giải pháp này không hoạt động. Hibernate yêu cầu một tên tệp jar ( java.lang.IllegalArgumentException: Unable to visit JAR file:).
Stephan

1
làm! :) với WildFly 8.2.1.Final + Hibernate 4.3.7.Final
Andreas Dietrich

Thx man, đã tìm kiếm rất nhiều và đây là giải pháp gọn gàng nhất hiện có. Wildfly10 + Hibernate 5.0.7 đang hoạt động.
boutta

7

Hibernate không hỗ trợ <exclude-unlisted-classes>false</exclude-unlisted-classes> trong SE, (một áp phích khác đã đề cập điều này hoạt động với TopLink và EclipseLink).

Có những công cụ sẽ tự động tạo danh sách các lớp cho Persence.xml, ví dụ như trình hướng dẫn Nhập lược đồ cơ sở dữ liệu trong IntelliJ. Khi bạn đã có các lớp ban đầu của dự án trong Persence.xml, việc thêm / xóa các lớp đơn lẻ bằng tay sẽ rất đơn giản khi dự án của bạn tiến triển.


Tự động phát hiện các thực thể trong Java SE không phải là một phần của JPA. Các ứng dụng dựa vào điều này không phải là di động.
Pascal Thivent,

4

Không chắc liệu bạn có đang làm điều gì đó tương tự như những gì tôi đang làm hay không, nhưng tôi đang tạo một tải java nguồn từ XSD bằng cách sử dụng JAXB trong một thành phần riêng biệt bằng Maven. Giả sử tạo tác này được gọi là "mô hình cơ sở"

Tôi muốn nhập cấu phần phần mềm này có chứa nguồn java và chạy chế độ ngủ đông trên tất cả các lớp trong jar tạo tác "mô hình cơ sở" của tôi và không chỉ định rõ ràng từng lớp. Tôi đang thêm "base-model" làm phần phụ thuộc cho thành phần ngủ đông của mình nhưng vấn đề là thẻ trong Persence.xml chỉ cho phép bạn chỉ định đường dẫn tuyệt đối.

Cách tôi đã làm được là sao chép rõ ràng sự phụ thuộc vào jar "base-model" của tôi vào dir mục tiêu của tôi và cũng loại bỏ phiên bản của nó. Vì vậy, trong khi nếu tôi xây dựng tạo tác "base-model", nó tạo ra "base-model-1.0-SNAPSHOT.jar", thì bước copy-resources sẽ sao chép nó thành "base-model.jar".

Vì vậy, trong pom của bạn cho thành phần ngủ đông:

            <!-- We want to copy across all our artifacts containing java code
        generated from our scheams. We copy them across and strip the version
        so that our persistence.xml can reference them directly in the tag
        <jar-file>target/dependency/${artifactId}.jar</jar-file> -->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-dependency-plugin</artifactId>
            <version>2.5.1</version>
            <executions>
                <execution>
                    <id>copy-dependencies</id>
                    <phase>process-resources</phase>
                    <goals>
                        <goal>copy-dependencies</goal>
                    </goals>
                </execution>
            </executions>       
            <configuration>
                <includeArtifactIds>base-model</includeArtifactIds>
                <stripVersion>true</stripVersion>
            </configuration>        
        </plugin>

Sau đó, tôi gọi plugin ngủ đông trong giai đoạn tiếp theo là "process-class":

            <!-- Generate the schema DDL -->
        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>hibernate3-maven-plugin</artifactId>
            <version>2.2</version>

            <executions>
                <execution>
                    <id>generate-ddl</id>
                    <phase>process-classes</phase>
                    <goals>
                        <goal>hbm2ddl</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
                <components>
                    <component>
                        <name>hbm2java</name>
                        <implementation>annotationconfiguration</implementation>
                        <outputDirectory>/src/main/java</outputDirectory>
                    </component>
                </components>
                <componentProperties>
                    <persistenceunit>mysql</persistenceunit>
                    <implementation>jpaconfiguration</implementation>
                    <create>true</create>
                    <export>false</export>
                    <drop>true</drop>
                    <outputfilename>mysql-schema.sql</outputfilename>
                </componentProperties>
            </configuration>
        </plugin>

và cuối cùng trong kiên trì.xml của tôi, tôi có thể đặt rõ ràng vị trí của cái lọ do đó:

<jar-file>target/dependency/base-model.jar</jar-file>

và thêm thuộc tính:

<property name="hibernate.archive.autodetection" value="class, hbm"/>

3

Nó không phải là một giải pháp mà là một gợi ý cho những người sử dụng Spring:

Tôi đã cố gắng sử dụng org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBeanvới cài đặt persistenceXmlLocationnhưng với điều này, tôi phải cung cấp các <class>yếu tố (ngay cả khi persistenceXmlLocationchỉ trỏ đếnMETA-INF/persistence.xml ).

Khi không sử dụng, persistenceXmlLocationtôi có thể bỏ qua các <class>yếu tố này .


Tôi đã sử dụng persistenceXmlLocationtài sản trong LocalContainerEntityManagerFactoryBeancài đặt của mình . Nhưng tất cả các truy vấn đều hoạt động ngay cả khi tôi bỏ qua các <class>phần tử. Nó trên ứng dụng Spring / Hibernate / Maven. Nhưng trong bạn gợi ý rằng bạn nói rằng "Khi không sử dụng PersenceXmlLocation, tôi có thể bỏ qua các phần tử <class> này." nhưng đối với tôi thì ngược lại.
May mắn

@Ethan bạn nói đúng, bởi vì PersenceXmlLocation ghi đè packageToScan - nếu bạn tìm trong các nguồn. Vì vậy, không sử dụng nó, khi sử dụng packageToScan.
Artem Novikov

2

Tôi không chắc giải pháp này nằm trong thông số kỹ thuật nhưng tôi nghĩ tôi có thể chia sẻ cho những người khác.

cây phụ thuộc

my-entity.jar

Chỉ chứa các lớp thực thể. Không META-INF/persistence.xml.

my-services.jar

Tùy thuộc vào my-entities. Chỉ chứa EJB.

my-resources.jar

Tùy thuộc vào my-services. Chứa các lớp tài nguyên và META-INF/persistence.xml.

các vấn đề

  • Làm cách nào chúng ta có thể chỉ định <jar-file/>phần tử trong my-resourcesdưới dạng tên tạo tác phiên bản hậu tố của một phụ thuộc tạm thời?
  • Làm cách nào chúng ta có thể đồng bộ hóa <jar-file/>giá trị của phần tử và giá trị của phần tử phụ thuộc thoáng qua thực tế?

giải pháp

phụ thuộc trực tiếp (dư thừa?) và lọc tài nguyên

Tôi đặt một tài sản và một phụ thuộc vào my-resources/pom.xml.

<properties>
  <my-entities.version>x.y.z-SNAPSHOT</my-entities.version>
</properties>
<dependencies>
  <dependency>
    <!-- this is actually a transitive dependency -->
    <groupId>...</groupId>
    <artifactId>my-entities</artifactId>
    <version>${my-entities.version}</version>
    <scope>compile</scope> <!-- other values won't work -->
  </dependency>
  <dependency>
    <groupId>...</groupId>
    <artifactId>my-services</artifactId>
    <version>some.very.sepecific</version>
    <scope>compile</scope>
  </dependency>
<dependencies>

Bây giờ hãy persistence.xmlchuẩn bị sẵn sàng để được lọc

<?xml version="1.0" encoding="UTF-8"?>
<persistence ...>
  <persistence-unit name="myPU" transaction-type="JTA">
    ...
    <jar-file>lib/my-entities-${my-entities.version}.jar</jar-file>
    ...
  </persistence-unit>
</persistence>

Plugin Maven Enforcer

Với dependencyConvergencequy tắc này, chúng tôi có thể đảm bảo rằng my-entitiesphiên bản 'giống nhau cả trực tiếp và bắc cầu.

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-enforcer-plugin</artifactId>
  <version>1.4.1</version>
  <executions>
    <execution>
      <id>enforce</id>
      <configuration>
        <rules>
           <dependencyConvergence/>
        </rules>
      </configuration>
      <goals>
        <goal>enforce</goal>
      </goals>
    </execution>
  </executions>
</plugin>

0

Không nhất thiết trong mọi trường hợp.

Tôi đang sử dụng Jboss 7.0.8 và Eclipselink 2.7.0. Trong trường hợp của tôi để tải các thực thể mà không cần thêm các thực thể tương tự trong Persence.xml, tôi đã thêm thuộc tính hệ thống sau trong Jboss Standalone XML:

<property name="eclipselink.archive.factory" value="org.jipijapa.eclipselink.JBossArchiveFactoryImpl"/>

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.