Home | 简体中文 | 繁体中文 | 杂文 | Github | 知乎专栏 | Facebook | Linkedin | Youtube | 打赏(Donations) | About
知乎专栏

48.9. FAQ 常见问题

48.9.1. Could not write JSON: failed to lazily initialize a collection of role

		
{"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>();
		
			

48.9.2. Query did not return a unique result: 2 results were returned

查询 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);
    }
			
			

48.9.3. Executing an update/delete query

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);
    }
			
			

48.9.4. could not initialize proxy [cn.netkiller.domain.Device#16] - no Session

第一种解决方法,捕捉 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类似	
			
			

48.9.5. this is incompatible with sql_mode=only_full_group_by

			
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',''));
			
			

48.9.6. A TupleBackedMap cannot be modified

			
    @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);
    }