Java 如何加入JPA?

Java 如何加入JPA?,java,jpa,testing,join,Java,Jpa,Testing,Join,我的应用程序使用JPA(Hibernate)和Spring。我的爱好是: 部门 @Entity @Table(schema = "myschema") public class Department { @Id @GeneratedValue(generator = "uuid") @GenericGenerator(name = "uuid", strategy = "uuid2") @Column(columnDefinition = "BINARY(16)

我的应用程序使用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<>();
}
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();
    }
}
@Repository(“departmentDao”)
公共课部{
@持久上下文
私人实体管理者实体管理者;
@交易的
公共UUID保存(部门实体){
log.info(“将保留部门实体”,实体);
entityManager.persist(实体);
返回实体.getUuid();
}
公共列表getAllWithUsers(){
日志信息(“选择所有部门”);
CriteriaQuery criteria=entityManager.getCriteriaBuilder().createQuery(Department.class);
criteria.from(Department.class).fetch(“用户”);
返回entityManager.createQuery(条件).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']}]
ApplicationContext context=new ClassPathXmlApplicationContext(“META-INF/spring.xml”);
UserDao UserDao=(UserDao)context.getBean(“UserDao”);
DepartmentDao DepartmentDao=(DepartmentDao)context.getBean(“DepartmentDao”);
Department newDep=新部门(“WebDepartment”,new Date());
部门DAO.save(新DEP);
用户newUser1=新用户(“Test1”,newDep);
用户newUser2=新用户(“Test2”,newDep);
userDao.save(newUser1);
userDao.save(newUser2);
List deps=departmentDao.getAllWithUsers();
//副总裁
//[部门{name='WebDepartment',用户=['Test1','Test2']},
//部门{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 = []}]
    }
}
@ContextConfiguration(locations=“classpath:META-INF/spring test.xml”)
@RunWith(SpringJUnit4ClassRunner.class)
公共类测试{
@自动连线
私人部门;
@自动连线
私有UserDao UserDao;
@试验
@交易的
public void daoTests()引发NoSuchAlgorithmException{
Department newDep=新部门(“WebDepartment”,new Date());
部门DAO.save(新DEP);
用户newUser1=新用户(“Test1”,newDep);
用户newUser2=新用户(“Test2”,newDep);
userDao.save(newUser1);
userDao.save(newUser2);
List deps=departmentDao.getAllWithUsers();
//副总裁
//[部门{name='WebDepartment',用户=[]},
//部门{name='WebDepartment',users=[]}]
}
}
所以,我有两个问题。 1.为什么我有两个部门的资格证书? 2.为什么join在Main中有效,但在test中无效

  • 为什么我有两个部门的资格证书
  • 这是因为您正在DAO中执行
    JOIN-FETCH
    查询:

    criteria.from(Department.class).fetch("users")
    
    这会将部门与用户合并,从而为每个用户生成一个部门行。由于该部门有两个用户,因此结果将包含具有相同部门的两行。这里需要的是
    where
    子句,而不是
    fetchjoin

  • 为什么join在Main中有效,但在test中无效

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

    对不起,可能是我误导了您。我不需要
    where
    子句。我需要一个部门实体,里面有两个用户实体。正如我所知,即使使用
    LAZY
    fetching,我也可以从数据库中获取相关的实体。我说得对吗?啊。我认为
    getAllWithUsers
    意味着获取所有拥有用户的部门。因此,要获得所有部门及其用户,您只需省略
    .fetch(“用户”)DAO方法的一部分。是的,通过
    LAZY
    fetching,您可以从数据库中获取相关实体。但您需要主动访问该集合,才能真正地对其进行访问。仅使用
    System.out.println
    或部门中的任何内容都不会加载用户集合(如果它是惰性获取的)。
    criteria.from(Department.class).fetch("users")