With JDO and JPA APIs you have the ability to find individual objects using their “identity”. This “identity” may be a field value for a single field that defines the primary key, or may be an identity object representing a composite primary key made up of multiple fields.
Some classes have other field(s) that are known to be unique for the particular class (termed in some places as “natural id”, or “unique key”), and so it makes sense to allow the user to find objects using these unique key(s). In the latest release (5.1.0 M2) we provide access to this mechanism. Be aware that this is a vendor extension and so you have to make use of DataNucleus classes (and hence not portable until included in the JDO / JPA specs).
Lets take an example, we have a class representing a driving license. We represent this with an identity that is a unique number. We also have a unique key that is what the driver is provided with.
With JDO the class is
@PersistenceCapable public class DrivingLicense { @PrimaryKey long id; String driverName; @Unique String number; }
Consequently we can do as follows to get an object using its identity.
DrivingLicense license = pm.getObjectById(DrivingLicense.class, 1);
retrieving the license with id 1. If however we want to use the new retrieval via unique key we do this
JDOPersistenceManager jdopm = (JDOPersistenceManager)pm; DrivingLicense license = jdopm.getObjectByUnique(DrivingLicense.class, {"number"}, {"ABCD-1234"});
retrieving the license with number set to “ABCD-1234”. See the JDO docs.
Using JPA for the same example we have
@Entity public class DrivingLicense { @Id long id; String driverName; @Column(unique=true) String number; }
To get an object using its identity we do
DrivingLicense license = em.find(DrivingLicense.class, 1);
and to get an object using its unique key we do
JPAEntityManager jpaem = (JPAEntityManager)em; DrivingLicense license = jpaem.findByUnique(DrivingLicense.class, {"number"}, {"ABCD-1234"});
See the JPA docs.
Notes:
- You can have as many unique keys as you want on a class, and this mechanism will support it, unlike with Hibernate “NaturalId” where you can only have 1 per entity.
- You use standard JDO/JPA annotations/XML to define the unique key(s), unlike with Hibernate “NaturalId” where you have to use a vendor specific annotation.
- If your unique key is made up on multiple fields then you simply specify multiple field name(s) to the second argument in the call, and multiple field value(s) to the third argument in the call.