Java 如何在@OneToOne关系中使用fetch join?
我有实体贴子,贴子细节。 这些是一对一关系,PostDetail是可选的Java 如何在@OneToOne关系中使用fetch join?,java,spring,spring-data-jpa,jpql,Java,Spring,Spring Data Jpa,Jpql,我有实体贴子,贴子细节。 这些是一对一关系,PostDetail是可选的 class Post { @Id private int id; @Column private String title; @Column private Strint contents; @OneToOne(cascade = CascadeType.ALL) @PrimaryKeyJoinColumn private PostDetail
class Post {
@Id
private int id;
@Column
private String title;
@Column
private Strint contents;
@OneToOne(cascade = CascadeType.ALL)
@PrimaryKeyJoinColumn
private PostDetail postDetail;
}
class PostDetail {
@Id
private int id;
@Column
private boolean duplicated;
@OneToOne
private Post post;
}
public interface PostRepository extends JpaRepository<Post, Integer> {
@Transactional
@Query("SELECT a FROM Post a LEFT JOIN FETCH a.postDetail")
public Page<Post> getAll(Example<Post> example, Pageable pageable);
@Transactional
@Query("SELECT a FROM Post a LEFT JOIN FETCH a.postDetail")
public List<Post> getAll();
}
class Post{
@身份证
私有int-id;
@纵队
私有字符串标题;
@纵队
私密内容;
@OneToOne(级联=级联类型.ALL)
@PrimaryKeyJoinColumn
私人PostDetail PostDetail;
}
类PostDetail{
@身份证
私有int-id;
@纵队
私有布尔复制;
@奥内托内
私人邮政;
}
公共接口PostRepository扩展了JpaRepository{
@交易的
@查询(“从左连接中选择Post获取a.POSTDEAL”)
公共页面getAll(例如,Pageable Pageable);
@交易的
@查询(“从左连接中选择Post获取a.POSTDEAL”)
公共列表getAll();
}
当应用程序启动时,会发生异常
原因:org.hibernate.QueryException:查询指定了联接获取,但获取的关联的所有者不在选择列表中
有什么问题?我尝试这样做是为了避免在查询post列表(getAll())时出现N+1问题
对不起,我修改了我的问题 两个PostRepository的方法都会出错 第一个getAll()抛出错误“查询指定的联接获取…” 第二个getAll()抛出错误 org.mariadb.jdbc.internal.common.QueryException:“字段列表”中的未知列“postdetail1\u.post\u id” 如果您正在使用,则
Post
中的id
类型应与JpaRepository
中的id
一致,只需进行一些修改:
@Entity
@Table(name = "post")
class Post {
@Id
private Integer id;
@Column
private String title;
@Column
private String contents;
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "postDetail_id")//assume this is the name
private PostDetail postDetail;
}
您不必为getAll()
定义查询,Spring Data JPA为常见查询提供了一些嵌入式实现,只需调用它们:
public interface CrudRepository<T, ID extends Serializable> extends Repository<T, ID> {
<S extends T> S save(S entity);
T findOne(ID primaryKey);
Iterable<T> findAll();
Long count();
void delete(T entity);
boolean exists(ID primaryKey);
// … more functionality omitted.
}
然后,您可以在单元测试中对其进行测试:
@RunWith(SpringRunner.class)
@SpringBootTest
public class MyTest {
@Autowired
private PostRepository repo;
@Test
public void testFindAll(){
repo.findAll();
}
@Test
public void testFindById(){
repo.findOne(id);
}
}
若要避免1+N查询问题,可以使用EntityGraph。只需在自定义Repo中重写'findAll'方法,并对其使用EntityGraph注释,如下所示:
public interface PostRepository extends JpaRepository<Post, Integer> {
@Override
@EntityGraph(attributePaths = {"postDetail"})
Page<Post> findAll(Pageable pageable);
@Override
@EntityGraph(attributePaths = {"postDetail"})
List<Post> findAll();
}
公共接口PostRepository扩展了JpaRepository{
@凌驾
@EntityGraph(AttributePath={“postDetail”})
页面findAll(可分页可分页);
@凌驾
@EntityGraph(AttributePath={“postDetail”})
列出findAll();
}
这在我看来很好(除了无用的事务注释)。我猜例外是关于另一个查询。发布完整的堆栈跟踪。提取的关联的所有者显然存在于选择列表中。@PrimaryKeyJoinColumn
可能有问题,如果删除注释,代码是否有效?一种解决方法是使用hibernate的@Fetch
注释声明默认的抓取策略,并删除连接抓取
altogether修改的问题。谢谢,第二个getAll()问题已经解决。但是,我不能使用findAll(),因为这会产生太多的查询。最终,我应该使用first getAll()进行页面导航。如何将FETCH JOIN与pageable一起使用?@chaeyk我很肯定,如果您读取异常的堆栈跟踪,您会意识到问题所在,并知道如何解决问题。我让你发的,但你没有。提示:当使用分页时,Spring需要执行一个查询来计算元素总数。@JBNizet否,我找不到解决方案。第二个getAll()是我的错。我删除了PostDetail.post,问题就消失了。但当有示例和Pageable参数时,我不能使用fetchjoin。
public interface PostRepository extends JpaRepository<Post, Integer> {
@Override
@EntityGraph(attributePaths = {"postDetail"})
Page<Post> findAll(Pageable pageable);
@Override
@EntityGraph(attributePaths = {"postDetail"})
List<Post> findAll();
}