如何将 fetch join 与 @OneToOne 关系一起使用?
How can I use fetch join with @OneToOne relationship?
我有实体 Post、Post详细信息。
它们是一对一的关系,Post详细信息是可选的。
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();
}
应用启动时出现异常
Caused by: org.hibernate.QueryException: query specified join fetching, but the owner of the fetched association was not present in the select list ...
问题是什么?我正在尝试这样做以避免在查询 post 列表(getAll())时出现 N+1 问题。
抱歉,我修改了问题。
两个PostRepository的方法都出错。
首先 getAll() 抛出错误 "query specified join fetching ..."
第二次 getAll() 抛出错误
org.mariadb.jdbc.internal.common.QueryException: Unknown column 'postdetail1_.post_id' in 'field list'
由于您使用的是Spring Data JPA,Post
中id
的类型应该与JpaRepository<T, ID extends Serializable>
中的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 数据定义查询 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.
}
所以 PostRepository
就像:
public interface PostRepository extends JpaRepository<Post, Integer> {
}
那你可以在你的单元测试中测试它:
@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();
}
我有实体 Post、Post详细信息。 它们是一对一的关系,Post详细信息是可选的。
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();
}
应用启动时出现异常
Caused by: org.hibernate.QueryException: query specified join fetching, but the owner of the fetched association was not present in the select list ...
问题是什么?我正在尝试这样做以避免在查询 post 列表(getAll())时出现 N+1 问题。
抱歉,我修改了问题。
两个PostRepository的方法都出错。
首先 getAll() 抛出错误 "query specified join fetching ..."
第二次 getAll() 抛出错误
org.mariadb.jdbc.internal.common.QueryException: Unknown column 'postdetail1_.post_id' in 'field list'
由于您使用的是Spring Data JPA,Post
中id
的类型应该与JpaRepository<T, ID extends Serializable>
中的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 数据定义查询 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.
}
所以 PostRepository
就像:
public interface PostRepository extends JpaRepository<Post, Integer> {
}
那你可以在你的单元测试中测试它:
@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();
}