Hibernate HQL Join 与复合键

Posted

技术标签:

【中文标题】Hibernate HQL Join 与复合键【英文标题】:Hibernate HQL Join with composite Key 【发布时间】:2014-12-30 23:31:50 【问题描述】:

我在尝试编写 HQL 查询时遇到了一些问题 加入如下定义的两个实体/表

CustomersDAO.java

@Entity
@Table(name="customers")
public class CustomerDAO implements Serializable 

private static final long serialVersionUID = 1L;

@EmbeddedId 
private CustomerNaming name;

@ManyToOne
@Cascade(org.hibernate.annotations.CascadeType.SAVE_UPDATE) 
@JoinColumns( @JoinColumn (name="city"), @JoinColumn(name="state"),@JoinColumn(name="via") )
private Address indirizzo;

@Column (name="email")
private String email;

@Column (name="mailinglist")
private boolean mailinglist;

@Column (name="sex")
private String sex;

public CustomerDAO()

    indirizzo=new Address();
    name=new CustomerNaming();




public CustomerNaming getNome() 
    return name;

public void setNome(CustomerNaming nome) 
    this.name = nome;


public Address getIndirizzo() 
    return indirizzo;

public void setIndirizzo(Address indirizzo) 
    this.indirizzo = indirizzo;

public String getEmail() 
    return email;

public void setEmail(String email) 
    this.email = email;

public boolean isMailinglist() 
    return mailinglist;

public void setMailinglist(boolean mailinglist) 
    this.mailinglist = mailinglist;

public String getSex() 
    return sex;

public void setSex(String sex) 
    this.sex = sex;


@Override
public String toString() 
    return "Customer :  [nome=" + name.getNome()
            + ", cognome=" + name.getCognome() + ", indirizzo=" + indirizzo
            + ", email=" + email + ", mailinglist=" + mailinglist
            + ", sex=" + sex + "]";




客户命名.java

@Embeddable
public class CustomerNaming implements Serializable 

/**
 * 
 */
private static final long serialVersionUID = 1L;

@Column (name="nome")
private String nome;

@Column (name="cognome")
private String cognome;

public String getNome() 
    return nome;

public void setNome(String nome) 
    this.nome = nome;

public String getCognome() 
    return cognome;

public void setCognome(String cognome) 
    this.cognome = cognome;





地址.java

@Entity
@Table(name="indirizzi")
public class Address implements Serializable 
/**
 * 
 */
private static final long serialVersionUID = 1L;

@EmbeddedId
private AddressKey key;

@Column (name="cap")
private String cap;
//private ArrayList<State> state=new ArrayList<State>();

public Address()
    key=new AddressKey();


public AddressKey getKey() 
    return key;


public void setKey(AddressKey key) 
    this.key = key;


public String getCap() 
    return cap;

public void setCap(String cap) 
    this.cap = cap;




AddressKey.java

@Embeddable
public class AddressKey implements Serializable

/**
 * 
 */
private static final long serialVersionUID = 1L;

@Column(name="via", nullable=false)
private String via;
@Column (name="city", nullable=false)
private String city;
@Column (name="state", nullable=false)
private String state;

public String getState() 
    return state;

public void setState(String state) 
    this.state = state;

public String getVia() 
    return via;

public void setVia(String via) 
    this.via = via;

public String getCity() 
    return city;

public void setCity(String city) 
    this.city = city;



如你所见,我有(试试这个……我还在学习休眠……) 在地址中创建复合 PK,由 AddressKey 映射

所以我必须创建一个复合连接来进行搜索,但没有成功

这是我最后一次(不是最好的......哈哈)尝试......

        Query q=s.createQuery("FROM CustomerDAO cust JOIN (cust.indirizzo.key.via   cust.indirizzo.key.city  , cust.indirizzo.key.state) as indirizzo WHERE  cust.name.nome=:nome and cust.name.cognome like :cognome and cust.indirizzo.key.via like :via and cust.indirizzo.key.city like :city and cust.indirizzo.cap like :cap and cust.indirizzo.key.state like :state and cust.sex like :sex and c.email like :mail and cust.mailinglist like :mailinglist")
                .setString("nome","\'%"+c.getNome().getNome()+"%\'")
                .setString("cognome", c.getNome().getCognome())
                .setString("via", c.getIndirizzo().getKey().getVia())
                .setString("city", c.getIndirizzo().getKey().getCity())
                .setString("cap", c.getIndirizzo().getCap())
                .setString("state", c.getIndirizzo().getKey().getState())
                .setString("sex", c.getSex())
                .setString("mail",c.getEmail());
        if(q!=null)
            customers=(List<Object[]>)q.list();

在某些情况下,我从 createQuery 收到了一个空查询...

在这种情况下......它根本无法识别查询

 org.hibernate.hql.ast.QuerySyntaxException: unexpected token: ( near line 1, column 43 [FROM myapp.customer.CustomerDAO cust JOIN (cust.indirizzo.key.via   cust.indirizzo.key.city  , cust.indirizzo.key.state) as indirizzo WHERE  cust.name.nome=:nome and cust.name.cognome like :cognome and cust.indirizzo.key.via like :via and cust.indirizzo.key.city like :city and cust.indirizzo.cap like :cap and cust.indirizzo.key.state like :state and cust.sex like :sex and c.email like :mail and cust.mailinglist like :mailinglist]

请注意,如下所示的更简单的搜索可以完美地工作...

List<CustomerDAO> customers=(List<CustomerDAO>)(s.createQuery("from CustomerDAO where nome=:nome and cognome=:cognome").setString("nome", nome).setString("cognome", cognome)).list();

感谢您的帮助

问候 翁贝托

【问题讨论】:

【参考方案1】:

好的

实际上要简单得多

查询必须没有任何“加入”添加并且有效...

下面的例子

Query q=s.createQuery("FROM CustomerDAO cust WHERE  cust.name.nome like :nome ");

感谢您的帮助!

问候

翁贝托

【讨论】:

以上是关于Hibernate HQL Join 与复合键的主要内容,如果未能解决你的问题,请参考以下文章

HQL Hibernate INNER JOIN

Hibernate 在 JoinTable (List<>) 中声明复合主键

为啥得到 org.hibernate.hql.internal.ast.QuerySyntaxException: Path expected for join!加入 3 个表时

Hibernate 表映射 主键生成策略与复合主键

hibernate 复合主键映射

hibernate hql update操作