#java #spring-boot #spring-data-jpa
#java #spring-boot #spring-data-jpa
Вопрос:
У меня есть приложение Spring Boot с JPA Spring Data и двумя объектами, сопоставленными с базой данных. Мое приложение настроено на воссоздание базы данных при каждом запуске. Теперь я хочу создать несколько экземпляров этих POJO, сохранить их в базе данных, чтобы у меня были некоторые данные для тестирования моего приложения в текущем процессе разработки.
Каков наилучший способ сделать это?
Что я пробовал до сих пор: мой класс для добавления образцов данных
public class DBSampleAdditor {
@PersistenceContext
private EntityManager em;
@Transactional
public void addSampleData() {
// creating POJO instances and persist them with em.perists()
}
}
Я попытался вызвать эти функции в основном из моего ApplicationClass
@SpringBootApplication()
public class ApiApplication {
public static void main(String[] args) {
SpringApplication.run(ApiApplication.class, args);
DBSampleAdditor dbsa = new DBSampleAdditor();
dbsa.addSampleData();
}
}
Это вообще не сработало, поскольку EntityManager так и не получил экземпляр из модуля сохранения.
Я также пытался создать CommandLineRunner:
@Component
public class PTCommandLineRunner implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
System.out.println("Adding sample data...");
DBSampleAdditor dbsa = new DBSampleAdditor();
dbsa.addSampleData();
}
}
Но, похоже, это никогда не вызывалось в процессе запуска.
Ответ №1:
Вы можете использовать метод с @PostConstruct с @Component для вставки данных при запуске.
@PostConstruct будет вызван после создания компонента, внедрения зависимостей, установки всех управляемых свойств и до того, как компонент будет фактически установлен в область видимости.
Просто введите свой репозиторий базы данных в класс, помеченный @Component, и вызовите введенный репозиторий базы данных внутри метода, помеченного @PostConstruct
Пример:
@Component
public class DbInit {
@Autowired
private UserRepository userRepository;
@PostConstruct
private void postConstruct() {
User admin = new User("admin", "admin password");
User normalUser = new User("user", "user password");
userRepository.save(admin, normalUser);
}
}
Комментарии:
1. Я пробовал это, но метод, который аннотируется с помощью @PostConstruct, никогда не вызывается.
2. Хорошо — я исправил это, забыл включить обработку аннотаций внутри IntelliJ. Для меня это работает просто отлично.
Ответ №2:
Для использования управляемых компонентов Spring, таких как EntityManager
объекты, необходимо использовать spring Beans
, что в основном означает, что они создаются внутри контекста Spring и могут использовать контейнер IoC.
В приведенном выше примере запуск DbSampleAdditor
класса из метода main находится вне контекста Spring, поэтому такие компоненты, как PersistenceContext
, не будут введены.
Один довольно простой способ сделать это внутри контекста spring — добавить ApplicationListener
для ApplicationReadyEvent
@Component
class Initialise implements ApplicationListener<ApplicationReadyEvent> {
@Autowired
private final DbSampleAdditor db;
@Override
public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) {
db.addSampleData();
}
}
Когда срабатывает событие готовности приложения, настраивается вся необходимая проводка spring bean, поэтому, когда он запускает addSampleData
метод, такие вещи, как EM, можно использовать.
Другие подходы к настройке базы данных для весенней загрузки задокументированы здесь
Комментарии:
1. Нужно ли мне в какой-то момент сообщать моему приложению, что этот класс существует, или я должен поместить его в пакет, который находится в определенном отношении к моему классу приложения? Инициализатор никогда не вызывается.
Ответ №3:
Вместо создания объекта DBSampleAdditor попробуйте автоматически подключить его, чтобы он был доступен при запуске приложения. @Autowired DBSampleAdditor DBSampleAdditor Затем вы пытаетесь добавить образцы данных в метод run