微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

将验证移至 JPQL 查询级别

如何解决将验证移至 JPQL 查询级别

我正在寻找一种将验证方法从服务转移到存储库的方法

一张图片一个图片数据。

这是方法

// Todo 将验证移至 JPQL 查询级别 .filter(pic -> pic.getPictureData().getFileName() != null)

这是我的服务

@Service
@ConditionalOnProperty(name = "picture.storage.type",havingValue = "file")
public class PictureServiceFileImpl implements PictureService {

    private static final Logger logger = LoggerFactory.getLogger(PictureServiceFileImpl.class);

    @Value("${picture.storage.path}")
    private String storagePath;

    private final PictureRepository repository;

    @Autowired
    public PictureServiceFileImpl(PictureRepository repository) {
        this.repository = repository;
    }

    @Override
    public Optional<String> getPictureContentTypeById(long id) {
        return repository.findById(id)
                // Todo move validation to the JPQL query level
                .filter(pic -> pic.getPictureData().getFileName() != null)
                .map(Picture::getContentType);
    }

    @Override
    public Optional<byte[]> getPictureDataById(long id) {
        return repository.findById(id)
                // Todo move validation to the JPQL query level
                .filter(pic -> pic.getPictureData().getFileName() != null)
                .map(pic -> Path.of(storagePath,pic.getPictureData().getFileName()))
                .filter(Files::exists)
                .map(path -> {
                    try {
                        return Files.readAllBytes(path);
                    } catch (IOException ex) {
                        logger.error("Can't open picture file",ex);
                        throw new RuntimeException(ex);
                    }
                });
    }

    @Override
    public PictureData createPictureData(byte[] picture) {
        String fileName = UUID.randomUUID().toString();
        try (OutputStream os = Files.newOutputStream(Path.of(storagePath,fileName))) {
            os.write(picture);
        } catch (IOException ex) {
            logger.error("Can't create picture file",ex);
            throw new RuntimeException(ex);
        }
        return new PictureData(fileName);
    }
}

实体

@Entity
@Table(name = "pictures")
public class Picture {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;

    @Column(name = "name",nullable = false)
    private String name;

    @Column(name = "content_type",nullable = false)
    private String contentType;

    @OnetoOne(fetch = FetchType.LAZY,cascade= CascadeType.ALL,optional = false,orphanRemoval = true)
    @JoinColumn(name="picture_data_id")
    private PictureData pictureData;

    @ManyToOne
    private Product product;

    public Picture() {
    }

    public Picture(String name,String contentType,PictureData pictureData,Product product) {
        this.name = name;
        this.contentType = contentType;
        this.pictureData = pictureData;
        this.product = product;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getContentType() {
        return contentType;
    }

    public void setContentType(String contentType) {
        this.contentType = contentType;
    }

    public PictureData getPictureData() {
        return pictureData;
    }

    public void setPictureData(PictureData pictureData) {
        this.pictureData = pictureData;
    }

    public Product getProduct() {
        return product;
    }

    public void setProduct(Product product) {
        this.product = product;
    }
}

@Entity
@Table(name = "pictures_data")
public class PictureData {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;

    @Lob
    @Type(type="org.hibernate.type.BinaryType") // для правильной работы Postgresql
    @Column(name = "data",length = 33554430) // для правильной hibernate-валидации в MysqL
    private byte[] data;

    @Column(name = "file_name")
    private String fileName;

    public PictureData() {
    }

    public PictureData(byte[] data) {
        this.data = data;
    }

    public PictureData(String fileName) {
        this.fileName = fileName;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public byte[] getData() {
        return data;
    }

    public void setData(byte[] data) {
        this.data = data;
    }

    public String getFileName() {
        return fileName;
    }

    public void setFileName(String fileName) {
        this.fileName = fileName;
    }
}

我正在努力让查询在 JPQL 中工作。

public interface PictureRepository extends JpaRepository<Picture,Long> {

    @Query ("SELECT p FROM Picture p JOIN p.pictureData d WHERE d.data  IS NOT NULL ")
    Picture filterPictureWherePictureDataIsNotNull ();
}

解决方法

既然你已经有了实体级别的join,可以直接使用下面的方法

public interface PictureRepository extends JpaRepository<Picture,Long> 
{

    @Query ("SELECT p FROM Picture p WHERE p.pictureData.data  IS NOT NULL ")
    Picture filterPictureWherePictureDataIsNotNull ();
}

另一个观察,

您的 repo 方法可能返回图片列表而不是一张图片。因此,理想情况下返回类型应该是

@Query ("SELECT p FROM Picture p WHERE p.pictureData.data  IS NOT NULL ")
    List<Picture> filterPictureWherePictureDataIsNotNull ();

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。