我正在编写Java程序,该程序通过Hibernate与Db交互。
我所有的持久类都从实现接口Entity
的通用抽象类IEntity
扩展而来。例如:
public interface IEntity {
long getId();
void setId(long id);
}
public abstract class Entity implements IEntity {
private long id;
//get + set id
}
public class User extends Entity {
private string name;
//get + set name
}
public class Item extends Entity {
private string description;
//get + set description
}
对于用Db进行的操作,我创建了存储库类,该库类从
Repository<T extends IEntity>
扩展为所有实体使用标准CRUD方法,并且该类实现接口IRepository<T extends IEntity>
:public interface IRepository<T extends IEntity> {
void create(T object) throws JDBCException;
//other CRUD operations
}
public abstract class Repository<T extends IEntity> implements IRepository<T> {
private final Class<T> entityClass;
protected final EntityManager entityManager;
public Repository(Class<T> entityClass, EntityManager entityManager) {
this.entityClass = entityClass;
this.entityManager = entityManager;
}
@Override
public void create(T object) throws JDBCException {
entityManager.getTransaction().begin();
entityManager.persist(object);
entityManager.getTransaction().commit();
}
//other CRUD operations implementation
}
public class UserRepository extends Repository<User> {
public UserRepository (EntityManager entityManager) {
super(AmountUnit.class, entityManager);
}
}
public class ItemRepository extends Repository<Item> {
public ItemRepository (EntityManager entityManager) {
super(AmountUnit.class, entityManager);
}
}
在我决定创建方法以通过其实体类获取特定存储库之前,这种结构一直有效。
我认为这种方法是这样的:
public <T extends IEntity, U extends IRepository<T>> U getByType(T object) {
// code here
}
假设该类
User extends Entity
并具有存储库类UserRepository extends Repository<User>
我期望这个方法应该返回Repository
for
User object`。我认为这可以通过两种方式实现:
优雅。为
IRepository
-Class<T> getEntityClass
创建方法然后比较输入类和getEntityClass的结果
笨。在此方法内编写许多
if/else
语句并返回存储库。 if(object instanceof A) return ARepository
public class Storage {
private IRepository<? extends IEntity>[] repositories;
public <T extends IEntity, U extends IRepository<T>> U getByTypeVar1(T object) {
for (IRepository<?> repo : repositories) {
if (object instanceof repo.getEntityClass ()) // cannot resolve getEntityClass
return repo;
}
}
public <T extends IEntity, U extends IRepository<T>> U getByTypeVar2(T object) {
if (object instanceof UserRepository.getEntityClass ())
return UserRepository; //incompatible type
//more if else here
}
}
但是这两个实现都无法编译。可能您有任何想法如何正确编写此方法
最佳答案
您可以像这样实现getByType
方法(我更改了参数类型):
private List<IRepository<? extends IEntity>> repositories;
@SuppressWarnings("unchecked")
public <E extends IEntity> IRepository<E> getByType(Class<E> entityClass) {
for (IRepository<?> repository : repositories) {
if (repository.getEntityClass().equals(entityClass)) {
return (IRepository<E>) repository;
}
}
throw new IllegalArgumentException(
"No repository for entity class " + entityClass.getName());
}
当您发布无法编译的代码时,我们可以找出问题出在哪里。
更新(代码注释)
您应该将
getEntityClass()
方法添加到IRepository
。为了减少代码复杂度,您可以替换:
<T extends IEntity, U extends IRepository<T>> U getByType()
与
<T extends IEntity> IRepository<T> getByType getByType()
在中使用
instanceof
object instanceof repo.getEntityClass ()
可能会有问题,因为您可以具有实体层次结构,并且可以为对象获得错误的(子类)存储库。如果您不知道该对象的类,则可以通过以下方式获取它(该对象可以是Hibernate代理):
org.hibernate.Hibernate.unproxy(object).getClass()
然后按
repository.getEntityClass().equals(entityClass)
比较类。