Hibernate Spring数据Jpa延迟加载未按预期工作
嘿,我正在处理Spring数据jpa,我只想懒洋洋地获取数据 我在我的spring项目中使用lombook 我想通过电子邮件获取用户及其角色 我很少上课Hibernate Spring数据Jpa延迟加载未按预期工作,hibernate,spring-boot,spring-data-jpa,spring-data,lombok,Hibernate,Spring Boot,Spring Data Jpa,Spring Data,Lombok,嘿,我正在处理Spring数据jpa,我只想懒洋洋地获取数据 我在我的spring项目中使用lombook 我想通过电子邮件获取用户及其角色 我很少上课 @Entity @Table(name = "user") @Data public class User extends DateAudit { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; priva
@Entity
@Table(name = "user")
@Data
public class User extends DateAudit {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String name;
@Column(columnDefinition = "char(50)")
private String email;
@Column(columnDefinition = "char(15)")
private String phone;
private String password;
@Column(columnDefinition = "bit")
private boolean isActive;
@Column(columnDefinition = "ENUM('MALE', 'FEMALE', 'OTHER')")
@Enumerated(EnumType.STRING)
private Gender gender;
@OneToMany(fetch = FetchType.LAZY, mappedBy = "user")
private List<UserRole> userRoles;
@OneToOne(fetch = FetchType.LAZY, mappedBy = "user")
private UserProfile userProfile;
}
这是我的用户存储库
@Repository
public interface UserRepository extends CrudRepository<User, Integer> {
@EntityGraph(attributePaths = {"userRoles"})
User findByEmail(String email);
}
我在application.properties中添加了以下属性
spring.jpa.properties.hibernate.show_sql=true
所以当我点击邮递员的测试动作时
我看到在我的应用程序控制台中执行了两个查询
Hibernate: select user0_.id as id1_21_0_, userroles1_.id as id1_23_1_, user0_.created_at as created_2_21_0_, user0_.updated_at as updated_3_21_0_, user0_.email as email4_21_0_, user0_.gender as gender5_21_0_, user0_.is_active as is_activ6_21_0_, user0_.name as name7_21_0_, user0_.password as password8_21_0_, user0_.phone as phone9_21_0_, userroles1_.hospital_id as hospital2_23_1_, userroles1_.role_id as role_id3_23_1_, userroles1_.user_id as user_id4_23_1_, userroles1_.user_id as user_id4_23_0__, userroles1_.id as id1_23_0__ from user user0_ left outer join user_role userroles1_ on user0_.id=userroles1_.user_id where user0_.email=?
Hibernate: select userprofil0_.id as id1_22_0_, userprofil0_.created_at as created_2_22_0_, userprofil0_.updated_at as updated_3_22_0_, userprofil0_.avg_rating as avg_rati4_22_0_, userprofil0_.city_id as city_id8_22_0_, userprofil0_.cnic as cnic5_22_0_, userprofil0_.date_of_birth as date_of_6_22_0_, userprofil0_.picture as picture7_22_0_, userprofil0_.user_id as user_id9_22_0_ from user_profile userprofil0_ where userprofil0_.user_id=?
我对用户配置文件不感兴趣。我做错了什么。一对一的关系被急切地加载。即使我们指示hibernate惰性地加载它们,hibernate也会忽略这个提示 为了克服这个问题,我们需要启用字节码增强 字节码增强 在我们的例子中,我们使用字节码增强插件来增强实体类的字节码,并允许我们使用无代理延迟抓取策略。我们可以通过以下方式在pom.xml文件中定义插件:
<build>
<plugins>
<plugin>
<groupId>org.hibernate.orm.tooling</groupId
<artifactId>hibernate-enhance-maven-plugin</artifactId>
<version>5.4.2.Final</version>
<executions>
<execution>
<configuration><enableLazyInitialization>true</enableLazyInitialization></configuration>
<goals>
<goal>enhance</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
一对一的关系被急切地加载。即使我们指示hibernate惰性地加载它们,hibernate也会忽略这个提示 为了克服这个问题,我们需要启用字节码增强 字节码增强 在我们的例子中,我们使用字节码增强插件来增强实体类的字节码,并允许我们使用无代理延迟抓取策略。我们可以通过以下方式在pom.xml文件中定义插件:
<build>
<plugins>
<plugin>
<groupId>org.hibernate.orm.tooling</groupId
<artifactId>hibernate-enhance-maven-plugin</artifactId>
<version>5.4.2.Final</version>
<executions>
<execution>
<configuration><enableLazyInitialization>true</enableLazyInitialization></configuration>
<goals>
<goal>enhance</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
这是因为它是一个双向关联,Hibernate需要知道它是否应该用null或代理类初始化userProfile属性,它只能通过查询user\u profile表来找到这一点 您可以避免删除外键列并对两个关联实体使用相同的主键值,因为您必须在所属端使用MapsId注释,如下所示:
@Entity
@Table(name = "user_profile")
@Data
public class UserProfile extends DateAudit {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@OneToOne
@MapsId
@JoinColumn(name = "id")
private User user;
.
.
.
}
在这里,您可以查看有关此问题的完整指南
如果您不想使用同一个键,另一个选项是将其映射为OneToMany关系。这是因为它是一个双向关联,Hibernate需要知道它是否应该使用null或代理类初始化userProfile属性,并且它只能通过查询user\u profile表来找到 您可以避免删除外键列并对两个关联实体使用相同的主键值,因为您必须在所属端使用MapsId注释,如下所示:
@Entity
@Table(name = "user_profile")
@Data
public class UserProfile extends DateAudit {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@OneToOne
@MapsId
@JoinColumn(name = "id")
private User user;
.
.
.
}
在这里,您可以查看有关此问题的完整指南
另一个选项,如果您不想使用同一个键,则只需将其映射为一个omany关系。我如您所说尝试了,但控制台输出仍然相同,它正在执行2个查询您可以添加查询的控制台日志吗,可能是第二个问题现在不同了为什么你把@LazyToOne放在用户角色上了它的oneToManyyar koi faraq nahi parh raha相同的结果aa raha hay main khud 1周说laga hun是maslay ko resolve karnay main谢谢你提到
@LazyGroup
,我试过了,但控制台输出仍然是一样的,它执行2个查询你能添加查询的控制台日志吗,可能是第2个查询现在不同了为什么你把@LazyToOne放在用户角色上了它的oneToManyyar koi faraq nahi parh raha相同的结果aa raha hay main khud 1周说laga hun是maslay ko resolve karnay main谢谢你提到@LazyGroup
嘿,你的解决方案看起来很清楚,只有一件事不清楚,用户id不会在用户配置文件中添加为fk我使用你的解决方案吗?是的,没错,这就是想法。嘿,你的解决方案看起来非常清楚,只有一件事不清楚,用户id不会在用户配置文件中添加为fk我使用你的解决方案吗?是的,没错,这就是想法
@OneToOne(fetch = FetchType.LAZY, mappedBy = "user")
@LazyToOne(LazyToOneOption.NO_PROXY)
@LazyGroup("userProfile")
private UserProfile userProfile;
@Entity
@Table(name = "user_profile")
@Data
public class UserProfile extends DateAudit {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@OneToOne
@MapsId
@JoinColumn(name = "id")
private User user;
.
.
.
}