juuubbb
juuubbb

Reputation: 179

How to use @Autowired in EntityListener class?

I have a class DatabaseInitializer which inserts some data via crudrepositories into my database. Now I added an EntityListener which should update a number in another table (table 2), if the date of the entity is not present in table 2. For this I try @Autowired with the crudrepository for this entity. But the repository isn't autowired correctly, it's always null.

The EntityListener:

@Component
public class OrderDayIdListener {

    @Autowired
    private static OrderRepository orderRepository;

    @Autowired
    private  OrderDayIdRepository orderDayIdRepository;

    @PrePersist
    private void incrementOrderIdInTable(Order order) {
        LocalDate date = order.getDate();

        OrderDayId orderDayIdObject =         orderDayIdRepository.findByDate(date);

        if(orderDayIdObject == null){
            orderDayIdObject = new OrderDayId(1L, date);
        } else {
            orderDayIdObject.incrementId();
        }

        Long orderDayId = orderDayIdObject.getId();
        order.setOrderDayId(orderDayId);

        orderDayIdRepository.save(orderDayIdObject);
        orderRepository.save(order);
    }
}

The Entity:

@EntityListeners(OrderDayIdListener.class)
@Data
@Entity
public class Order {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id", updatable = false, nullable = false)
    private Long id;

    @Column(name ="date")
    private LocalDate date;
}

Upvotes: 1

Views: 3128

Answers (1)

Milenko Jevremovic
Milenko Jevremovic

Reputation: 1056

As I know you cannot inject spring managed beans into a JPA EntityListener. What I have found is to create helper class for do the job:

public final class AutowireHelper implements ApplicationContextAware {

private static final AutowireHelper INSTANCE = new AutowireHelper();
private static ApplicationContext applicationContext;

private AutowireHelper() {
}

/**
 * Tries to autowire the specified instance of the class if one of the specified beans which need to be autowired
 * are null.
 *
 * @param classToAutowire the instance of the class which holds @Autowire annotations
 * @param beansToAutowireInClass the beans which have the @Autowire annotation in the specified {#classToAutowire}
 */
public static void autowire(Object classToAutowire, Object... beansToAutowireInClass) {
    for (Object bean : beansToAutowireInClass) {
        if (bean == null) {
            applicationContext.getAutowireCapableBeanFactory().autowireBean(classToAutowire);
            return;
        }
    }
}

@Override
public void setApplicationContext(final ApplicationContext applicationContext) {
    AutowireHelper.applicationContext = applicationContext;
}

/**
 * @return the singleton instance.
 */
public static AutowireHelper getInstance() {
    return INSTANCE;
}}

than just do:

public class OrderDayIdListener {

@Autowired
private OrderRepository orderRepository;

@Autowired
private  OrderDayIdRepository orderDayIdRepository;

@PrePersist
public void incrementOrderIdInTable(Order order) {
    AutowireHelper.autowire(this, this.orderRepository);
    AutowireHelper.autowire(this, this.orderDayIdRepository);

    LocalDate date = order.getDate();

    OrderDayId orderDayIdObject = orderDayIdRepository.findByDate(date);

    if(orderDayIdObject == null){
        orderDayIdObject = new OrderDayId(1L, date);
    } else {
        orderDayIdObject.incrementId();
    }

    Long orderDayId = orderDayIdObject.getId();
    order.setOrderDayId(orderDayId);

    orderDayIdRepository.save(orderDayIdObject);
    orderRepository.save(order);
}}

full explanation here

Upvotes: 1

Related Questions