I would like to have a generic method performing a SELECT * FROM entity<T> WHERE entity<T>.primaryKey = method_parameter
that I can use on every entity of my domain code.
So far I have this nongeneric method. It returns a list which will always only have one element because the primary keys are unqiue:
public static List<App> selectOneApp(int appid) {
Session session = HibernateSessionFactory.getFactory().openSession();
List<App> list = null;
Transaction tx = null;
try {
tx = session.beginTransaction();
CriteriaBuilder builder = session.getCriteriaBuilder();
CriteriaQuery<App> criteria = builder.createQuery(App.class);
Root<App> root = criteria.from(App.class);
criteria.select(root);
criteria.where(builder.equal(root.get(App_.appId), appid));
//equivalent to WHERE App.appid = appid
list = session.createQuery(criteria).getResultList();
tx.commit();
} catch (HibernateException e) {
if (tx != null)
tx.rollback();
log.error(e);
} finally {
session.close();
}
return list;
}
I would like it to be somehow like this:
public static <T> List<T> selectOneRow(int key, Class<T> clazz) {
Session session = HibernateSessionFactory.getFactory().openSession();
List<T> list = null;
Transaction tx = null;
try {
tx = session.beginTransaction();
CriteriaBuilder builder = session.getCriteriaBuilder();
CriteriaQuery<T> criteria = builder.createQuery(clazz);
Root<T> root = criteria.from(clazz);
criteria.select(root);
criteria.where(builder.equal(root.get(clazz_.Id), key));
// I got stuck here. How can I pass a generic key?
list = session.createQuery(criteria).getResultList();
tx.commit();
...
return list;
}
I use hibernate's code generator to generate the domain code automatically. From that I genererate the JPA metamodel and everything is nice and typesafe.
I was thinking I would have to generate some kind of inheritence structure where the parent class only has a get() method and a primary key. All the entity classes that want to use this generic select method then inherit from that parent class. But I am not sure how to do that or if it is even possible.
This question was my reference but it is missing the criteria.where part: Java class - how to pass Generic Object to a function
Snippet from my data model:
CREATE TABLE app_type(
appTypeID TINYINT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
app_type_name VARCHAR(32)
);
CREATE TABLE app(
appID INT UNSIGNED NOT NULL PRIMARY KEY,
app_name VARCHAR(191),
appTypeID TINYINT UNSIGNED,
pubID INT UNSIGNED,
CONSTRAINT fk_app_appType_appTypeID
FOREIGN KEY (appTypeID)
REFERENCES app_type(appTypeID)
ON UPDATE CASCADE);
CREATE TABLE publisher(
pubID INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
publisher_name VARCHAR(191));
CREATE TABLE ref_app_publisher(
appID INT UNSIGNED NOT NULL,
pubID INT UNSIGNED NOT NULL,
PRIMARY KEY(appID, pubID),
UNIQUE INDEX ux_refAppPublisher_pubID_appID (pubID, appID),
CONSTRAINT fk_refAppPublisher_app_appID
FOREIGN KEY (appID)
REFERENCES app(appID)
ON UPDATE CASCADE,
CONSTRAINT fk_refAppPublisher_publisher_pubID
FOREIGN KEY (pubID)
REFERENCES publisher(pubID)
ON UPDATE CASCADE);
Thanks!