【问题标题】:Spring CrudRepository implement interface?Spring CrudRepository 实现接口?
【发布时间】:2017-07-21 03:48:45
【问题描述】:

我目前正在学习 Spring CrudRepository。我为以后继承的其他类创建了一个基础存储库,下面是我的代码:

@NoRepositoryBean
public interface BaseRepository<T, ID extends Serializable> extends CrudRepository<T, ID>
{
}

我需要创建一个实现BaseRepository 接口的类吗?如果是,如何实施?有什么例子吗?或者我只是把它留空,Spring 会做这些工作?
我尝试使用如下简单代码:
LoginBean.java

@ManagedBean(name = "loginBean")
@RequestScoped
public class LoginBean
{
    private String username;
    private String password;

    @Autowired
    private AccountRepository accountRepository;

    public LoginBean()
    {
    }

    public void saveAcc()
    {
        System.out.println("Save Acc");
        accountRepository.save(new Account("username", "password", 1));
    }

    //getter and setter
}

但我得到NullPointerException

Warning:   java.lang.NullPointerException
javax.el.ELException: java.lang.NullPointerException
    at com.sun.el.parser.AstValue.invoke(AstValue.java:293)
    at com.sun.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:304)
    at org.jboss.weld.util.el.ForwardingMethodExpression.invoke(ForwardingMethodExpression.java:40)
    at org.jboss.weld.el.WeldMethodExpression.invoke(WeldMethodExpression.java:50)
    at javax.faces.event.MethodExpressionActionListener.processAction(MethodExpressionActionListener.java:149)
    at javax.faces.event.ActionEvent.processListener(ActionEvent.java:88)
    at javax.faces.component.UIComponentBase.broadcast(UIComponentBase.java:814)
    at javax.faces.component.UICommand.broadcast(UICommand.java:300)
    at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:790)
    at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1282)
    at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:81)
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
    at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:198)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:658)
    at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1682)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:318)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:160)
    at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:734)
    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:673)
    at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:99)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:174)
    at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:416)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:283)
    at com.sun.enterprise.v3.services.impl.ContainerMapper$HttpHandlerCallable.call(ContainerMapper.java:459)
    at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:167)
    at org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:206)
    at org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:180)
    at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:235)
    at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:283)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:200)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:132)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:111)
    at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
    at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:536)
    at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:112)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:117)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:56)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:137)
    at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:591)
    at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:571)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.NullPointerException
    at com.peter.uass.bean.LoginBean.saveAcc(LoginBean.java:55)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.sun.el.parser.AstValue.invoke(AstValue.java:289)
    ... 41 more

Severe:   java.lang.NullPointerException
    at com.peter.uass.bean.LoginBean.saveAcc(LoginBean.java:55)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.sun.el.parser.AstValue.invoke(AstValue.java:289)
    at com.sun.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:304)
    at org.jboss.weld.util.el.ForwardingMethodExpression.invoke(ForwardingMethodExpression.java:40)
    at org.jboss.weld.el.WeldMethodExpression.invoke(WeldMethodExpression.java:50)
    at javax.faces.event.MethodExpressionActionListener.processAction(MethodExpressionActionListener.java:149)
    at javax.faces.event.ActionEvent.processListener(ActionEvent.java:88)
    at javax.faces.component.UIComponentBase.broadcast(UIComponentBase.java:814)
    at javax.faces.component.UICommand.broadcast(UICommand.java:300)
    at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:790)
    at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1282)
    at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:81)
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
    at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:198)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:658)
    at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1682)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:318)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:160)
    at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:734)
    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:673)
    at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:99)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:174)
    at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:416)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:283)
    at com.sun.enterprise.v3.services.impl.ContainerMapper$HttpHandlerCallable.call(ContainerMapper.java:459)
    at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:167)
    at org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:206)
    at org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:180)
    at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:235)
    at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:283)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:200)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:132)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:111)
    at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
    at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:536)
    at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:112)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:117)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:56)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:137)
    at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:591)
    at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:571)
    at java.lang.Thread.run(Thread.java:745)

更新
好的,我找到了问题,NullPointerException 是因为我的 autowired accountRepository 为空,知道吗?

【问题讨论】:

  • 因为您明确地将BaseRepository 标记为@NoRepositoryBean,所以Spring Data 当然不会为它创建一个bean。你到底想做什么?您应该为您的帐户创建一个接口(即interface AccountRepository extends BaseRepository&lt;Account, WHATEVER&gt; 并注入它。
  • 是的,因为您明确将 BaseRepository 标记为 @NoRepositoryBean,您应该实现它,我建议创建使用您想要实现的额外方法实现它的存储库类。
  • 我创建了 AccountRepository 接口,我仍然得到NullPointerException,我的班级:@Repository public interface AccountRepository extends BaseRepository&lt;Account, Integer&gt;{}
  • 为什么要创建中间接口而不是直接扩展CrudRepository
  • 您想通过BaseRepository 实现什么目标?否则很难帮助您解决问题

标签: java spring spring-data


【解决方案1】:

基本存储库接口必须扩展由存储库接口扩展的相同接口。换句话说,如果您的存储库接口扩展了 CrudRepository 接口,则 BaseRepository 接口也必须扩展它。

public class BaseRepositoryImpl <T, ID extends Serializable>
        extends SimpleJpaRepository<T, ID>  implements BaseRepository<T, ID> {



  private final EntityManager entityManager;

    public BaseRepositoryImpl(Class<T> domainClass, EntityManager entityManager) {
        super(domainClass, entityManager);
        this.entityManager = entityManager;
    }

    @Transactional
    @Override
    public Optional<T> deleteById(ID id) {
        T deleted = entityManager.find(this.getDomainClass(), id);
        Optional<T> returned = Optional.empty();

        if (deleted != null) {
            entityManager.remove(deleted);
            returned = Optional.of(deleted);
        }
        return returned;
    }
}

更多内容可以参考以下链接:

https://www.petrikainulainen.net/programming/spring-framework/spring-data-jpa-tutorial-adding-custom-methods-into-all-repositories/

【讨论】:

  • 你的SimpleJpaRepository 班级是什么?
【解决方案2】:

顺便说一句,在您的情况下不需要BaseRepository&lt;T, ID extends Serializable&gt;,因为您尚未在此存储库中定义任何新方法。因此,您可以为每个直接扩展 CrudRepository 的实体创建一个接口。 注意:

@Autowired
private BaseRepository baseRepository;

不起作用,因为您已经将 BaseRepository 标记为 @NoRepositoryBean

所以只需为您的实体创建一个接口,例如实体AccountDetail,您可以执行以下操作:

@Repository
public interface AccountDetailRepository extends CrudRepository<AccountDetail, String>
{
  //Can add any custom method you want, but not necessary.
}

最后像这样使用它:

@Autowired
private AccountDetailRepository accountRepository;
public void saveAcc()
{
    System.out.println("Save Acc");
    accountRepository.save(new AccountDetail("username", "password", 1));
}

【讨论】:

  • 我仍然收到错误javax.el.ELException: java.lang.NullPointerException
  • @Newbie 您是否为要在其中自动装配 AccountDetailRepository 对象的类创建了 bean?
  • 已更新完整的错误堆栈。那是什么豆子?我在我的loginBean 中调用saveAcc() 函数,有关于如何正确执行此操作的指南吗?抱歉,我是 JSF、Hibernate 和 Spring 的新手
【解决方案3】:

要使用 Spring Data JPA 存储库,您不需要实现它们。您可以扩展它们:

public interface MyEntityRepo extends JpaRepository<MyEntity, Integer> {
}

其中MyEntity 是您要从数据库中存储/读取的实体,IntegerMyEntity 主键类型,由@Id 注释标记:

@Entity
public class MyEntity {

    @Id
    @GeneratedValue
    private Integer id;

    // fields, getters, setters and other stuff
}

创建 repo 接口时,您可以使用扩展存储库提供的所有基本方法:savedeletefindAll 和其他(参见 javadocs:JpaRepositoryPagingAndSortingRepositoryCrudRepository ...)。

要使用 repo 方法,您只需将 repo 注入 repo 变量,例如:

@Transactional
@Service
public class MyEntityService {

    @Autoware
    private MyEntityRepo repo;

    @Transactional(readOnly = true)
    public List<MyEntity> findAll() {

        return repo.findAll();
    }  

    public void save(MyEntity entity) {

        repo.save(entity);
    }

    public void delete(MyEntity entity) {

        repo.delete(entity);
    }
}

更多信息:

【讨论】:

  • 我有一个疑问,spring 实例化类对吗??那么我们如何使用 autowired 作为接口的参考呢??
猜你喜欢
  • 2015-03-07
  • 2015-07-18
  • 2019-04-09
  • 2018-11-29
  • 2017-08-18
  • 2015-10-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多