将 Hibernate HQL 应用于 H2 时遇到困难
Posted
技术标签:
【中文标题】将 Hibernate HQL 应用于 H2 时遇到困难【英文标题】:Facing difficulty with Hibernate HQL when applying it to H2 【发布时间】:2014-09-15 06:14:03 【问题描述】:我是 hibernate 和 spring maven 环境的新手。
我尝试使用 H2 实现嵌入式数据库,之前使用的是 mysql。有两个 DAO
OffersDao.java
package com.skam940.main.dao;
import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
@Repository
@Component("offersDao")
@Transactional
public class OffersDao
@Autowired
private SessionFactory sessionFactory;
public Session session()
return sessionFactory.getCurrentSession();
@SuppressWarnings("unchecked")
public List<Offer> getOffers()
Criteria crit = session().createCriteria(Offer.class);
crit.createAlias("user", "u").add(Restrictions.eq("u.enabled", true));
return crit.list();
@SuppressWarnings("unchecked")
public List<Offer> getOffers(String username)
Criteria crit = session().createCriteria(Offer.class);
crit.createAlias("user", "u");
crit.add(Restrictions.eq("u.enabled", true));
crit.add(Restrictions.eq("u.username", username));
return crit.list();
public void saveOrUpdate(Offer offer)
session().saveOrUpdate(offer);
public boolean delete(int id)
Query query = session().createQuery("delete from Offer where id=:id");
query.setLong("id", id);
return query.executeUpdate() == 1;
public Offer getOffer(int id)
Criteria crit = session().createCriteria(Offer.class);
crit.createAlias("user", "u");
crit.add(Restrictions.eq("u.enabled", true));
crit.add(Restrictions.idEq(id));
return (Offer) crit.uniqueResult();
和UsersDao.java
package com.skam940.main.dao;
import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
@Repository
@Transactional
@Component("usersDao")
public class UsersDao
@Autowired
private PasswordEncoder passwordEncoder;
@Autowired
private SessionFactory sessionFactory;
public Session session()
return sessionFactory.getCurrentSession();
@Transactional
public void create(User user)
user.setPassword(passwordEncoder.encode(user.getPassword()));
session().save(user);
public boolean exists(String username)
Criteria crit = session().createCriteria(User.class);
crit.add(Restrictions.idEq(username));
User user = (User) crit.uniqueResult();
return user != null;
@SuppressWarnings("unchecked")
public List<User> getAllUsers()
return session().createQuery("from User").list();
不,我得到了一个例外
HTTP 状态 500 - PreparedStatementCallback;错误的 SQL 语法 [选择用户名、密码,从二进制用户名 = ?的用户启用];嵌套异常是 org.h2.jdbc.JdbcSQLException:找不到列“BINARY”; SQL语句:
我想在这里做的事情是让用户名区分大小写,显然 H2 将 BINARY 识别为表名,但不是类型或你所说的任何东西,谁能告诉哪个方法正在实现这个 SQL语法?
用户.java
package com.skam940.main.dao;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
import org.hibernate.validator.constraints.NotBlank;
import com.skam940.main.validation.ValidEmail;
@Entity
@Table(name="users")
public class User
@NotBlank(groups=PersistenceValidationGroup.class, FormValidationGroup.class)
@Size(min=6, max=15, groups=PersistenceValidationGroup.class, FormValidationGroup.class)
@Pattern(regexp="^\\w8,$", groups=PersistenceValidationGroup.class, FormValidationGroup.class)
@Id
@Column(name="username")
private String username;
@NotBlank(groups=PersistenceValidationGroup.class, FormValidationGroup.class)
@Pattern(regexp="^\\S+$", groups=PersistenceValidationGroup.class, FormValidationGroup.class)
@Size(min=8, max=15, groups=PersistenceValidationGroup.class, FormValidationGroup.class)
private String password;
@ValidEmail(groups=PersistenceValidationGroup.class, FormValidationGroup.class)
private String email;
@NotBlank(groups=PersistenceValidationGroup.class, FormValidationGroup.class)
@Size(min=3, max=30, groups=FormValidationGroup.class)
private String name;
private boolean enabled = false;
private String authority;
public User()
public User(String username, String name, String password, String email, boolean enabled,
String authority)
this.username = username;
this.name = name;
this.password = password;
this.email = email;
this.enabled = enabled;
this.authority = authority;
public String getUsername()
return username;
public void setUsername(String username)
this.username = username;
public String getPassword()
return password;
public void setPassword(String password)
this.password = password;
public boolean isEnabled()
return enabled;
public void setEnabled(boolean enabled)
this.enabled = enabled;
public String getAuthority()
return authority;
public void setAuthority(String authority)
this.authority = authority;
public String getEmail()
return email;
public void setEmail(String email)
this.email = email;
public String getName()
return name;
public void setName(String name)
this.name = name;
@Override
public int hashCode()
final int prime = 31;
int result = 1;
result = prime * result
+ ((authority == null) ? 0 : authority.hashCode());
result = prime * result + ((email == null) ? 0 : email.hashCode());
result = prime * result + (enabled ? 1231 : 1237);
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result
+ ((username == null) ? 0 : username.hashCode());
return result;
@Override
public boolean equals(Object obj)
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
User other = (User) obj;
if (authority == null)
if (other.authority != null)
return false;
else if (!authority.equals(other.authority))
return false;
if (email == null)
if (other.email != null)
return false;
else if (!email.equals(other.email))
return false;
if (enabled != other.enabled)
return false;
if (name == null)
if (other.name != null)
return false;
else if (!name.equals(other.name))
return false;
if (username == null)
if (other.username != null)
return false;
else if (!username.equals(other.username))
return false;
return true;
@Override
public String toString()
return "User [username=" + username + ", email=" + email + ", name="
+ name + ", enabled=" + enabled + ", authority=" + authority
+ "]";
Offer.java
package com.skam940.main.dao;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.validation.constraints.Size;
@Entity
@Table(name="offers")
public class Offer
@Id
@GeneratedValue
// because this is an auto increment value
private int id;
@Size(min=5, max=255, groups=PersistenceValidationGroup.class, FormValidationGroup.class)
@Column(name="text")
private String text;
// every user can have only one offer
@ManyToOne
@JoinColumn(name="username")
private User user;
public Offer()
this.user = new User();
public Offer(User user, String text)
this.user = user;
this.text = text;
public Offer(int id, User user, String text)
this.id = id;
this.user = user;
this.text = text;
public int getId()
return id;
public void setId(int id)
this.id = id;
public String getText()
return text;
public void setText(String text)
this.text = text;
public User getUser()
return user;
public void setUser(User user)
this.user = user;
public String getUsername()
return user.getUsername();
@Override
public int hashCode()
final int prime = 31;
int result = 1;
result = prime * result + ((text == null) ? 0 : text.hashCode());
result = prime * result + ((user == null) ? 0 : user.hashCode());
return result;
@Override
public boolean equals(Object obj)
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Offer other = (Offer) obj;
if (text == null)
if (other.text != null)
return false;
else if (!text.equals(other.text))
return false;
if (user == null)
if (other.user != null)
return false;
else if (!user.equals(other.user))
return false;
return true;
@Override
public String toString()
return "Offer [id=" + id + ", text=" + text + ", user=" + user + "]";
完整的文件内容在这里-> https://app.box.com/s/c3uq71khbwf05p8asu27
【问题讨论】:
在 exists 方法中Restrictions.eq
而不是 Restrictions.idEq
不能正常工作(我猜是问题出在哪里)?
@geo 我试过了,我认为它已经实现了,因为用户名是外键和主键集成。
不管是不是外键,你所做的只是用它作为标准
你能发布你的 UDT 映射吗?
@geoand 我已经尝试改变它,我得到一个错误the method eq(String, Object0 is not applicable for the arguments (String)
【参考方案1】:
此查询来自您的 Spring 安全配置,请检查 security-context.xml,您可以找到使用 authority-by-username-query as 的 Spring 安全身份验证提供程序
select username, authority from users where binary username = ?
此查询使用 MySQL 特定的函数 BINARY 进行区分大小写的比较 (http://gilfster.blogspot.com/2005/08/case-sensitivity-in-mysql.html)。另一方面,H2 默认区分大小写。
尝试改变它
select username, authority from users where username = ?
这同样适用于 users-by-username-query 属性。
【讨论】:
以上是关于将 Hibernate HQL 应用于 H2 时遇到困难的主要内容,如果未能解决你的问题,请参考以下文章