在 Java 中按实体类型检索存储库



我正在编写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用户对象。

在我看来,这可以通过两种方式实现:

  1. 优雅。创建IRepository方法 -Class<T> getEntityClass然后比较输入的类和getEntityClass的结果
  2. 笨。在此方法中执行许多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)比较类。

最新更新