在升级到Hibernate6和Spring Boot3之后,下面的代码抛出了一个错误(Cannot project java.lang.Short to com.cubetrek.cubetrekplayground.database.TrackData$Sharing; Target type is not an interface and no matching Converter found).

@Entity类如下所示:

@Entity(name = "trackdata")
@Table(name = "trackdata")
public class TrackData implements Serializable {

    public enum Sharing {
        PRIVATE, FRIENDS, PUBLIC;
    }

    @Getter
    @Setter
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Getter
    @Setter
    @Column(name = "title")
    private String title;

    @Getter
    @Setter
    @Enumerated(EnumType.ORDINAL)
    @Column(name = "sharing")
    private Sharing sharing;
    
    // loads of other fields and getters and setters...

    //and here's the interface
    
    public interface TrackMetadata {
        Long getId();
        @JsonSerialize(using = TitleSerializer.class, as=String.class)
        String getTitle();

        @Enumerated(EnumType.ORDINAL)
        Sharing getSharing();
    }
}

在TrackDataRepository中:

public interface TrackDataRepository extends JpaRepository<TrackData, Long>, JpaSpecificationExecutor<TrackData> {
    Optional<TrackData> findById(Long id);
    
    // and here's the query in question:
    @Query(value = "SELECT trackdata.id, trackdata.title, trackdata.sharing FROM trackdata " +
            "WHERE trackdata.id = :trackid", nativeQuery = true)
    TrackData.TrackMetadata getMetadata(long trackid);
}

实体的工作方式与预期一致:

    TrackData trackData = trackDataRepository.getReferenceById(21682L);
    System.out.println(trackData.getSharing()); //works fine

但界面却搞砸了:

TrackData.TrackMetadata td2 = trackDataRepository.getMetadata(21682L);
System.out.println(td2.getTitle()); //works
System.out.println(td2.getSharing()); //ERROR!!

错误似乎是因为从short到enum的投影:

100


此外,定制的Converter似乎不能完成此任务:

    @Converter
    public static class SharingConverter implements AttributeConverter<Sharing, Short> {
        @Override
        public Short convertToDatabaseColumn(Sharing sharing) {
            return (short)sharing.ordinal();
        }

        @Override
        public Sharing convertToEntityAttribute(Short dbData) {
            return Sharing.values()[dbData];
        }
    }
    public interface TrackMetadata {
        Long getId();
        @JsonSerialize(using = TitleSerializer.class, as=String.class)
        String getTitle();

        @Convert(converter = SharingConverter.class)
        Sharing getSharing();
    }

推荐答案

有一个变通的解决方案来解决这个问题.将您的转换器类标记为带有@Component的Bean.

@Component
@Converter(autoApply = true)
public class SharingConverter implements AttributeConverter<Sharing, Short> {
  @Override
  public Short convertToDatabaseColumn(Sharing sharing) {
    return (short)sharing.ordinal();
  }

  @Override
  public Sharing convertToEntityAttribute(Short dbData) {
    return Sharing.values()[dbData];
  }
}

然后使用Spel到@ValueShort转换为枚举.

target是一个将被绑定到"支持投影的聚合根"(Spring data JPA文档,"一个开放投影"一节)的标识符.

  public interface TrackMetadata {
    Long getId();

    String getTitle();

    @Value("#{@sharingConverter.convertToEntityAttribute(target.sharing)}")
    Sharing getSharing();
  }

Java相关问答推荐

RxJava PublishSubject缓冲区元素超时

如何在Java中声明未使用的变量?

在Java Stream上调用collect方法出现意外结果

有关手动创建的包的问题

为什么在枚举中分支预测比函数调用快?

具有多种令牌类型和段的复杂Java 17正则表达式

Bean定义不是从Spring ApplationConext.xml文件加载的

Docker不支持弹性APM服务器

如何将Java文档配置为在指定的项目根目录中生成?

使用Class.this.field=Value初始化构造函数中的最后一个字段会产生错误,而使用this.field=Value则不会

Spring Boot&;Docker:无法执行目标org.springframework.boot:spring-boot-maven-plugin:3.2.0:build-image

在处理2个映射表时,没有更多的数据可从套接字读取

如何在ImageIO或十二只猴子中旋转TIFF CMYK图像?

为什么项目名称出现在我的GET请求中?

使用@ExceptionHandler的GlobalExceptionHandler还是来自服务器的REST应答的ResponseEntity?

从字节数组切换到JakartaMail org.springframework.mail.javamail.JavaMailSender InputStreamResource

为什么Spring要更改Java版本配置以及如何正确设置?

try 添加;按流派搜索;在Web应用程序上,但没有;I don’我不知道;It’这个代码错了

message.acknowledge()没有';在使用Spring Boot在ActiveMQ中读取消息后,t将消息出列

Java ModbusRTU写寄存器