spring - 检测表中插入数据并调用方法
问题描述
我在检测向表中添加新行时遇到问题。当有人在数据库(Postgres)上执行插入查询时,我想从某个服务(Spring boot)触发一个方法
有人告诉我,我可以使用 @Scheduled 注释并检查是否使用存储库添加了某些内容。我必须立即进行一些更改(通过使用另一种方法)。计划的方法应每 5 秒运行一次以立即执行此操作。当然,这是一个非常糟糕的主意,因为它有一天会杀死数据库并且效率不高。我怎样才能做得更好?
解决方案
您可以编写org.hibernate.integrator.spi.Integrator
. 并将其提供给hibernate.integrator_provider
FromServiceRegistry
我们可以获取EventListenerRegistry
然后附加类型的侦听器EventType.POST_INSERT
。更多活动在这里。
根据查询,我还添加了如何从侦听器类调用服务方法。
以下是我的做法:
package com.example.samplejdbctemplatecall;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.hibernate.boot.Metadata;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.event.service.spi.EventListenerGroup;
import org.hibernate.event.service.spi.EventListenerRegistry;
import org.hibernate.event.spi.EventType;
import org.hibernate.event.spi.PostInsertEvent;
import org.hibernate.event.spi.PostInsertEventListener;
import org.hibernate.integrator.spi.Integrator;
import org.hibernate.jpa.boot.spi.IntegratorProvider;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.service.spi.SessionFactoryServiceRegistry;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.orm.jpa.HibernatePropertiesCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import java.util.Collections;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
@RequestMapping(path = "/entity-listener")
@RestController
public class SampleLogController {
private final SampleLogRepository sampleLogRepository;
private final SampleLogEntries sampleLogEntiries;
@Autowired
public SampleLogController(SampleLogRepository sampleLogRepository, SampleLogEntries sampleLogEntiries) {
this.sampleLogRepository = sampleLogRepository;
this.sampleLogEntiries = sampleLogEntiries;
}
// This is usually post method but for test purpose creating new log with uuid random and inserting
@GetMapping(path = "insert")
public SampleLog insertNewEntry() {
final String uuid = UUID.randomUUID().toString();
final SampleLog sampleLog = new SampleLog();
sampleLog.setMessage(uuid);
return sampleLogRepository.save(sampleLog);
}
@GetMapping(path = "list-recent-inserts")
public Map<Long, String> entries() {
return sampleLogEntiries.data();
}
}
@Slf4j
@Component
class HibernateConfig implements HibernatePropertiesCustomizer {
private final JpaEventListenerIntegrator jpaEventListenerIntegrator;
@Autowired
HibernateConfig(JpaEventListenerIntegrator jpaEventListenerIntegrator) {
this.jpaEventListenerIntegrator = jpaEventListenerIntegrator;
}
@Override
public void customize(Map<String, Object> hibernateProperties) {
log.warn("Called hibernate configuration");
hibernateProperties.put("hibernate.integrator_provider",
(IntegratorProvider) () -> Collections.singletonList(jpaEventListenerIntegrator));
}
}
@Configuration
class SampleConfiguration {
@Bean
SampleLogEntries sampleEntries() {
return new SampleLogEntries();
}
}
class SampleLogEntries {
private final ConcurrentMap<Long, String> map = new ConcurrentHashMap<>();
public void add(SampleLog sampleLog) {
this.map.put(sampleLog.getId(), sampleLog.getMessage());
}
public Map<Long, String> data() {
return Collections.unmodifiableMap(this.map);
}
}
@Repository
interface SampleLogRepository extends CrudRepository<SampleLog, Long> {
}
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Entity
class SampleLog {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String message;
}
@Service
@Slf4j
class JpaEventListenerIntegrator implements Integrator, PostInsertEventListener {
private final SampleLogEntries sampleLogEntiries;
@Autowired
JpaEventListenerIntegrator(SampleLogEntries sampleLogEntiries) {
this.sampleLogEntiries = sampleLogEntiries;
}
@Override
public void integrate(Metadata metadata, SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry) {
final EventListenerRegistry eventListenerRegistry = serviceRegistry.getService(EventListenerRegistry.class);
eventListenerRegistry
.appendListeners(EventType.POST_INSERT, this);
}
@Override
public void disintegrate(SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry) {
final EventListenerRegistry eventListenerRegistry = serviceRegistry.getService(EventListenerRegistry.class);
EventListenerGroup<PostInsertEventListener> eventListenerGroup = eventListenerRegistry
.getEventListenerGroup(EventType.POST_INSERT);
log.info("listener attached were: " + eventListenerGroup.getClass().getSimpleName());
log.error("disintegrate : " + getClass().getCanonicalName());
eventListenerGroup.clearListeners();
}
@Override
public void onPostInsert(PostInsertEvent event) {
log.info("Inserted : " + event.getEntity());
final Object entity = event.getEntity();
if (entity instanceof SampleLog) {
sampleLogEntiries.add((SampleLog) entity);
}
}
@Override
public boolean requiresPostCommitHanding(EntityPersister persister) {
return false;
}
}
推荐阅读
- java - 如何在其他实体中两次映射同一列
- ruby - 尝试设置一个 Ruby 邮件程序,我收到:ActionView::MissingTemplate
- java - Java spring 排序和过滤
- python - 有没有办法重命名重复标题并选择正确的python列?
- ios - 如何将 CGRect 转换为 CGPoint iOS Swift
- java - 如何修复“变量可能尚未初始化”
- sql-server-2012 - Sql server 2012 连接查询问题。我想加入两个表,我想得到第一个表的完整数据和第二个表的完整数据
- python-3.x - 如何使用python从sharepoint文件夹/链接中获取文件?
- php - UNION ALL 影响从数据库回显的日期时间变量
- c# - 如何在 Web 服务中验证 Azure AD Web 表单令牌