我正在编写Java程序,它通过Hibernate与Db交互。
我所有的持久类都从实现接口IEntity
的公共抽象类Entity
扩展而来。例如:
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 的操作,我创建了存储库类,这些存储库类使用所有实体的标准 CRUD 方法从Repository<T extends IEntity>
扩展,此类实现了接口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>
我希望此方法应该返回存储库for
用户对象。
在我看来,这可以通过两种方式实现:
- 优雅。创建
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)
比较类。