当前位置: 首页 > 知识库问答 >
问题:

@EntityGraph/JOIN FETCH无法使用字节码eNahElement

申屠项明
2023-03-14

我正在使用字节码enanh水泥通过基本注释懒惰加载用户实体的头像属性;我还希望懒惰加载与成员实体(扩展用户)相关的身份证。到目前为止,一切正常,我的代码如下:

用户类:

@Data
@Entity
@Table(name = "users")
@Inheritance(strategy = InheritanceType.JOINED)
@JsonInclude(JsonInclude.Include.NON_DEFAULT)
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    @NotEmpty
    private String name;

    @NotEmpty
    private String surname;

    @Lob
    @NotNull
    @Basic(fetch = FetchType.LAZY)
    private byte[] avatar;

}

会员类:

@Data
@Entity
@Table(name = "members")
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true)
public class Member extends User {

    @NotNull
    @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    @LazyToOne(value = LazyToOneOption.NO_PROXY)
    private IdentityCard identityCard;

}

识别卡类别:

@Data
@Entity
@Table(name = "identityCards")
public class IdentityCard {

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

    @Lob
    @NotNull
    private byte[] backImage;

    @Lob
    @NotNull
    private byte[] frontImage;

}

波姆。xml

<plugins>
    <plugin>
        <groupId>org.hibernate.orm.tooling</groupId>
        <artifactId>hibernate-enhance-maven-plugin</artifactId>
        <version>${hibernate.version}</version>
        <executions>
            <execution>
                <configuration>
                    <failOnError>true</failOnError>
                    <enableLazyInitialization>true</enableLazyInitialization>
                </configuration>
                <goals>
                    <goal>enhance</goal>
                </goals>
            </execution>
        </executions>
    </plugin>
</plugins>

应用yml:

...
spring:
     jpa:
          open-in-view: false
...

现在,在我的控制器中,我想通过存储库中的实体图注释来获取成员的头像和身份证

控制器:

@Controller
@RequestMapping("members")
public class MemberController {

    @Autowired
    MemberService memberService;

    @GetMapping("/{id}")
    public String get(@PathVariable String id, Model model) {
        Optional<Member> member = memberService.findFullMemberById(Long.valueOf(id));

        // Using model to pass member and let thymeleaf process it
        return "members/form";
    }

}

成员库:

@Repository
public interface MemberRepository extends JpaRepository<Member, Long> {

    ...

    @EntityGraph(attributePaths = {"avatar", "identityCard"})
    Optional<Member> findFullMemberById(Long id);

}

但是我得到的成员对象总是有头像和标识卡属性设置为null。我还尝试了查询注释和LEFT JOIN FETCH,结果相同。

@Repository
public interface MemberRepository extends JpaRepository<Member, Long> {

    ...

    @Query("select m from Member m LEFT JOIN FETCH m.identityCard identityCard where m.id=:id")
    Optional<Member> findFullMemberById(Long id);

}
  • Spring靴:2.2.5。期末考试
  • 冬眠:5.4.12。决赛

谢谢你的帮助。非常感谢。

共有1个答案

颛孙博易
2023-03-14

从Hibernate 5.4.26开始,有两个截然不同的问题。

您正试图通过@EntityGraph获取一个懒惰的基本属性,这在Hibernate 5中不受支持,但Hibernate 6有一个功能请求,允许EntityGraph控制基本实体状态的加载(不仅仅是关联):https://hibernate.atlassian.net/browse/HHH-9270

我不知道是否有任何解决办法,我认为它不可能存在。enableLazyInitialization的另一种选择是使用子实体,或者更好的是使用投影,如中所述https://vladmihalcea.com/the-best-way-to-lazy-load-entity-attributes-using-jpa-and-hibernate

事实上,enableLazy初始化允许使用@LazyToOne(NO_PROXY)懒惰加载@OneToOne,但是JOIN FETCH变得更加困难:您必须在会话打开时初始化关联,以便能够在会话之外使用它,并且它仍然会产生N 1 SELECT!

所有惰性单一属性都被排除在初始加载计划之外(包括惰性ToOne关联的联接列)。

无连接获取

通过id查找会员时,Hibernate将生成:

  1. 首先选择以获取渴望的属性:id、name、姓氏
  2. 需要时,N 1选择读取相应隐式@LazyGroup化身、身份证\u id
  3. N 1选择以获取相关的identityCard

用join-fetch

当加入并获取identityCard时,Hibernate会生成适当的SQL连接来获取关联的identityCard,但它会错过成员。identity_card_idjoin列,结果是LazyInitializationException(我没有空值,正如您在问题中提到的,但它完全相同)。

  1. 第一个SELECT得到渴望属性id,name,surname和加入的实体属性:IdtyCard.id,IdtyCard.frontImage,IdtyCard.backImage
  2. 当需要时,一个N 1 SELECT读取相应的隐式懒惰属性@LazyGroupavatar,identity_card_id(相同的没有连接获取!)

存在与此错误(或功能…)相关的未决问题:

>

https://hibernate.atlassian.net/browse/HHH-13134JOIN FETCH无法与增强的实体一起正常工作

启用此新选项:

hibernate.bytecode.allow_enhancement_as_proxy=true

您将获得与未启用字节码增强和enableLazy初始化相同的行为,并且JOIN FETCH将按预期工作,但您仍然能够懒惰地加载基本属性和@OneToOne

这样,你甚至不需要在所有懒惰的ToOne上添加@LazyToOne(无代理)(除了@OneToOne)和@LazyGroup

见我对这个问题的评论。https://hibernate.atlassian.net/browse/HHH-13134?focusedCommentId=107604

有关此新功能的更多信息,请查看https://in.relation.to/2019/07/30/bytecode-proxy/

另一个建议

不使用新的Hibernate时。字节码。允许作为_proxy或@LazyGroup的_增强_,所有惰性属性都隐式地属于同一组。因此,当懒洋洋地加载identityCard时,Hibernate也会加载avatar,这可能不是您想要的。

因此,您应该使用@LazyGroup(“lob”)@LazyGroup(“identityCard”)或使用Hibernate来分离lob和身份证。字节码。允许作为代理进行增强

 类似资料:
  • 我试图随机化一个字节数组,但它不允许我编译它,因为下面的错误。它甚至不适用于而不是。 错误C2338:independent_bits_engine的无效模板参数:N465929.6.1.1[rand.req.genl]/1f需要un有符号短、无符号int、无符号长或无符号长 消息:请参阅类模板实例化的d::independent_bits_engine 错误C2338:注意:不允许使用字符、有符

  • javac是否有可能为以下过程生成无法访问的字节码? 当我查看字节码(javap-v)的异常表时,有以下条目看起来很奇怪: 和 现在的问题是,只有捕捉到类型为“any”而不是“Throwable”的异常,才能访问某些代码。在什么情况下会发生这种情况? ======编辑=====感谢您迄今为止的回答。让我给出另一个证据来证明我真的不理解异常处理:考虑以下过程 如果查看字节码,您会发现: 和异常表 这

  • 问题内容: 我有一个套接字服务器,应该从客户端接收UTF-8有效字符。 问题是某些客户端(主要是黑客)正在通过它发送所有错误的数据。 我可以轻松地区分真正的客户端,但是我会将所有发送的数据记录到文件中,以便以后进行分析。 有时我会得到这样的导致错误的字符。 我需要能够使带有或不带有这些字符的字符串UTF-8。 更新: 对于我的特殊情况,套接字服务是MTA,因此我只希望接收ASCII命令,例如: 我

  • 问题内容: 我试图在Python熊猫中做一些数据工作,但写出我的结果时遇到麻烦。我将数据读取为CSV文件,并一直将每个脚本导出为自己的CSV文件,效果很好。最近,尽管我尝试使用工作表将所有内容导出到1个Excel文件中,但其中一些工作表给我一个错误 “’utf8’编解码器无法解码位置1的字节0xe9:无效的继续字节” 我什至不知道如何开始寻找任何可能导致导出到Excel的问题的字符。不知道为什么导

  • 我有一个套接字服务器,它应该从客户端接收UTF-8有效字符。 问题是一些客户端(主要是黑客)正在通过它发送所有错误类型的数据。 我可以很容易地分辨出真正的客户机,但我会将发送的所有数据记录到文件中,以便以后进行分析。 有时我会遇到这样的字符,导致UnicodeDecodeError错误。 我需要能够使字符串UTF-8有或没有这些字符。 更新: 对于我的特殊情况,套接字服务是MTA,因此我只希望接收

  • 问题内容: 我有一个套接字服务器,应该从客户端接收UTF-8有效字符。 问题是某些客户端(主要是黑客)正在通过它发送所有错误的数据。 我可以轻松地区分真正的客户端,但是我会将所有发送的数据记录到文件中,以便以后进行分析。 有时我会收到这样的字符œ,从而导致错误。 我需要使字符串UTF-8带有或不带有这些字符。 更新: 对于我的特殊情况,套接字服务是MTA,因此我只希望接收ASCII命令,例如: 我