Generating JPA Entities OEPE allows you to generate JPA entities using the entity generation tool called OEPE JPA Entity Generation Wizard. Note that prior to using this tool, you should set up and configure the database connection, as well as add JPA support to your Eclipse project. Oct 19, 2019 Simply put, a composite primary key — also known as a composite key — is a key that contains two or more columns to form a primary key for the table. In this article, you'll learn how to map a composite primary key in a Spring Boot project using Spring Data JPA's both @IdClass and @EmbeddedId annotations.
Nov 26, 2017 Enter Artifact as “jpa-composite-primary-key-demo” Click Options dropdown to see all the options related to project metadata. Change Package Name to “com.example.jpa” Select Web, JPA and Mysql dependencies. Click Generate to generate and download the project. Following is the directory structure of the complete application for your reference.
Every JPA entity must have a primary key.
You can specify a primary key as a single primitive, or JDK object type entity field (see 'Configuring a JPA Entity Simple Primary Key Field').
You can specify a composite primary key made up of one or more primitive, or JDK object types using a separate composite primary key class (see 'Configuring a JPA Entity Composite Primary Key Class').
Generating public private key pairs for use in an application form. You can either assign primary key values yourself, or you can associate a primary key field with a primary key value generator (see 'Configuring JPA Entity Automatic Primary Key Generation'). Ms office 2010 home and business key generator reviews.
Configuring a JPA Entity Simple Primary Key Field
The simplest primary key is one you specify as a single primitive or JDK object type entity field (see 'Using Annotations').
Note:
For a JPA entity primary key field code example, see: http://www.oracle.com/technology/tech/java/oc4j/ejb3/howtos-ejb3/howtoejb30mappingannotations/doc/how-to-ejb30-mapping-annotations.html#id
Using Annotations
Example 7-1 shows how to use the
@Id
annotation to specify an entity field as the primary key. In this example, primary key values are generated using a table generator (see 'Configuring JPA Entity Automatic Primary Key Generation').Configuring a JPA Entity Composite Primary Key Class
A composite primary key is usually made up of two or more primitive or JDK object types. Composite primary keys typically arise when mapping from legacy databases when the database key is comprised of several columns. You can specify such a composite primary key with a separate composite primary key class (see 'Using Annotations')
A composite primary key class has the following characteristics:
- It is a POJO class.
- It must be public and must have a public no-argument constructor.
- If you use property-based access, the properties of the primary key class must be public or protected.
- It must be serializable.
- It must define
equals
andhashCode
methods.The semantics of value equality for these methods must be consistent with the database equality for the database types to which the key is mapped.
You can make the composite primary key class either an embedded class owned by the entity class, or a nonembedded class whose fields you map to multiple fields or properties of the entity class. In the latter case, the names of primary key fields or properties in the composite primary key class and those of the entity class must correspond and their types must be the same.
Using Annotations
Example 7-2 shows a typical embeddable composite primary key class. Example 7-3 shows how to configure a JPA entity with this embedded composite primary key class using the
@EmbeddedId
annotation.Example 7-2 Embeddable Composite Primary Key Class
Example 7-3 JPA Entity With an Embedded Composite Primary Key Class
Example 7-5 shows a nonembedded composite primary key class. In this class, fields
empName
and birthDay
must correspond in name and type to properties in the entity class. Example 7-5 shows how to configure a JPA entity with this nonembedded composite primary key class using the @IdClass
annotation. Because entity class fields empName
and birthDay
are used in the primary key, you must also annotate them using the @Id
annotation.Example 7-4 Non-Embedded Composite Primary Key Class
Example 7-5 JPA Entity With a Mapped Composite Primary Key Class
Configuring JPA Entity Automatic Primary Key Generation
Typically, you associate a primary key field (see 'Configuring a JPA Entity Simple Primary Key Field') with a primary key value generator so that when an entity instance is created, a new, unique primary key value is assigned automatically.
Table 7-2 lists the types of primary key value generators that you can define.
Table 7-2 JPA Entity Primary Key Value Generators
Type | Description | For more information, see .. |
---|---|---|
Generated Id Table | A database table that the container uses to store generated primary key values for entities. Typically shared by multiple entity types that use table-based primary key generation. Each entity type will typically use its own row in the table to generate the primary key values for that entity class. Primary key values are positive integers. | 'Table Sequencing' in the Oracle TopLink Developer's Guide |
Table Generator | A primary key generator, which you can reference by name, defined at one of the package, class, method, or field level. The level at which you define it will depend upon the desired visibility and sharing of the generator. No scoping or visibility rules are actually enforced. Oracle recommends that you define the generator at the level for which it will be used. This generator is based on a database table. | 'Table Sequencing' in the Oracle TopLink Developer's Guide |
Sequence Generator | A primary key generator which you can reference by name, defined at one of the package, class, method, or field level. The level, at which you define it, will depend upon the desired visibility and sharing of the generator. No scoping or visibility rules are actually enforced. Oracle recommends that you define the generator at the level for which it will be used. This generator is based on a sequence object that the database server provides. | 'Native Sequencing With an Oracle Database Platform' in the Oracle TopLink Developer's Guide 'Native Sequencing With a Non-Oracle Database Platform' in the Oracle TopLink Developer's Guide |
Note:
For an EJB 3.0 automatic primary key generation code example, see: http://www.oracle.com/technology/tech/java/oc4j/ejb3/howtos-ejb3/howtoejb30mappingannotations/doc/how-to-ejb30-mapping-annotations.html#sequencing
Using Annotations
Example 7-6 shows how to use the
@TableGenerator
annotation to specify a primary key value generator based on a database table. The TopLink JPA persistence provider will attempt to create this table at deployment time: if it cannot, then you must follow your database documentation to ensure that this table exists before deployment. When a new instance of Address
is created, a new value for entity field id
is obtained from ADDRESS_GENERATOR_TABLE
. In this case, you must set the @GeneratedValue
annotation attribute strategy
to TABLE
and generator
to ADDRESS_TABLE_GENERATOR
.Example 7-6 GeneratedValue Strategy Table: @TableGenerator
Example 7-7 shows how to use the
@SequenceGenerator
annotation to specify a primary key value generator based on a sequence object provided by the database. The TopLink JPA persistence provider will attempt to create this object at deployment time: if it cannot, then you must follow your database documentation to ensure that this sequence object exists before deployment. When a new instance of Address
is created, a new value for entity field id
is obtained from database sequence object ADDRESS_SEQ
. In this case, you must set the @GeneratedValue
annotation attribute strategy
to SEQUENCE
and generator
to ADDRESS_SEQUENCE_GENERATOR
.Example 7-7 GeneratedValue Strategy Sequence: @SequenceGenerator
Jpa Tools Generate Composite Key Tables For Kids
Example 7-8 shows how to use the
@GeneratedValue
annotation to specify a primary key value generator based on a primary key identity column (autonumber column). When a new instance of Address
is persisted, the database assigns a value to the identity column. In this case, the TopLink JPA persistence provider re-reads the inserted row and updates the in-memory Address
entity to set id
to this value.The issue of the legacy database schema
The problem definition
This tip starts with a simple description of the problem: defining a composite database key. This is a key that combines a number of columns to uniquely define the rows of a database table. Sometimes, composite keys are called natural keys or business keys. Composite keys are sometimes used because the choice of key relates in some way to the end-user business domain. To define a composite key, you simply take some attributes from the domain and combine them to provide the required degree of row uniqueness. The downside to composite keys is that they are a little difficult to design and code. Also, they tend to tie your database and ORM design to the original domain. The latter may or may not be a big issue.
Entity code
Listing 1 illustrates a Java class called
BillingAddress
. This class models the billing address for a person or an organization. The billing itself relates to another Java class called PurchaseOrder
. There's nothing too amazing here — a purchase order is placed and a billing process ensues.Listing 1. The BillingAddress
class
An important point to note is that the class implements the Java
Serializable
interface. Notice also the line with the annotation @Embeddable
. This annotation is the first piece of the composite key jigsaw puzzle. A Java class with the @Embeddable
annotation can itself become a subcomponent of another class. That sounds a lot more complicated than it is. To illustrate, Listing 2 shows the PurchaseOrder
class, which uses the BillingAddress
class from Listing 1.Listing 2. The PurchaseOrder
class
![Jpa tools generate composite key tables for sale Jpa tools generate composite key tables for sale](/uploads/1/2/5/8/125871187/694934000.png)
I always find annotations a bit hard to follow, and Listing 2 is no exception, so I'll break it down into manageable chunks. The first annotation is
@Entity
, which indicates that the class is a database entity (that is, it will form part of the ORM solution). Typically, when you see the @Entity
annotation, you can expect to see a corresponding database table. The latter is indicated by the next annotation — namely, @Table
. I find when you break down the process in this way, it becomes easier to understand.Next up in Listing 2 is the
@IdClass
annotation, which defines the composite key class reference. You may have noted that this annotation refers to the BillingAddress
class from Listing 1. Skipping past the constructors in Listing 2, notice the @Id
annotation. This is where the composite key is defined with nested @AttributeOverrides
annotations. These annotations are used to define the composite key columns: 'STREET' and 'CITY' respectively.Just after the annotations in Listing 2, can you spot two lines of duplicate code from Listing 1? The duplicate code is, of course, the two private data members for street and city. This duplication is required to create the composite key.
The database schema
So far, it's all been fairly technical. Now see this expressed in a more concrete fashion by generating a database schema. Listing 3 illustrates the schema from this ultra-simple ORM database design.
Listing 3. The database schema
You can see that the primary key is indeed a composite made up of the street and city fields. What does this look like in a real database — for example, one with a graphical user interface (GUI) tool? Before answering that, I write some simple client code to persist one or two entities to a database.
Listing 4 illustrates an excerpt of some code to instantiate objects of the classes defined earlier.
Listing 4. Some ORM client code
The code in Listing 4 illustrates the journey from
PurchaseOrder
object instantiation and setup all the way through to persistence of this object in the database. This really illustrates the magic that is ORM. Have a look at what happens.To begin with, an instance of
EntityManagerFactory
is created, and this is, in turn, used to create an instance of EntityManager
called em
. The latter is then used to write the PurchaseOrder
object instance to the database. The actual persistence into the database occurs as part of a transaction.A transaction is a set of atomic actions that either all occur successfully or are rolled back in the case of error. As you can see from Listing 4, the
EntityManager
object is used to create an instance of EntityTransaction
called tx
. It is the latter object that wraps the unit of work in a transaction.Notice the calls to
persist()
and commit()
. It's important to remember that no changes to the database occur unless both of these invocations occur. This is the simple pattern of the Java Persistence API (JPA).To complete the ORM tour, Figure 1 shows what the database looks like after running the code in Listing 4. The code was tested using an in-memory database called HSQLDB, and this product includes a simple GUI tool. The state of the HSQLDB database is shown in Figure 1. You can see that I ran an SQL query on the PURCHASE_ORDERS table. This table was created from the schema, which itself was created from the Java code in the earlier listings.
Figure 1. The populated database
In Figure 1, you can see the effect that this line of code from Listing 4 had:
purchaseOrder.setItemName('My new computer')
. The invocation of the setter code populated the associated column in the database row with the String data: 'My new computer.' In terms of workflow, you can think of the overall program run as the creation of a purchase order for a new computer followed by a billing process. All the steps in the workflow are implicitly stored in the database.Concluding comments about composite keys
The composite key defined in listings 1 and 2 allows you to bundle a number of columns together. The combination of columns then provides the required uniqueness so you can have an arbitrary number of rows in the database table. You've seen how it's done. Now, you need to briefly understand why one might take this quirky approach to database design.
Probably the most common reason for using composite keys is for backwards-compatibility. In other words, it occurs in those cases where you need to integrate new database code into a legacy environment. I think it's quite unusual to intentionally design a database this way nowadays, so it's likely you'll only need to create composite keys where it is a long-established practice.
In such cases, my experience is that it's pointless arguing against this approach. If composite keys are the standard, then that's not likely to change any time soon. In many cases, there may be masses of existing data already structured in this way. So, if a change is made from composite keys to numerical keys, then the legacy data has to be migrated. Also, there may be business processes that map onto the composite key data. The combination of all these factors may make composite key design a necessity.
Downloadable resources
Related topics
- Visit Sun's JPA wiki to learn more about the Java Persistence API for persistence and object/relational mapping for the Java EE platform.
- Go to the Hibernate site for background reading, code downloads, and more.
- Follow developerWorks on Twitter.
- Download IBM product evaluation versions and get your hands on application development tools and middleware products from DB2®, Lotus®, Rational®, Tivoli®, and WebSphere®.