我正在编写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)比较类。

09-10 02:53
查看更多