在使用 jpa 的 jax-rs 休息服务中使用泛型的障碍
Roadblock using generics in jax-rs rest services using jpa
我正在编写一个公开关系数据库的休息服务。我在应用程序中有三层:
- 持久层(JPA 实体)
- EJB 层
- 休息层
对于每个实体,我正在实施的方法是:add
、update
、findAll
、findById
。我在 Rest 层 和 EJB 层 中都使用了 Java 泛型,以便编写尽可能少的代码。
但是我在实现方法 findById
的 EJB 层 遇到了障碍,因为数据库的一些实体有一个 Integer
类型的主键,其他人有一个 String
类型的主键。通用EJB实现如下:
public abstract class SimpleEJB <T extends Object> {
//This entity is injected by the container.
@PersistenceContext(name="PersistenceUnit")
private EntityManager em;
private Class<?> TClass;
public SimpleEJB(Class<?> entityClass){
this.TClass = entityClass;
}
public T findById(String id){
T t = this.em.find(this.TClass, id);
return t;
}
}
我不想为我可能找到的每个不同的主键类型(整数、字符串、日期等)编写摘要 类(在 rest 层和 ejb 层上)。由于其余层接收主键作为 url 中的 String
,我是否可以将 String
传递给 EJB 层,并将 find
方法 [=21] =] 自动将 String
转换为 T 的类型,还是我被迫为每个不同的主键类型编写不同的摘要 类?
旁注:我无法更改数据库。
我认为您可以对 TClass
做一些反思以获得 id
字段的类型(假设这是 "id" 字段的通用名称)和只是有条件地设置 PK 为 check 。像
public T findById(String id) throws Exception {
Field idField = TClass.getDeclaredField("id");
Class<?> type = idField.getType();
Object pk = id;
if (type == Integer.class) {
pk = Integer.parseInt(id);
}
return manager.find(TClass, pk);
}
对于更通用的方法(您不需要知道字段的名称),您可以选择检查所有字段上的 @Id
注释。有注解的就是你要解析的类型。例如
public T findById(String id) throws Exception {
Field[] declaredFields = TClass.getDeclaredFields();
Field idField = null;
for (Field field: declaredFields) {
if (field.isAnnotationPresent(Id.class)) {
idField = field;
break;
}
}
if (idField == null) {
throw new IllegalStateException("No field annotated with @Id");
}
Class<?> type = idField.getType();
Object pk = id;
if (type == Integer.class) {
pk = Integer.parseInt(id);
}
return manager.find(TClass, pk);
}
我正在编写一个公开关系数据库的休息服务。我在应用程序中有三层:
- 持久层(JPA 实体)
- EJB 层
- 休息层
对于每个实体,我正在实施的方法是:add
、update
、findAll
、findById
。我在 Rest 层 和 EJB 层 中都使用了 Java 泛型,以便编写尽可能少的代码。
但是我在实现方法 findById
的 EJB 层 遇到了障碍,因为数据库的一些实体有一个 Integer
类型的主键,其他人有一个 String
类型的主键。通用EJB实现如下:
public abstract class SimpleEJB <T extends Object> {
//This entity is injected by the container.
@PersistenceContext(name="PersistenceUnit")
private EntityManager em;
private Class<?> TClass;
public SimpleEJB(Class<?> entityClass){
this.TClass = entityClass;
}
public T findById(String id){
T t = this.em.find(this.TClass, id);
return t;
}
}
我不想为我可能找到的每个不同的主键类型(整数、字符串、日期等)编写摘要 类(在 rest 层和 ejb 层上)。由于其余层接收主键作为 url 中的 String
,我是否可以将 String
传递给 EJB 层,并将 find
方法 [=21] =] 自动将 String
转换为 T 的类型,还是我被迫为每个不同的主键类型编写不同的摘要 类?
旁注:我无法更改数据库。
我认为您可以对 TClass
做一些反思以获得 id
字段的类型(假设这是 "id" 字段的通用名称)和只是有条件地设置 PK 为 check 。像
public T findById(String id) throws Exception {
Field idField = TClass.getDeclaredField("id");
Class<?> type = idField.getType();
Object pk = id;
if (type == Integer.class) {
pk = Integer.parseInt(id);
}
return manager.find(TClass, pk);
}
对于更通用的方法(您不需要知道字段的名称),您可以选择检查所有字段上的 @Id
注释。有注解的就是你要解析的类型。例如
public T findById(String id) throws Exception {
Field[] declaredFields = TClass.getDeclaredFields();
Field idField = null;
for (Field field: declaredFields) {
if (field.isAnnotationPresent(Id.class)) {
idField = field;
break;
}
}
if (idField == null) {
throw new IllegalStateException("No field annotated with @Id");
}
Class<?> type = idField.getType();
Object pk = id;
if (type == Integer.class) {
pk = Integer.parseInt(id);
}
return manager.find(TClass, pk);
}