For complete ORM mapping, see JPA ORM Schema 2.2.
For proprietary ORM mapping extension, see Cmobilecom JPA ORM Extension Schema 1.0 which extends JPA ORM Schema 2.2.
To ignore all annotations and use XML mappings only, add <xml-mapping-metadata-complete/> element.
The persistence-unit-defaults element specifies persistence unit default values, including catalog, schema, delimited identifiers, access, cascade-persist and default listeners.
For example, META-INF/orm.xml
<entity-mappings> <persistence-unit-metadata> <xml-mapping-metadata-complete/> <persistence-unit-defaults> <schema>jpa_example_schema</schema> <entity-listeners> <entity-listener class="com.cmobilecom.jpa.example.managed_classes.DefaultListener"/> </entity-listeners> </persistence-unit-defaults> </persistence-unit-metadata> </entity-mappings>
@Entity public class Employee { @OneToOne(fetch=FetchType.LAZY, mappedBy="employee") private Office office; } @Entity public class Office { @OneToOne(fetch=FetchType.EAGER) @JoinColumn(name="employee_id") private Employee employee; }XML:
<entity-mappings> <entity class="Employee"> <attributes> <one-to-one name="office" fetch="LAZY" mapped-by="employee"> </one-to-one> </attributes> </entity> <entity class="Office"> <attributes> <one-to-one name="employee" fetch="EAGER"> <join-column name="employee_id"/> </one-to-one> </attributes> </entity> </entity-mappings>
@Entity public class Employer { @OneToMany(cascade={CascadeType.ALL}, orphanRemoval=true, fetch=FetchType.LAZY, mappedBy="employer", targetEntity=Employee.class) @OrderColumn(nullable=false) private List<Employee> employees; } @Entity public class Employee { @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name="employer_id", nullable = false) private Employer employer; }XML:
<entity-mappings> <entity class="Employer"> <attributes> <one-to-many name="employees" fetch="LAZY" orphan-removal="true" mapped-by="employer" target-entity="Employee"> <order-column nullable="false"/> <cascade> <cascade-all/> </cascade> </one-to-many> </attributes> </entity> <entity class="Employee"> <attributes> <many-to-one name="employer" fetch="LAZY"> <join-column name="employer_id" nullable="false"/> </many-to-one> </attributes> </entity> </entity-mappings>
Annotations:
@Entity @Table(name="User_Table") @IdClass(UserId.class) public class User { public enum Type { MANAGER, REGULAR } @Id @Enumerated(EnumType.ORDINAL) private Type type; @Id @Column(length=20) private String username; @ManyToMany(fetch = FetchType.LAZY) @JoinTable(name = "User_Role", joinColumns = {@JoinColumn(name = "user_type", referencedColumnName = "type"), @JoinColumn(name = "username", referencedColumnName = "username")}, inverseJoinColumns = {@JoinColumn(name = "role_id")}) private List<Role> roles; } @Entity public class Role { @Id private Long id; } public class UserId { private Type type; private String username; // getter/setter, equals(), hashCode() }
Join Table foreign keys:
User_Table User_Role Role ------------------------------------------------------------------------ (type,username) <--- (user_type,username) (role_id) ---> (id)XML:
<entity-mappings> <entity class="User"> <table name="User_Table"/> <id-class class="UserId"/> <attributes> <id name="type"> <enumerated>ORDINAL</enumerated> </id> <id name="username"> <column length="20"/> </id> <many-to-many name="roles" fetch="LAZY"> <join-table name="User_Role"> <join-column name="user_type" referenced-column-name="type"/> <join-column name="username" referenced-column-name="username"/> <inverse-join-column name="role_id"/> </join-table> </many-to-many> </attributes> </entity> <entity class="Role"> <attributes> <id name="id"> </id> </attributes> </entity> </entity-mappings>
Annotations:
public class Employee { @ElementCollection(fetch=FetchType.EAGER) @CollectionTable(name="Employee_PhoneNumber") @Column(name="phoneNumber", length = 15) private List<PhoneNumber> phoneNumbers; }Collection table:
Employee Employee_PhoneNumber ------------------------------------ id <---- Employee_id, phoneNumberXML:
<entity-mappings> <entity class="Employee"> <attributes> <element-collection name="phoneNumbers" fetch="EAGER"> <column name="phoneNumber" length="15"/> <collection-table name="Employee_PhoneNumber"/> </element-collection> </attributes> </entity> </entity-mappings>
Annotations:
@Embeddable public class ZipCode { @Column(length = 5) private String majorCode; @Column(length = 4) private String minorCode; } @Embeddable public class Address { @Column(length = 50) private String street; @Column(length = 30) private String city; @Column(length = 20) private String state; @Embedded private ZipCode zipCode; } @Entity public class Employee { @Embedded private Address address; }ZipCode is embedded into Address which is embedded into Employee.
XML:
<entity-mappings> <embeddable name="ZipCode"/> <embeddable name="Address"> <attributes> <embedded name="zipCode"/> </attributes> </embeddable> <entity class="Employee"> <attributes> <embedded name="address"/> </attributes> </entity> </entity-mappings>
@MappedSuperclass public class Person { @Column(length = 30, nullable = false) private String name; @OneToOne /* default @JoinColumns({ @JoinColumn(name="user_type", referencedColumnName = "type"), @JoinColumn(name="user_username", referencedColumnName = "username") }) */ private User user; } @Entity @AttributeOverride(name = "name", column = @Column(length = 32, nullable = false)) @AssociationOverride(name = "user", joinColumns = { @JoinColumn(name = "userType", referencedColumnName = "type"), @JoinColumn(name = "username", referencedColumnName = "username") } ) public class Employee extends Person { @Embedded @AttributeOverrides({ @AttributeOverride(name="zipCode.majorCode", column = @Column(name = "zipcode_major", length = 10, nullable = false)), @AttributeOverride(name="zipCode.minorCode", column = @Column(name = "zipcode_minor", length = 4, nullable = true)) }) private Address address; }ZipCode is embedded into Address which is embedded into Employee.
XML:
<entity-mappings> <mapped-superclass name="Person"> <attributes> <one-to-one name="user"/> </attributes> <mapped-superclass/> <entity class="Employee"> <attribute-override name="name"> <column length="32" nullable="false"/> </attribute-override> <association-override name="user"> <join-column name="userType" referenced-column-name="type"/> <join-column name="username" referenced-column-name="username"/> </association-override> <attributes> <embedded name="address"> <attribute-override name="zipCode.majorCode"> <column name="zip_code_major" length="6" nullable="false"/> </attribute-override> <attribute-override name="zipCode.minorCode"> <column name="zip_code_minor" length="4" nullable="true"/> </attribute-override> </embedded> </attributes> </entity> </entity-mappings>
Expressions #{expr} are supported in mapping table schema names and multitenant attributes, which can be resolved by its corresponding property (expression as property name) set in META-INF/persistence.xml or passed to Persistence.createEntityManagerFactory() method. Expressions are useful in case that ORM mappings are shared by multiple persistence units. For example,
orm.xml
<entity-mappings> <entity class="Employee"> <table schema="#{employee.schema}" name="Employee"/> <multitenant enabled="#{multitenant.enabled}"/> </entity> </entity-mappings>Method 1: Resolve expressions by setting properties in META-INF/persistence.xml:
<persistence> <persistence-unit name="pu_1" transaction-type="RESOURCE_LOCAL"> <mapping-file>orm.xml</mapping-file> <properties> <property name="employee.schema" value="hr" /> <property name="multitenant.enabled" value="true" /> </properties> </persistence-unit> <persistence-unit name="pu_2" transaction-type="RESOURCE_LOCAL"> <mapping-file>orm.xml</mapping-file> <properties> <property name="employee.schema" value="" /> <property name="multitenant.enabled" value="false" /> </properties> </persistence-unit> </persistence>Method 2: Resolve expressions by passing properties to the method of creating EntityManagerFactory:
// persistence unit 1 Map<String, Object> properties = new HashMap<>(); properties.put("employee.schema", "hr"); properties.put("multitenant.enabled", "true"); EntityManagerFactory emf = Persistence.createEntityManagerFactory("pu_1", properties); EntityManager em = emf.createEntityManager(); // persistence unit 2 Map<String, Object> properties = new HashMap<>(); properties.put("employee.schema", ""); properties.put("multitenant.enabled", "false"); EntityManagerFactory emf = Persistence.createEntityManagerFactory("pu_2", properties); EntityManager em = emf.createEntityManager();