Bom Dia.
Estou fazendo uma API rest para um app, e preciso que sempre a partir de 00h os dados do usuário armazenados em uma List<> sejam deletados.
Esta lista ira listar os dados do relacionamento OneToMany.
Eu tenho 2 entidades, a entidade pai (DayUser) e a entidade filho (FoodConsumed).
@Entity
@Table(name="day_user")
public class DayUser {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Integer id;
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "id_client")
private ClientModel clientModel;
@Basic
@Temporal(TemporalType.DATE)
@Column(name = "created_at")
private java.util.Date date;
@Column(name = "day_index")
private int dayIndex;
@OneToMany(targetEntity=FoodConsumed.class, mappedBy="dayUser", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER)
@JsonIgnore
private List<FoodConsumed> foodConsumeds = new ArrayList<>();
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public ClientModel getClientModel() {
return clientModel;
}
public void setClientModel(ClientModel clientModel) {
this.clientModel = clientModel;
}
public int getDayIndex() {
return dayIndex;
}
public void setDayIndex(int dayIndex) {
this.dayIndex = dayIndex;
}
public List<FoodConsumed> getFoodConsumeds() {
return foodConsumeds;
}
public void setFoodConsumeds(List<FoodConsumed> foodConsumeds) {
this.foodConsumeds = foodConsumeds;
}
public java.util.Date getDate() {
return date;
}
public void setDate(java.util.Date date) {
this.date = date;
}
@Override
public int hashCode() {
return Objects.hash(clientModel, dayIndex, id);
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
DayUser other = (DayUser) obj;
return Objects.equals(clientModel, other.clientModel) && dayIndex == other.dayIndex
&& Objects.equals(id, other.id);
}
public DayUser(Integer id, ClientModel clientModel, int dayIndex) {
super();
this.id = id;
this.clientModel = clientModel;
this.dayIndex = dayIndex;
}
public DayUser(Integer id, ClientModel clientModel, Date date, int dayIndex, List<FoodConsumed> foodConsumeds) {
super();
this.id = id;
this.clientModel = clientModel;
this.date = date;
this.dayIndex = dayIndex;
this.foodConsumeds = foodConsumeds;
}
public DayUser(int dayIndex) {
super();
this.dayIndex = dayIndex;
}
public DayUser() {
super();
// TODO Auto-generated constructor stub
}
}
Child Entity:
@Entity
@TypeDef(
name = "ConsumptionPeriod",
typeClass = PostgreSQLEnumType.class
)
@Table(name="food_consumed")
public class FoodConsumed {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Integer id;
@Column(name = "consumption_id")
private Integer consumptionID;
@Column(name = "consumption_name")
private String name;
@Column(name = "consumption_amount")
private double amount;
@Column(name = "consumption_amountkcal")
private double amountKcal;
@Basic
@Temporal(TemporalType.DATE)
@Column(name = "consumption_date")
private java.util.Date date;
@Enumerated(EnumType.STRING)
@Column(name = "consumption_period")
@Type(type = "ConsumptionPeriod")
private ConsumptionPeriod period;
@ManyToOne(fetch = FetchType.LAZY, optional = false)
@OnDelete(action = OnDeleteAction.CASCADE)
@JoinColumn(name = "id_day", nullable = false)
@JsonIgnore
private DayUser dayUser;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getConsumptionID() {
return consumptionID;
}
public void setConsumptionID(Integer consumptionID) {
this.consumptionID = consumptionID;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getAmount() {
return amount;
}
public void setAmount(double amount) {
this.amount = amount;
}
public java.util.Date getDate() {
return date;
}
public void setDate(java.util.Date date) {
this.date = date;
}
public ConsumptionPeriod getPeriod() {
return period;
}
public void setPeriod(ConsumptionPeriod period) {
this.period = period;
}
public DayUser getDayUser() {
return dayUser;
}
public void setDayUser(DayUser dayUser) {
this.dayUser = dayUser;
}
public double getAmountKcal() {
return amountKcal;
}
public void setAmountKcal(double amountKcal) {
this.amountKcal = amountKcal;
}
@Override
public int hashCode() {
return Objects.hash(amount, consumptionID, date, dayUser, id, name, period);
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
FoodConsumed other = (FoodConsumed) obj;
return Double.doubleToLongBits(amount) == Double.doubleToLongBits(other.amount)
&& Objects.equals(consumptionID, other.consumptionID) && Objects.equals(date, other.date)
&& Objects.equals(dayUser, other.dayUser) && Objects.equals(id, other.id)
&& Objects.equals(name, other.name) && period == other.period;
}
public FoodConsumed(Integer id, Integer consumptionID, String name, double amount, double amountKcal, Date date,
ConsumptionPeriod period, DayUser dayUser) {
super();
this.id = id;
this.consumptionID = consumptionID;
this.name = name;
this.amount = amount;
this.amountKcal = amountKcal;
this.date = date;
this.period = period;
this.dayUser = dayUser;
}
public FoodConsumed(Integer consumptionID, String name, double amount, double amountKcal, Date date,
ConsumptionPeriod period) {
super();
this.consumptionID = consumptionID;
this.name = name;
this.amount = amount;
this.amountKcal = amountKcal;
this.date = date;
this.period = period;
}
public FoodConsumed() {
super();
// TODO Auto-generated constructor stub
}
}
Este e o repositorio da child entity:
public interface ConsumedRepository extends JpaRepository<FoodConsumed, Integer> {
//public Optional<FoodConsumed> findByName(String name);
//public Optional<FoodConsumed> findById(int id);
@Transactional
void deleteById(Integer id);
//public Optional<FoodConsumed> findByPeriod(ConsumptionPeriod period);
}
Postgresql Querys:
CREATE TABLE day_user(
id SERIAL PRIMARY KEY,
day_index integer,
created_at DATE NULL
);
CREATE TABLE food_consumed(
id SERIAL PRIMARY KEY,
consumption_id integer,
consumption_name VARCHAR(50),
consumption_amount double precision NULL,
consumption_amountKcal double precision NULL,
consumption_date DATE NULL,
consumption_period ConsumptionPeriod NULL
);
ALTER TABLE food_consumed ADD COLUMN id_day SERIAL NULL;
ALTER TABLE food_consumed ADD CONSTRAINT fk_consumed FOREIGN KEY (id_day)
REFERENCES day_user (id);
ALTER TABLE day_user ADD COLUMN id_client UUID;
ALTER TABLE day_user ADD CONSTRAINT fk_consumed FOREIGN KEY (id_client)
REFERENCES client (id);
O problema é o seguinte, quando tento deletaras entidades pelo id em uma tarefa, eles apenas alteram o id e continuam no banco de dados.
Mas quando tento DELETE uma requisicao de API funciona normalmente.
Rest Request (Funciona):
@DeleteMapping("/{id}")
public ResponseEntity<HttpStatus> deleteConsumed(@PathVariable("id") Integer id) {
try {
consumedRepository.deleteById(id);
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
} catch (Exception e) {
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
Scheduled Task (Nao Funciona):
@Component
public class JourneyScheduler {
Pusher pusher = new Pusher(PusherCredentials.AppId, PusherCredentials.Key, PusherCredentials.Secret);
@Autowired
private ClientRepository repository;
@Autowired
private DayUserRepository dayUserRepository;
@Autowired
private ConsumedRepository consumedRepository;
@Scheduled(fixedRate = 6000)//(cron = "0 35 21 * * ?")
public void checkUserJourney() {
List<ClientModel> allClients = repository.findAll();
pusher.setCluster(PusherCredentials.Cluster);
pusher.setEncrypted(true);
for (ClientModel client : allClients) {
ClientProfile clientProfile = client.getClientProfile();
Optional<DayUser> dayUser = dayUserRepository.findById(clientProfile.getCurrentDay());
if(dayUser.isPresent()) {
int currentDayIndex = dayUser.get().getDayIndex();
double allKcalConsumed = 0;
for (FoodConsumed consumed : dayUser.get().getFoodConsumeds())
allKcalConsumed += consumed.getAmountKcal();
String message = "Meta nao atingida";
if(isEligible(client,allKcalConsumed)) {
currentDayIndex ++;
message = "Meta atingida";
}else {
System.out.println("Usuario Reprovado");
for (FoodConsumed consumed : dayUser.get().getFoodConsumeds())
consumedRepository.deleteById(consumed.getId());
}
pusher.trigger(client.getId()+"", "day_update", Collections.singletonMap("message", message));
clientProfile.setCurrentDay(client.getDayUsers().get(currentDayIndex).getId());
repository.save(client);
}
}
}
public boolean isEligible(ClientModel client, double allKcalConsumed) {
ClientProfile clientProfile = client.getClientProfile();
//if(allKcalConsumed > 0)
//if(allKcalConsumed * 0.8 <= clientProfile.getDailyKcal() && clientProfile.getDailyKcal() <= allKcalConsumed)
//return true;
return false;
}
}
Quando esta tarefa é executada, os itens vão para um novo id e permanecem relacionados ao DayUser mesmo que eu chame o repositório.deleteByID