我想要一个通用方法来执行 SELECT * FROM entity<T> WHERE entity<T>.primaryKey = method_parameter
我可以在域代码的每个实体上使用它。
到目前为止,我有这个非通用方法。它返回一个列表,该列表始终只有一个元素,因为主键是唯一的:
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;
}
我希望它是这样的:
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;
}
我使用hibernate的代码生成器自动生成域代码。由此我生成了 JPA 元模型,一切都很好且类型安全。
我想我必须生成某种继承结构,其中父类只有一个 get() 方法和一个主键。所有想要使用此通用选择方法的实体类都从该父类继承。但我不确定如何做到这一点,或者是否可能。
这个问题是我的引用,但缺少标准。其中部分:Java class - how to pass Generic Object to a function
我的数据模型的片段:
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);
谢谢!
最佳答案
我成功了!
调用者将始终知道该操作应该作用于哪个类或实体。因此,诀窍是通过添加参数 ormClass
和 singularAttribute
来赋予调用者更多责任。
/**
* Select a single row from any ORM type. Returns a single result in a list
* or an empty list. Avoids NoResultException() from JPA's getSingleResult()
* method
*
* @param key
* The unique primary key to select.
* @param ormClass
* The ORM class to select.
* @param singularAttribute
* A JPA SingularAttribute<<ormType>, <primaryKey> data
* type> containing the mapping to the primary key.
* @return list The selected ORM type in a list. If no result the list is
* empty.
*/
public static <T, X> List<T> selectOneRow(int key, Class<T> ormClass,
SingularAttribute<T, X> singularAttribute) {
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(ormClass);
Root<T> root = criteria.from(ormClass);
criteria.select(root);
criteria.where(builder.equal(root.get(singularAttribute), key));
list = session.createQuery(criteria).getResultList();
tx.commit();
} catch (HibernateException e) {
if (tx != null)
tx.rollback();
log.error(e);
} finally {
session.close();
}
return list;
}
注意:在将 SingularAttribute 作为参数传递时,我遇到了无法解释的 NullPointerException,这花了我一些时间才弄清楚。解决方案如下:Hibernate/JPA - NullPointerException when accessing SingularAttribute parameter
关于java - 能够对域代码的每个实体执行选择的通用方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41579417/