知乎专栏 |
{"status":false,"code":"HttpMessageNotWritableException","data":null,"reason":"Could not write JSON: failed to lazily initialize a collection of role: cn.netkiller.domain.Lora.keyword: could not initialize proxy - no Session"}⏎
@ElementCollection(fetch = FetchType.EAGER) private Set<String> keyword = new HashSet<String>();
查询 version 表中的最有一条记录,提示 Query did not return a unique result: 2 results were returned
package cn.netkiller.domain; import jakarta.persistence.*; import lombok.Data; import org.hibernate.annotations.Comment; import org.hibernate.annotations.DynamicInsert; import org.hibernate.annotations.DynamicUpdate; import java.io.Serial; import java.io.Serializable; import java.util.Date; @Entity @Table @DynamicUpdate @DynamicInsert @Data @Comment("版本表") public class Version implements Serializable { @Serial public static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id", unique = true, nullable = false, insertable = false, updatable = false, columnDefinition = "int unsigned") @Comment("主键") private Integer id; @Comment("产品") @Column(columnDefinition = "enum('Phone','Tablet','Badges','Watch') DEFAULT 'Tablet'") private String product; @Comment("版本") @Column(length = 5) private String version; @Comment("下载地址") private String url; @Column(insertable = false, updatable = false, columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP") @Comment("创建时间") private Date ctime; @Column(nullable = true, insertable = false, updatable = false, columnDefinition = "TIMESTAMP NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP") @Comment("修改时间") private Date mtime; }
接口定义 findOneBy 查询 version 表中存在多条记录,我们只要最后一条,所以不能使用 findOneBy,需要使用 findFirstBy
package cn.netkiller.repository; import cn.netkiller.domain.Version; import org.springframework.data.repository.CrudRepository; import org.springframework.stereotype.Repository; import java.util.Optional; @Repository public interface VersionRepository extends CrudRepository<Version, Integer> { Iterable<Version> findByProduct(String tablet); Optional<Version> findOneByProductOrderByIdDesc(String tablet); }
package cn.netkiller.repository; import cn.netkiller.domain.Version; import org.springframework.data.repository.CrudRepository; import org.springframework.stereotype.Repository; import java.util.Optional; @Repository public interface VersionRepository extends CrudRepository<Version, Integer> { Iterable<Version> findByProduct(String tablet); Optional<Version> findFirstByProductOrderByIdDesc(String tablet); }
@GetMapping("/version/tablet/latest") public AigcResponse tabletLatest() { Optional<Version> optional = versionRepository.findFirstByProductOrderByIdDesc("Tablet"); if (optional.isPresent()) { Version version = optional.get(); log.debug(version.toString()); return new AigcResponse(version); } return new AigcResponse(null); }
org.springframework.dao.InvalidDataAccessApiUsageException: Executing an update/delete query
package cn.netkiller.repository; import cn.netkiller.domain.Picture; import io.lettuce.core.dynamic.annotation.Param; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Repository; import java.util.Optional; @Repository public interface PictureRepository extends JpaRepository<Picture, Long> { @Query("UPDATE Picture SET share = :status WHERE id=:id") @Modifying int updateShareStatus(@Param("id") Long id, @Param("status") boolean status); }
Service
public int share(Long id, boolean status) { return pictureRepository.updateShareStatus(id, status); }
解决方案,再 Server 方法增加事务注解
@Transactional(rollbackFor = Exception.class) public int share(Long id, boolean status) { return pictureRepository.updateShareStatus(id, status); }
第一种解决方法,捕捉 LazyInitializationException 异常
@Cacheable(value = "picture:click", key = "#deviceId+'-'+#pictureId", unless = "#result == null") public Optional<PictureClick> click(Integer deviceId, Integer pictureId) { Optional<PictureClick> optional = pictureClickRepository.findByDeviceIdAndPictureId(deviceId, pictureId); optional.ifPresent(pictureClick -> { try { log.debug(pictureClick.toString()); } catch (LazyInitializationException e) { log.error(e.getMessage()); } }); return optional; }
第二种解决方法 FetchType.EAGER
@ManyToOne(fetch = FetchType.EAGER, optional = false)
第三种解决方法 @Transactional(readOnly = true)
@Transactional(readOnly = true) public Optional<PictureClick> click(Integer deviceId, Integer pictureId) { Optional<PictureClick> optional = pictureClickRepository.queryByDeviceIdAndPictureId(deviceId, pictureId); optional.ifPresent(pictureClick -> { try { log.debug(pictureClick.toString()); } catch (LazyInitializationException e) { log.error(e.getMessage()); } }); return optional; }
第四种解决方法 @Proxy(lazy = false)
@Proxy(lazy = false) 的意思和FetchType.EAGER类似
JDBC exception executing SQL [select p1_0.id,p1_0.audio,p1_0.audit,p1_0.bmp,p1_0.ctime,p1_0.device,p1_0.english,p1_0.favorites,p1_0.forward,p1_0.group_id,p1_0.image,p1_0.likes,p1_0.mtime,p1_0.picture_group_id,p1_0.pinyin,p1_0.prompt,p1_0.session,p1_0.share,p1_0.story,p1_0.thumbnail,p1_0.translate from picture p1_0 where p1_0.audit=1 and p1_0.share=1 group by coalesce(p1_0.picture_group_id,p1_0.session) limit ?,?] [Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'watch.p1_0.id' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by] [n/a]; SQL [n/a]
解决方案一,使用 ANY_VALUE() 函数
@Query(" SELECT ANY_VALUE(p.id), ANY_VALUE(p.story), ANY_VALUE(p.image) FROM Picture p WHERE p.audit = true AND p.share = true GROUP BY IFNULL(p.pictureGroup.id,p.session)") Page<Picture> queryGroup(Pageable pageable);
解决方案二,修改数据库配置
SET sql_mode=''; SELECT id,name,group_id FROM test.photograph group by group_id; SET sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY','')); SET GLOBAL sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY',''));
@GetMapping("discovery/group") // @Deprecated(since = "v4.0.0", forRemoval = true) public AigcResponse group(Pageable pageable) { Page<Map<String, Object>> page = pictureGroupService.discoveryPictureGroup(pageable); List<Map<String, Object>> newList = new ArrayList<Map<String, Object>>(); List<Map<String, Object>> contents = page.getContent(); contents.forEach(content -> { Map<String, Object> map = new HashMap<String, Object>(content); map.put("thumbnail", url.concat((String) map.get("thumbnail"))); newList.add(map); }); Page<Map<String, Object>> newPage = new PageImpl<>(newList, pageable, page.getTotalElements()); return new AigcResponse(newPage); }