Hibernate带WHERE条件的SELECT查询及实体映射类问题
嘿,针对你的User实体类,我整理了几种常用的Hibernate带WHERE条件查询的实现方式,你可以根据自己的场景来选:
基于User实体类的Hibernate带WHERE条件查询实现
1. 使用JPQL(JPA查询语言)
JPQL是面向实体类的查询语言,可读性强,也是最常用的方式之一。它直接操作你的User实体,不用关心底层数据库的表结构。
示例代码:
// 获取EntityManager(如果用原生Hibernate的话也可以用Session,用法类似) EntityManager em = entityManagerFactory.createEntityManager(); em.getTransaction().begin(); // 单个条件:根据login查询用户 String jpql = "SELECT u FROM User u WHERE u.login = :loginParam"; Query<User> query = em.createQuery(jpql, User.class); query.setParameter("loginParam", "john_doe"); // 如果确定只有一个结果,用getSingleResult();不确定的话用getResultList() User targetUser = query.getSingleResult(); // 多个条件:同时匹配login和email String jpqlMulti = "SELECT u FROM User u WHERE u.login = :login AND u.email = :email"; Query<User> multiQuery = em.createQuery(jpqlMulti, User.class); multiQuery.setParameter("login", "john_doe"); multiQuery.setParameter("email", "john@example.com"); List<User> matchedUsers = multiQuery.getResultList(); em.getTransaction().commit(); em.close();
小提示:使用命名参数(:loginParam这种)比位置参数更清晰,还能避免因参数顺序搞错导致的问题,同时也能防止SQL注入。
2. 使用Hibernate Criteria API(类型安全的动态查询)
如果你需要处理动态条件(比如前端多条件筛选,有些条件可能为空),Criteria API是个好选择——它是类型安全的,编译期就能检查出字段名拼写错误,不用等到运行时才报错。
示例代码:
Session session = sessionFactory.openSession(); Transaction tx = session.beginTransaction(); // 创建Criteria构建器和查询对象 CriteriaBuilder cb = session.getCriteriaBuilder(); CriteriaQuery<User> cq = cb.createQuery(User.class); Root<User> userRoot = cq.from(User.class); // 单个条件:匹配login cq.select(userRoot).where(cb.equal(userRoot.get("login"), "john_doe")); User targetUser = session.createQuery(cq).getSingleResult(); // 多个条件:同时匹配login和email(用and连接) cq.select(userRoot).where( cb.and( cb.equal(userRoot.get("login"), "john_doe"), cb.equal(userRoot.get("email"), "john@example.com") ) ); List<User> matchedUsers = session.createQuery(cq).getResultList(); // 动态条件示例:根据传入的参数决定是否添加查询条件 List<Predicate> predicates = new ArrayList<>(); String loginParam = "john_doe"; // 假设这是前端传入的参数 String emailParam = "john@example.com"; if (loginParam != null && !loginParam.isEmpty()) { predicates.add(cb.equal(userRoot.get("login"), loginParam)); } if (emailParam != null && !emailParam.isEmpty()) { predicates.add(cb.equal(userRoot.get("email"), emailParam)); } cq.where(predicates.toArray(new Predicate[0])); List<User> dynamicResult = session.createQuery(cq).getResultList(); tx.commit(); session.close();
3. 使用原生SQL查询
如果遇到HQL/JPQL不好实现的复杂查询,或者需要直接操作数据库原生语法,可以用原生SQL查询。不过要注意,这种方式会和数据库耦合,换数据库可能需要修改SQL语句。
示例代码:
Session session = sessionFactory.openSession(); Transaction tx = session.beginTransaction(); // 注意这里的表名是数据库实际的表名(和User实体的@Table(name="user")一致) String sql = "SELECT * FROM user WHERE login = ? AND email = ?"; NativeQuery<User> query = session.createNativeQuery(sql, User.class); query.setParameter(1, "john_doe"); query.setParameter(2, "john@example.com"); List<User> matchedUsers = query.getResultList(); tx.commit(); session.close();
一些关键注意事项
- 事务管理:查询操作最好放在事务中执行,如果是只读查询,可以设置为只读事务来优化性能。
- 防止SQL注入:绝对不要直接把用户输入的字符串拼接进查询语句里!一定要用参数绑定的方式(不管是命名参数还是位置参数)。
- 结果处理:
getSingleResult()会在没有结果或者结果超过一个时抛出异常,如果不确定结果数量,优先用getResultList()然后判断列表是否为空。
内容的提问来源于stack exchange,提问作者Nikita
相关产品推荐
相关产品推荐

