具有编程 bean 创建功能的通用 Java 服务不会注入 EntityManager

发布于 2024-10-27 20:47:06 字数 3624 浏览 5 评论 0原文

我有一个(希望)标准设置,其中包含一堆 @Controller@Service@Entity@Repository< /code> 带注释的类,例如:

@Service
public class ChannelManager {
    @Autowired
    private ChannelDao channelDao;

    public List<Channel> allChannels() {
        return channelDao.findAll();
    }
}

其中 ChannelDao 是:

public interface ChannelDao extends PersistentDao<Channel> {}

ChannelImpl 是:

@Repository
public class ChannelImpl extends PersistentImpl<Channel> implements ChannelDao {}

Channel 是:

@Entity
@Table(name = "channel")
public class Channel extends Persistent {
    @Id
    @Column(name = "id", nullable = false)
    private Long id;
    // set/get
}

PersistentDao 是:

public interface PersistentDao<T extends Persistent> {
    public List<T> findAll();
}

最后,PersistentImpl 是:

public class PersistentImpl<T extends Persistent> implements PersistentDao<T> {
    @PersistenceContext
    protected EntityManager entityManager;

    private Class<T> clazz; // gets assigned correctly

    public List<T> findAll() {
        return entityManager.createQuery("from " + clazz.getSimpleName()).getResultList();
    }
}

所有这些都按预期工作。我正在使用 以及 persistence.xml。基本上一切都有效。

但现在我想概括 ChannelManager,因为我有许多其他实体并且希望避免重复。例如,我还需要一个带有 List的 JobManager 。 allJobs() { 返回 jobDao.findall(); } 方法。

所以我创建了这个:

@Service
public class GeneralManager<T extends PersistentDao, E extends Persistent>  {
    @Autowired
    private AutowireCapableBeanFactory factory;
    public void setFactory(AutowireCapableBeanFactory factory) {
        this.factory = factory;
    }

    private Class<? extends T> impl;
    private T dao;

    public GeneralManager(Class<? extends T> impl) throws Exception {
        this.impl = impl;
    }

    @PostConstruct
    public void postCtor() {
        dao = factory.createBean(impl); // seems to be created and is not null
    }

    public List<E> all() {
        return dao.findAll();
    }
}

我更新了 context.xml

<bean id="jobImpl" class="a.b.c.GeneralManager">
    <property name="factory" ref="autowireFactory"/>
    <constructor-arg value="a.b.c.JobImpl"/>
</bean>

<bean id="autowireFactory" class="org.springframework.beans.factory.support.DefaultListableBeanFactory"/>

<context:annotation-config/>
  <context:component-scan base-package="a.b.c">
    <context:exclude-filter type="regex" expression=".*GeneralManager"/>
</context:component-scan>

最后在控制器中添加了一个声明:

@Autowired
@Qualifier(value="jobImpl")
private GeneralManager<JobDao, Job> jobManager;

想象一下 Jobxxx 类与 Channelxxx 类类似。

但是,当执行 JobImpl 专门化中的 findAll() 方法时,entityManager 为 null,因此未设置某些内容正确。

所以我的问题确实是“这可以做到吗”?不过,如果有其他更好的方法来做到这一点,请启发我!

编辑:可能值得注意的是,我正在使用 Spring 3.0.5、Java 1.6.0_21-b07 和 Hibernate 3.6.2.Final

I have a (hopefully) standard set-up with a bunch of @Controller, @Service, @Entity and @Repository annotated classes, for example:

@Service
public class ChannelManager {
    @Autowired
    private ChannelDao channelDao;

    public List<Channel> allChannels() {
        return channelDao.findAll();
    }
}

where ChannelDao is:

public interface ChannelDao extends PersistentDao<Channel> {}

ChannelImpl is:

@Repository
public class ChannelImpl extends PersistentImpl<Channel> implements ChannelDao {}

Channel is:

@Entity
@Table(name = "channel")
public class Channel extends Persistent {
    @Id
    @Column(name = "id", nullable = false)
    private Long id;
    // set/get
}

PersistentDao is:

public interface PersistentDao<T extends Persistent> {
    public List<T> findAll();
}

and finally PersistentImpl is:

public class PersistentImpl<T extends Persistent> implements PersistentDao<T> {
    @PersistenceContext
    protected EntityManager entityManager;

    private Class<T> clazz; // gets assigned correctly

    public List<T> findAll() {
        return entityManager.createQuery("from " + clazz.getSimpleName()).getResultList();
    }
}

All this works as expected. I am using <context:annotation-config/> and <context:component-scan/> as well as the <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" ...> with a persistence.xml. Basically it all works.

But now I want to generalize the ChannelManager since I have many other entities and want to avoid duplication. For example I also need a JobManager with a List<Job> allJobs() { return jobDao.findall(); } method.

So I created this:

@Service
public class GeneralManager<T extends PersistentDao, E extends Persistent>  {
    @Autowired
    private AutowireCapableBeanFactory factory;
    public void setFactory(AutowireCapableBeanFactory factory) {
        this.factory = factory;
    }

    private Class<? extends T> impl;
    private T dao;

    public GeneralManager(Class<? extends T> impl) throws Exception {
        this.impl = impl;
    }

    @PostConstruct
    public void postCtor() {
        dao = factory.createBean(impl); // seems to be created and is not null
    }

    public List<E> all() {
        return dao.findAll();
    }
}

And I updated the context.xml

<bean id="jobImpl" class="a.b.c.GeneralManager">
    <property name="factory" ref="autowireFactory"/>
    <constructor-arg value="a.b.c.JobImpl"/>
</bean>

<bean id="autowireFactory" class="org.springframework.beans.factory.support.DefaultListableBeanFactory"/>

<context:annotation-config/>
  <context:component-scan base-package="a.b.c">
    <context:exclude-filter type="regex" expression=".*GeneralManager"/>
</context:component-scan>

And finally added a declaration in the controller:

@Autowired
@Qualifier(value="jobImpl")
private GeneralManager<JobDao, Job> jobManager;

Just imagine the Jobxxx classes to be similar to the Channelxxx ones.

However, when it comes to execute the findAll() method in the JobImpl specialization, the entityManager is null, so something is not set-up correctly.

So my question really is "can this be done"? Although if there is an alternate and nicer way to do this please enlighten me!

Edit: Might be of note that I'm using Spring 3.0.5, Java 1.6.0_21-b07 and Hibernate 3.6.2.Final

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

木格 2024-11-03 20:47:06

因此,经过更多思考后,我通过显式定义 bean 走向了略有不同的方向,这是我试图避免的事情。但这对我有用。我仍然不知道我想做的事情是否因为类型擦除而无法实现。

我的代码现在看起来像:

public class GeneralManager<T extends PersistentDao, E extends Persistent>  {
    private T dao;
    public void setDao(T dao) {
        this.dao = dao;
    }
    ...
}

控制器使用:

@Autowired
private GeneralManager<ChannelDao, Channel> channelManager;

@Autowired
private GeneralManager<JobDao, Job> jobManager;

并且 context.xml 现在有:

<bean id="jobManager" class="com.a.b.service.EntityManager" p:dao-ref="jobImpl"/>
<bean id="jobImpl" class="com.a.b.dao.JobImpl"/>
<bean id="channelManager" class="com.a.b.service.EntityManager" p:dao-ref="channelImpl"/>
<bean id="channelImpl" class="com.a.b.dao.ChannelImpl"/>

希望这对某人有帮助!

So after thinking a bit more about it, I've gone in a slightly different direction by explicitly defining the beans which was something I was trying to avoid. But it is working for me. I still don't know if what I was trying to do was just not possible because of type erasure.

My code now looks like:

public class GeneralManager<T extends PersistentDao, E extends Persistent>  {
    private T dao;
    public void setDao(T dao) {
        this.dao = dao;
    }
    ...
}

with the controller using:

@Autowired
private GeneralManager<ChannelDao, Channel> channelManager;

@Autowired
private GeneralManager<JobDao, Job> jobManager;

and context.xml now has:

<bean id="jobManager" class="com.a.b.service.EntityManager" p:dao-ref="jobImpl"/>
<bean id="jobImpl" class="com.a.b.dao.JobImpl"/>
<bean id="channelManager" class="com.a.b.service.EntityManager" p:dao-ref="channelImpl"/>
<bean id="channelImpl" class="com.a.b.dao.ChannelImpl"/>

Hope this helps someone!

网名女生简单气质 2024-11-03 20:47:06

为什么不简单地使用 spring-data 项目呢?它完全可以满足您的需求,甚至更多。

why not simply use spring-data project? it does exactly what you need and more.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文