2

我已经为我的 spring/hibernate 项目配置了一个自定义的通用服务 DAO——我的想法是我可以从我的控制器中轻松地重用它。

它基本上看起来像这样:

public class DefaultService<T> {

private Class<T> e;

public String className(Class<T> e) {
    String clip = e.getName();
    clip = clip.substring(clip.lastIndexOf('.') + 1, clip.length());
    return clip;
}
public List<T> getAll(Integer status) {
    Session session = sessionFactory.getCurrentSession();
    Query query = session.createQuery("FROM " + className(e) + " WHERE status = " + status);
    return query.list();
}
...

哪个被引用:

@Autowired
public DefaultService<Address> addressService;
addressService.get(1);

但是,该String clip = e.getName()行会引发 Null 指针异常。如果我将类移动到属性部分,我可以让它工作(所以addressService.get(Address.class, 1)但我发现这有点不整洁,特别是当有多个不同的类被调用时。

有什么方法可以让类正确生成一个值,而无需重复将其添加到我的所有函数中?

提前致谢。

4

3 回答 3

5

我做了类似的事情,您也需​​要泛型类作为构造函数参数,我的使用休眠实体,但您可以传入表名字符串。

public class DomainRepository<T> {

    @Resource(name = "sessionFactory")
    protected SessionFactory sessionFactory;

 public DomainRepository(Class genericType) {
        this.genericType = genericType;
    }

 @Transactional(readOnly = true)
    public T get(final long id) {
        return (T) sessionFactory.getCurrentSession().get(genericType, id);
    }

然后,您可以子类化(如果需要)来自定义或简单地在 spring 配置中设置您的 bean,如下所示:

<bean id="tagRepository" class="com.yourcompnay.data.DomainRepository">
        <constructor-arg value="com.yourcompnay.domain.Tag"/>
</bean>

因此,在您的代码中,您可以像这样引用 tagRepository (除了上面和下面发布的代码之外,不需要其他代码 eis):

@Resource(name = "tagRepository")
private DomainRepository<Tag> tagRepository;

此外,我将其称为存储库而不是服务,服务处理不同类型及其交互(不仅仅是一个)。特别是您使用 SQL 字符串的示例:

public final String tableName;
public DomainRepository(String tableName) {
      this.tableName = tableName;
}
public List<T> getAll(Integer status) {
    Session session = sessionFactory.getCurrentSession();
    Query query = session.createQuery("FROM " + tableName + " WHERE status = " + status);
    return query.list();
}

并像这样定义你的豆子

<bean id="addressRepository" class="com.yourcompnay.data.DomainRepository">
  <constructor-arg value="address"/>
</bean>

然后你也可以在必要时自己创建子类:

public class PersonRepository extends DomainRepository<Person> {
    public PersonRepository(){
        super("person"); //assumes table name is person
    }
于 2013-02-21T13:01:56.023 回答
0

据我了解,您之所以获得 NPE,是因为您没有为此字段设置任何值。所以你可以通过两种方式解决这个问题:

  1. 手动设置类对象,如注释 NimChimpsky。
  2. 动态获取类类型。例如,如果你使用 Spring 试试这个:

protected Class getEntityClass() { return GenericTypeResolver.resolveTypeArguments(getClass(), DefaultService.class)[0]; }

这里的一些解决方法

于 2013-02-21T13:08:39.513 回答
0

最好为地址服务定义一个特定的类

public class AddressService extends DefaultService<Address>{
  public String getClassName(){
   return "Address";
  }
}

在哪里

public String getClassName();

是在 DefaultService 中声明的抽象方法,并在数据访问逻辑中使用(如您的方法 className())。

使用这种方法,您将能够添加特定的数据访问逻辑(例如,getUsersByAddress)

于 2013-02-21T13:18:08.637 回答