如何解决将验证移至 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 举报,一经查实,本站将立刻删除。