如何在JPA中加入JOIN?

时间:2019-02-13 06:51:27

标签: java jpa testing join

我的JPA(休眠)和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();
    }
}

我在Main类中运行代码时,它会连接实体(但是重复它们,为什么?):

主要

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 个答案:

答案 0 :(得分:1)

  
      
  1. 我为什么要得到两个部门官员?
  2.   

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

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

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

  
      
  1. 为什么join在Main中起作用,但在测试中却不起作用?
  2.   

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