gpt4 book ai didi

java - 如何在 JPA 中加入 JOIN?

转载 作者:行者123 更新时间:2023-11-28 20:35:45 25 4
gpt4 key购买 nike

我使用 JPA (Hibernate) 和 Spring 的应用程序。我的实体是:

部门

@Entity
@Table(schema = "myschema")
public class Department {

@Id
@GeneratedValue(generator = "uuid")
@GenericGenerator(name = "uuid", strategy = "uuid2")
@Column(columnDefinition = "BINARY(16)", length = 16 )
private UUID uuid;

@Column(name = "name", length = 200, nullable = false)
private String name;

@OneToMany(fetch = FetchType.LAZY, mappedBy = "department", cascade = CascadeType.ALL, orphanRemoval = true)
List<User> users = new ArrayList<>();
}

用户

@Entity
@Table(schema = "myschema")
public class User {

@Id
@GeneratedValue(generator = "uuid")
@GenericGenerator(name = "uuid", strategy = "uuid2")
@Column(columnDefinition = "BINARY(16)", length = 16 )
private UUID uuid;

@NotNull
@Column(name = "login", length = 100, nullable = false)
private String login;

@ManyToOne
@JoinColumn(name = "department_fk", nullable = false)
private Department department;

}

DAO 部门:

@Repository("departmentDao")
public class DepartmentDao {

@PersistenceContext
private EntityManager entityManager;

@Transactional
public UUID save(Department entity) {
log.info("Department entity will be persisted", entity);
entityManager.persist(entity);
return entity.getUuid();
}

public List<Department> getAllWithUsers() {
log.info("Select all departments");
CriteriaQuery<Department> criteria = entityManager.getCriteriaBuilder().createQuery(Department.class);
criteria.from(Department.class).fetch("users");
return entityManager.createQuery(criteria).getResultList();
}
}

当我在主类中运行代码时,它会加入实体(但会重复它们,为什么?):

主要

ApplicationContext context = new ClassPathXmlApplicationContext("META-INF/spring.xml");
UserDao userDao = (UserDao) context.getBean("userDao");
DepartmentDao departmentDao = (DepartmentDao) context.getBean("departmentDao");

Department newDep = new Department("WebDepartment", new Date());
departmentDao.save(newDep);

User newUser1 = new User("Test1", newDep);
User newUser2 = new User("Test2", newDep);
userDao.save(newUser1);
userDao.save(newUser2);

List<Department> deps = departmentDao.getAllWithUsers();

//deps
//[Department{name='WebDepartment', users = ['Test1', 'Test2']},
// Department{name='WebDepartment', users = ['Test1', 'Test2']}]

当我用相同的代码运行单元测试时,部门列表仍然包含两个实体,每个部门都有空的用户列表:

@ContextConfiguration(locations = "classpath:META-INF/spring-test.xml")
@RunWith(SpringJUnit4ClassRunner.class)
public class DaoTests {

@Autowired
private DepartmentDao departmentDao;

@Autowired
private UserDao userDao;

@Test
@Transactional
public void daoTests() throws NoSuchAlgorithmException {

Department newDep = new Department("WebDepartment", new Date());
departmentDao.save(newDep);

User newUser1 = new User("Test1", newDep);
User newUser2 = new User("Test2", newDep);
userDao.save(newUser1);
userDao.save(newUser2);
List<Department> deps = departmentDao.getAllWithUsers();

//deps
//[Department{name='WebDepartment', users = []},
// Department{name='WebDepartment', users = []}]
}
}

所以,我有两个问题。1. 为什么我有两个部门实体?2. 为什么 join 在 Main 中起作用,但在测试中却不起作用?

最佳答案

  1. Why I get two Department-entites?

这是因为您正在 DAO 中执行 JOIN FETCH 查询:

criteria.from(Department.class).fetch("users")

这将部门与用户连接在一起,导致每个用户一个部门行。由于该部门有两个用户,因此结果将包含同一部门的 2 行。您在这里需要的是 where 子句而不是 fetch join

  1. Why join works in Main, but in test it doesn't?

它确实有效,但是您在您部门内的用户集合上使用 FetchType.LAZY。这意味着用户只有在您访问它们时才会从数据库中加载。您可以使用 FetchType.EAGER 立即加载用户。

关于java - 如何在 JPA 中加入 JOIN?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54664212/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com