如何使用Spring Data JPA在没有HTTP请求的情况下调用持久化方法?

du7egjpx  于 11个月前  发布在  Spring
关注(0)|答案(2)|浏览(135)

我是Spring Data JPA的新手,我遇到了一些.新手问题。
我不能调用一个没有注解 @Controller 的持久化方法,或者 HTTP requests 的注解在我的类中。我知道类接口 CommandLineRunner 实现了一个方法 run,但是主代码需要留在方法 run 中,我想调用另一个类和自己的方法,就像一个facade行为。

型号:

package com.example.demo;

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;

@Entity
public class Expense {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String item;
    private float amount;

    public Expense () {
        
    }
    
    public Expense(String item, float amount) {
        this.item = item;
        this.amount = amount;
    }

    /* Getters and setters */

    @Override
    public String toString() {
        return "Expense{" + "id=" + id + ", item=" + item + ", amount=" + amount + '}';
    }

字符串

接口仓库

package com.example.demo;

import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

@Repository
public interface ExpenseRepository extends JpaRepository<Expense, Long>{
    
    public List<Expense> findByItem (String item);
    
    @Query("SELECT e FROM Expense e WHERE e.amount >= :amount")
    public List<Expense> listItemsWithPriceOver(@Param("amount") float amount);
    
}

持久化类:

package com.example.demo;

import org.springframework.beans.factory.annotation.Autowired;

public class ExpansePersistence {

    @Autowired
    private ExpenseRepository repository;

    public void expensePersistence() {
        repository.save(new Expense("tomato", 10));
        repository.save(new Expense("banana", 6));
        repository.save(new Expense("apple", 12));
        
        Iterable<Expense> iterator = repository.findAll();

        System.out.println("List all: ");
        iterator.forEach(item -> System.out.println(item.toString()));
    }
    
}

主要方法

package com.example.demo;

import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication implements CommandLineRunner {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

    @Override
    public void run(String... args) throws Exception {
        new ExpensePersistence().expensePersistence();
    }

}


这里有一个类似的线程(How to call repository service in main class and use main arguments?),用户遇到了同样的问题和同样的输出错误,但是答案只解决了 *run * 方法,使用了接口 CommandLineRunner,但在run方法内部进行了编码。我想调用另一个方法。
运行的代码生成消息:

Caused by: java.lang.NullPointerException: Cannot invoke "com.example.demo.ExpenseRepository.findAll()" because "this.repository" is null

mftmpeh8

mftmpeh81#

这是因为你的ExpansePersistence类的示例没有ExpenseRepository类的注入示例- Spring IoC容器不能做到这一点。你应该声明ExpansePersistence类的bean(例如使用@Service annotation),让它实现CommandLineRunner会更好。类似这样:

@Service
public class ExpansePersistence implements CommandLineRunner {

    ...

    @Override
    public void run(String... args) throws Exception {
        expensePersistence();
    }
}

字符串
然后ExpansePersistenceExpenseRepository都将由Spring IoC控制,bean注入将按预期工作。

pgx2nnw8

pgx2nnw82#

在您提供的示例中,TestPersistence是一个单元测试。这意味着它不能识别@Autowired这样的注解(因为它没有spring上下文)。您需要一个@SpringBootTest才能自动连接beans(在您的示例中是repository)。在这个tutorial中,您可以找到一个使用@SpringBootTest测试repository的示例。
祝你好运!

相关问题