简体   繁体   English

春季通用道类名称

[英]Spring Generic Dao class name

I have configured a custom generic service DAO for my spring / hibernate project - the idea being that I can reuse it easily from my controllers. 我已经为我的spring / hibernate项目配置了一个自定义的通用服务DAO-这个想法是我可以从控制器中轻松地重用它。

It essentially looks like this: 基本上看起来像这样:

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();
}
...

Which gets referenced by: 被哪个引用:

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

However the String clip = e.getName() line throws a Null pointer exception. 但是, String clip = e.getName()行会引发Null指针异常。 I can get this to work if I move the class into the attributes section (so addressService.get(Address.class, 1) but I find this somewhat untidy, especially when there are multiple different classes being called upon. 如果将类移到属性部分(所以addressService.get(Address.class, 1) ,我可以使它addressService.get(Address.class, 1)但是我发现这有点不整洁,尤其是在调用多个不同的类时。

Is there some way to get the class to generate a value correctly without repeatedly adding it into all my functions? 有什么方法可以让类正确地生成一个值,而无需将其重复添加到我的所有函数中?

Thanks in advance. 提前致谢。

I did something similar, you need the generic class to be a constructor argument as well, mine uses hibernate entities, but you could pass in the string of table name. 我做了类似的事情,您也需​​要将通用类也用作构造函数参数,我的也使用休眠实体,但是您可以传入表名的字符串。

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);
    }

You can then subclass (if you need to) to customize or simply set up you bean in the spring config like below t : 然后,您可以子类化(如果需要)以自定义或简单地在spring配置中设置bean,如t所示:

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

So in your code you could then reference tagRepository like so (no other cod eis needed than that posted above, and below) : 因此,在您的代码中,您可以像这样引用tagRepository(除了上面和下面发布的代码之外,不需要其他编码):

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

Also, I would call it a repository not a service, a service deals with different types and their interactions (not just one). 另外,我将其称为存储库而不是服务,服务处理不同的类型及其交互(而不仅仅是一个)。 And for specifically your example using SQL strings : 特别是您使用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();
}

and have your beans defined like so 并像这样定义您的豆子

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

And then you can alsow create subclasses youself where necessary : 然后,您还可以根据需要自己创建子类:

public class PersonRepository extends DomainRepository<Person> {
    public PersonRepository(){
        super("person"); //assumes table name is person
    }

As I understand you got NPE because you did not set any value for this field. 据我了解,您之所以获得NPE,是因为您没有为此字段设置任何值。 So you can resolve this problem by 2 ways: 因此,您可以通过两种方法解决此问题:

  1. Set manually class object as in comment NimChimpsky. 如注释NimChimpsky中所述手动设置类对象。
  2. Get class type dynamically. 动态获取类类型。 Eg, if you use Spring try this one: 例如,如果您使用Spring,请尝试以下一种方法:

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

or some workaround here 这里的一些解决方法

It's better to define a specific class for Address service 最好为地址服务定义一个特定的类

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

where 哪里

public String getClassName();

is an abstract method declared in DefaultService, and used (like your method className()) in your data access logic. 是在DefaultService中声明的抽象方法,并在数据访问逻辑中使用(类似于方法className())。

Using this approach, you will be able to add specific data access logic (example, getUsersByAddress) 使用这种方法,您将能够添加特定的数据访问逻辑(例如,getUsersByAddress)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM