PragmaticProgrammer
PragmaticProgrammer

Reputation: 1129

How to set mixed schemas to certain classes in persistence unit in orm/persistence.xml

I am developing a JPA application which requires to be able to access different schemas on the same database (i.e. DB2/Oracle). I want all of my entities to be registered in the persistence.xml file (<class>) and be able to define which ones belong to certain schemas.

I know it is possible to use java annotations, however this is a product which will need the end user to configure that accordingly (hence why I want to be able to achieve this in an xml file).

Currently I have found an example like this:

orm.xml

  <?xml version="1.0" encoding="UTF-8"?>
<entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm orm_2_0.xsd"
    version="2.0">
    <persistence-unit-metadata>
        <persistence-unit-defaults>
            <schema>SECURITY</schema>
        </persistence-unit-defaults>
    </persistence-unit-metadata>
</entity-mappings>

persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.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_2_0.xsd">
    <persistence-unit name="jpa.sample.plain">
        <mapping-file>custom-orm.xml</mapping-file>
        <class>com.reds.model.Role</class>
        <class>com.reds.model.User</class>
        <properties>
            <property name="javax.persistence.target-database" value="PostgreSQL" />
            <property name="javax.persistence.jdbc.driver" value="org.postgresql.Driver" />
            <property name="javax.persistence.jdbc.url" value="jdbc:postgresql://127.0.0.1:5432/security" />
            <property name="javax.persistence.jdbc.user" value="user" />
            <property name="javax.persistence.jdbc.password" value="password" />
            <!-- EclipseLink should create the database schema automatically -->
            <property name="eclipselink.ddl-generation" value="none" />
            <property name="eclipselink.weaving" value="false" />
            <!-- <property name="eclipselink.ddl-generation.output-mode"
                value="database" /> -->
            <property name="eclipselink.logging.level" value="INFO"/>
        </properties>     
    </persistence-unit>
</persistence>

In the above files, from my understanding the schema "SECURITY" is set on the persistence unit that includes the orm.xml mapping file (makes it the default which an annotation can change?). But this makes the schema be implicitly "SECURITY" for both classes listed in persistence.xml.

Contrary to the above I need:

Details of project:

EDIT:

I found this link which helped me set up my orm.xml: https://docs.jboss.org/hibernate/stable/annotations/reference/en/html/xml-overriding.html

Posted below is the most relevant excerpt:

3.1.2. Entity level metadata

You can either define or override metadata informations on a given entity.

<?xml version="1.0" encoding="UTF-8"?>

<entity-mappin(1)gs 
  xmlns="http://java.sun.com/xml/ns/persistence/orm"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm orm_2_0.xsd"
  version="2.0">

    <package>o(2)rg.hibernate.test.annotations.reflection</package>
    <entity cl(3)ass="Administration" access="PROPERTY" metadata-complete="true">
        <table(4) name="tbl_admin">
            <unique-constraint>
                <column-name>firstname</column-name>
                <column-name>lastname</column-name>
            </unique-constraint>
        </table>
        <secon(5)dary-table name="admin2">
            <primary-key-join-column name="admin_id" referenced-column-name="id"/>
            <unique-constraint>
                <column-name>address</column-name>
            </unique-constraint>
        </secondary-table>
        <id-cl(6)ass class="SocialSecurityNumber"/>
        <inher(7)itance strategy="JOINED"/>
        <seque(8)nce-generator name="seqhilo" sequence-name="seqhilo"/>
        <table(9)-generator name="table" table="tablehilo"/>
        ...
    </entity>

    <entity class="PostalAdministration">
        <prima(10)ry-key-join-column name="id"/>
        ...
    </entity>
</entity-mappings>
1   entity-mappings: entity-mappings is the root element for all XML files. You must declare the xml schema, the schema file is included in the hibernate-annotations.jar file, no internet access will be processed by Hibernate Annotations.
2   package (optional): default package used for all non qualified class names in the given deployment descriptor file.
3   entity: desribes an entity.
metadata-complete defines whether the metadata description for this element is complete or not (in other words, if annotations present at the class level should be considered or not).

An entity has to have a class attribute refering the java class the metadata applies on.

You can overrides entity name through the name attribute, if none is defined and if an @Entity.name is present, then it is used (provided that metadata complete is not set).

For metadata complete (see below) element, you can define an access (either FIELD or PROPERTY (default)). For non medatada complete element, if access is not defined, the @Id position will lead position, if access is defined, the value is used.

4   table: you can declare table properties (name, schema, catalog), if none is defined, the java annotation is used.
You can define one or several unique constraints as seen in the example

5   secondary-table: defines a secondary table very much like a regular table except that you can define the primary key / foreign key column(s) through the primary-key-join-column element. On non metadata complete, annotation secondary tables are used only if there is no secondary-table definition, annotations are ignored otherwise.
6   id-class: defines the id class in a similar way @IdClass does
7   inheritance: defines the inheritance strategy (JOINED, TABLE_PER_CLASS, SINGLE_TABLE), Available only at the root entity level
8   sequence-generator: defines a sequence generator
9   table-generator: defines a table generator
10  primary-key-join-column: defines the primary key join column for sub entities when JOINED inheritance strategy is used

Upvotes: 0

Views: 3017

Answers (1)

Dean Clark
Dean Clark

Reputation: 3878

No, you can't do this via the orm.xml or persistence.xml files.

That said, you can do something similar by specifying the non-standard schema in your @Table annotation on each individual persistence object.

@Entity
@Table(name = "PERSON", schema="SOME_OTHER_SCHEMA")
public class Person {
    . . . 
}

Upvotes: 0

Related Questions