【问题标题】:How to make JOIN in JPA?如何在 JPA 中进行 JOIN?
【发布时间】:2019-02-13 06:51:26
【问题描述】:

我的 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();
    }
}

当我在 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 中有效,而在 test 中却无效?

【问题讨论】:

    标签: java jpa testing join


    【解决方案1】:
    1. 为什么我得到两个部门实体?

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

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

    这会将部门与用户连接起来,从而为每个用户生成一个部门行。由于该部门有两个用户,因此结果将包含具有相同部门的 2 行。你想要的是where clausle 而不是fetch join

    1. 为什么 join 在 Main 中有效,但在测试中却无效?

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

    【讨论】:

    • 对不起,我可能误导了你。我不需要where 子句。我需要获得 一个 部门实体,其中包含 两个 用户实体。据我所知,即使使用LAZY 获取,我也可以从数据库中获取相关实体。我说的对吗?
    • 啊。我认为getAllWithUsers 的意思是获取所有拥有用户的部门。因此,要让所有部门都拥有他们的用户,您只需从您的 DAO 方法中省略 .fetch("users"); 部分。
    • 是的,LAZY fetching 你可以从数据库中获取相关实体。但是您需要主动访问该集合才能真正加载它。仅使用 System.out.println 或部门中的任何内容都不会加载用户集合,如果它是惰性获取的。
    猜你喜欢
    • 1970-01-01
    • 2018-11-06
    • 2011-06-12
    • 2019-07-17
    • 1970-01-01
    • 1970-01-01
    • 2015-11-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多