【问题标题】:How to retrieve last created record based on creation date in hibernate如何根据休眠中的创建日期检索最后创建的记录
【发布时间】:2021-01-23 06:15:22
【问题描述】:

我有以下与projectId 关联的波的数据库表,每个波也可能不同。

现在我想根据 created_atprojectId 字段获取上次创建的 wave。

我只尝试了created_at 有效的字段。现在我想尝试使用 projectId 以及 created_at 字段。我用下面的代码 w.r.t EntityManager.

List<Wave> waves = em.createNamedQuery("select p " + "from Wave p " + "order by p.createdAt desc")
                .setFirstResult(0)
                .setMaxResults(1)
                .getResultList();
        
        System.out.println(waves.get(0).getCreatedAt() + " " + waves.get(0).getName());
// I am getting last record

有人可以帮我获取基于projectId alongwith createdAt 的记录吗?其次,使用实体管理器编写查询而不是在WaveService 类中编写查询的最佳实践是什么?查询应该写在哪里以及如何写?我是实体经理的新手。

这是我的完整代码:

WaveRepository:

import java.util.List;
import java.util.Optional;

import javax.transaction.Transactional;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

import com.nokia.rmt.model.Wave;

@Repository
public interface WaveRepository extends JpaRepository<Wave, Long> {

    Optional<Wave> findById(Long waveID);

    Optional<Wave> findByName(String waveName);

    List<Wave> findByProjectId(Long projectId);
    
    @Transactional
    @Modifying
    @Query("DELETE FROM WaveRecord r where r.wave.id = :waveId")
    void deleteRecordByWave(@Param("waveId") Long waveId);
}

WaveController:

import java.net.URI;
import java.util.List;
import java.util.Optional;

import javax.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;

import com.nokia.rmt.model.Wave;
import com.nokia.rmt.payloads.ApiResponse;
import com.nokia.rmt.payloads.WaveRequest;
import com.nokia.rmt.payloads.WaveResponse;
import com.nokia.rmt.repository.WaveRepository;
import com.nokia.rmt.security.CurrentUser;
import com.nokia.rmt.security.UserPrincipal;
import com.nokia.rmt.service.WaveService;

@RestController
@RequestMapping("/api/baseline/wave")
public class WaveController {

    @Autowired
    WaveRepository waveRepository;
    
    @Autowired
    WaveService waveService;
    
    @PostMapping
    @PreAuthorize("hasRole('USER')")
    public ResponseEntity<?> createWave(@Valid @RequestBody WaveRequest waveRequest, @CurrentUser UserPrincipal currentUser) {
        
        try {
            
            final String waveName = waveRequest.getWaveName();
            Optional<Wave> currentWave = waveRepository.findByName(waveName);
            
            if(currentWave.isPresent()) {
                Wave wave = waveService.updateWave(waveRequest, currentUser, currentWave.get());
                
                URI location = ServletUriComponentsBuilder
                        .fromCurrentRequest().path("/{waveId}")
                        .buildAndExpand(wave.getId()).toUri();

                return ResponseEntity.created(location)
                        .body(new ApiResponse(true, "Wave Updated Successfully"));
            }
            
            Wave wave = waveService.createWave(waveRequest, currentUser);

            URI location = ServletUriComponentsBuilder
                    .fromCurrentRequest().path("/{waveId}")
                    .buildAndExpand(wave.getId()).toUri();

            return ResponseEntity.created(location)
                    .body(new ApiResponse(true, "Wave Created Successfully"));
            
        } catch(IllegalArgumentException e) {
            return new ResponseEntity<Object>(new ApiResponse(false, "Unable to create wave!"),
                    HttpStatus.BAD_REQUEST);
        }
    }
    
    @GetMapping("/id/{waveId}")
    public WaveResponse getWaveById(@CurrentUser UserPrincipal currentUser, @PathVariable Long waveId) {
        return waveService.getWaveById(waveId, currentUser);
    }
    
    @GetMapping("/{waveName}")
    public WaveResponse getWaveByName(@CurrentUser UserPrincipal currentUser, @PathVariable String waveName) {
        return waveService.getWaveByName(waveName, currentUser);
    }
    
    @GetMapping("/project/{projectName}")
    public ResponseEntity<?> getAllWavesByProjectName(@CurrentUser UserPrincipal currentUser, @PathVariable String projectName) {
        
        try {
            List<WaveResponse> response = waveService.getAllWavesByProjectName(currentUser, projectName);
            return new ResponseEntity<List<WaveResponse>>(response, HttpStatus.OK);
            
        } catch(IllegalArgumentException e) {
            return new ResponseEntity<Object>(new ApiResponse(false, e.getMessage()),
                    HttpStatus.NOT_FOUND);
        }
    }
}

WaveService:

import java.util.ArrayList;
import java.util.List;

import javax.persistence.EntityManager;
import javax.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.nokia.rmt.exception.AppException;
import com.nokia.rmt.exception.ResourceNotFoundException;
import com.nokia.rmt.model.Project;
import com.nokia.rmt.model.ProjectName;
import com.nokia.rmt.model.User;
import com.nokia.rmt.model.Wave;
import com.nokia.rmt.model.WaveRecord;
import com.nokia.rmt.payloads.WaveRecordRequest;
import com.nokia.rmt.payloads.WaveRequest;
import com.nokia.rmt.payloads.WaveResponse;
import com.nokia.rmt.repository.ProjectRepository;
import com.nokia.rmt.repository.UserRepository;
import com.nokia.rmt.repository.WaveRepository;
import com.nokia.rmt.security.UserPrincipal;
import com.nokia.rmt.util.ModelClassMapper;

@Service
public class WaveService {

    @Autowired
    WaveRepository waveRepository;

    @Autowired
    UserRepository userRepository;

    @Autowired
    ProjectRepository projectRepository;
    
    @Autowired
    EntityManager em;
    
    public Wave createWave(WaveRequest waveRequest, UserPrincipal currentUser) throws IllegalArgumentException {

        ProjectName name = ProjectName.stringToEnum(currentUser.getProject().getName().name());
        Project project = projectRepository.findByName(name)
                .orElseThrow(() -> new AppException("Project Name does not exist!."));

        Wave wave = Wave.builder()
                .name(waveRequest.getWaveName())
                .project(project).build();

        waveRequest.getWaveRecords().forEach(waveRecordRequest -> {
            WaveRecord waveRecord = WaveRecord.builder()
                    .productName(waveRecordRequest.getProductName())
                    .releaseName(waveRecordRequest.getReleaseName())
                    .typeName(waveRecordRequest.getTypeName())
                    .streamName(waveRecordRequest.getStreamName())
                    .dateOfTransition(waveRecordRequest.getDateOfTransition())
                    .compatabilityStatus(waveRecordRequest.getCompatabilityStatus())
                    .comment(waveRecordRequest.getComment())
                    .isReleaseUpdated(0)
                    .build();
            wave.addWaveRecord(waveRecord);
        });
        
        List<Wave> waves = em.createNamedQuery("select p " + "from Wave p " + "order by p.createdAt desc")
                .setFirstResult(0)
                .setMaxResults(1)
                .getResultList();
        
        System.out.println(waves.get(0).getCreatedAt() + " " + waves.get(0).getName());
                
        return waveRepository.save(wave);
    }
    
    public Wave updateWave(@Valid WaveRequest waveRequest, UserPrincipal currentUser, Wave wave) {
        
        List<WaveRecord> waveRecords = wave.getWaveRecords();
        
        waveRequest.getWaveRecords().forEach(waveRecordRequest -> {
            WaveRecord record = isRecordAvailable(waveRecords, waveRecordRequest);
            
            if(record != null) {
                record.setProductName(waveRecordRequest.getProductName());
                record.setReleaseName(waveRecordRequest.getReleaseName());
                record.setDateOfTransition(waveRecordRequest.getDateOfTransition());
                record.setCompatabilityStatus(waveRecordRequest.getCompatabilityStatus());
                record.setComment(waveRecordRequest.getComment());
            }
            else {
                WaveRecord waveRecord = WaveRecord.builder()
                        .productName(waveRecordRequest.getProductName())
                        .releaseName(waveRecordRequest.getReleaseName())
                        .typeName(waveRecordRequest.getTypeName())
                        .streamName(waveRecordRequest.getStreamName())
                        .compatabilityStatus(waveRecordRequest.getCompatabilityStatus())
                        .dateOfTransition(waveRecordRequest.getDateOfTransition())
                        .comment(waveRecordRequest.getComment())
                        .build();
                wave.addWaveRecord(waveRecord);
            }
        });
        return waveRepository.save(wave);
    }

    private WaveRecord isRecordAvailable(List<WaveRecord> waveRecords, WaveRecordRequest waveRecordRequest) {
        final String type = waveRecordRequest.getTypeName();
        final String stream = waveRecordRequest.getStreamName();
        return waveRecords.stream().filter(record -> record.getTypeName().equalsIgnoreCase(type) && record.getStreamName().equalsIgnoreCase(stream)).findFirst().orElse(null);
    }

    public WaveResponse getWaveById(Long waveId, UserPrincipal currentUser) {

        Wave wave = waveRepository.findById(waveId).orElseThrow(() -> new ResourceNotFoundException("Wave", "id", waveId));

        User creator = userRepository.findById(wave.getCreatedBy())
                .orElseThrow(() -> new ResourceNotFoundException("User", "id", wave.getCreatedBy()));

        return ModelClassMapper.mapWaveResponse(wave, creator);
    }

    public WaveResponse getWaveByName(String waveName, UserPrincipal currentUser) {

        Wave wave = waveRepository.findByName(waveName).orElseThrow(
                () -> new ResourceNotFoundException("Wave", "name", waveName));

        User creator = userRepository.findById(wave.getCreatedBy())
                .orElseThrow(() -> new ResourceNotFoundException("Wave", "id", wave.getCreatedBy()));

        return ModelClassMapper.mapWaveResponse(wave, creator);
    }

    public List<WaveResponse> getAllWavesByProjectName(UserPrincipal currentUser, String projectName) throws IllegalArgumentException {

        ProjectName name = ProjectName.stringToEnum(projectName);
        Project project = projectRepository.findByName(name)
                .orElseThrow(() -> new AppException("Project Name does not exist!."));

        List<Wave> waves = waveRepository.findByProjectId(project.getId());

        List<WaveResponse> waveResponses = new ArrayList<>();

        waves.forEach(wave -> {
            User creator = userRepository.findById(wave.getCreatedBy())
                    .orElseThrow(() -> new ResourceNotFoundException("Wave", "id", wave.getCreatedBy()));

            WaveResponse response = ModelClassMapper.mapWaveResponse(wave, creator);
            waveResponses.add(response);
        });

        return waveResponses;
    }


}

【问题讨论】:

    标签: java spring spring-boot hibernate spring-mvc


    【解决方案1】:

    您需要在查询中使用 GROUP By

     List<Wave> waves = entityManager.createQuery("select w from Wave w group by w.projectId order by w.createdAt",Wave.class).list();
    
    

    你不应该在服务组件中使用 EntityManger,你必须定义一个 CustomWaveRepository 接口

    public interface CustomWaveRepository{
    List<Wave> getWavesGroupByProjectIdAndOrderByCreateAt();
    }
    

    然后实现这个接口

    @Repository
    @Transactional
    public class CustomWaveRepositoryImpl impelemnets CustomWaveRepository{
    
    EntityManager entityManger;
    
    public CustomWaveRepositoryImpl(EntityManager entityManger){
    this.entityManger = entityManger;
    }
    
    List<Wave> getWavesGroupByProjectIdAndOrderByCreateAt(){
       
    return entityManager.createQuery("select w from Wave w group by w.projectId order by w.createdAt",Wave.class).list();
    }
    }
    

    现在更改您的 WaveRepository

    public interface WaveRepository extends JpaRepository<Wave, Long>, CustomWaveRepository{
    }
    

    希望这个回答对你有帮助

    【讨论】:

    • 我认为查询需要更改,因为正如我所提到的,它们可以是不同的 projectID 并且基于 createdAt 我需要提取最新的 wave。例如,我也有项目 id = 2 的 wave。但是我需要提取 projectid = 1 和创建的最新波的波
    • 我不明白你的问题!我的查询检索最后创建的基于 wave 的 projectId,projectId=1 和 projectId=2 的最新记录。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-02-03
    • 2014-05-14
    • 1970-01-01
    • 2011-03-20
    • 2021-05-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多