简体   繁体   中英

Select row with most recent date per user with 1 condition in JPA

I have this Entity and I want to list for each device the last event with the property message = 1

@Entity
@Table(name = "t_device_event")
@NamedQueries(value = { 
@NamedQuery(name = "DeviceEvent.findWithMessageActive",
            query = "from DeviceEvent as de1 where de1.message = 1 and de1.received = " 
                  + " ( select max(de2.received) from DeviceEvent de2 " 
                  + " where de2.device.id = de1.device.id )  "), )
public class DeviceEvent {
     ..
}

But I have an assertion problem in the last test , because it considers device3 as a last event and its not the case.

assertTrue ((numDevicesWithActiveMessage+1) == deviceEventService.findWithActiveMessage().size());

DeviceEvent deviceEvent3 = newDeviceEvent();
deviceEvent3.setMessage(1);
deviceEventService.save(deviceEvent3);

DeviceEvent deviceEvent4 = newDeviceEvent();
deviceEventService.save(deviceEvent4);

assertTrue ((numDevicesWithActiveMessage+1) == deviceEventService.findWithActiveMessage().size());

I assume DeviceEvent.received is set in newDeviceEvent() method and it's set to current time.

In such case as there is no delay between creating deviceEvent3 and deviceEvent4 , most probably they will have the same time in received field. The query will then choose the maximum of all received and according to outer condition it will select both deviceEvent3 and deviceEvent4 for which only deviceEvent3 will match as it has message equal to 1 .

So I believe that because the TEST consider device3 as a Last event is actually correct (most probably unless the clocks tick between creation of the two events).

Why not create an identity column for each record to be inserted. For an instance, an ID which automatically increment upon insertion (identity). From there, it should be able to return the latest value of that ID and we base our data from the ID being returned?

You have not set - deviceEvent4.setMessage(1) . Hence deviceEvent3 would be the latest device event and hence your test seems to be considering the correct device event (deviceEvent3) as the latest event

I think you should have added

deviceEvent4.setMessage(1);

since this code

assertTrue ((numDevicesWithActiveMessage+1) == deviceEventService.findWithActiveMessage().size());

is looking for an active message but device4 doesn't have any. Thus, the latest one is device3.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM