【问题标题】:How to use inner join statement with Hibernate如何在 Hibernate 中使用内部连接语句
【发布时间】:2013-11-30 12:36:47
【问题描述】:

我在 MySQL 数据库中有两个表: 1. 带有一些设备特定值的设备表。 2.只有id值和name值的vendor表

现在,我想从设备表中获取两个值,型号名称和 vendor_id。但是为了显示 vendor_id 我想显示相应的供应商名称。 因此,在 MySQL Workbench 中,此语句运行良好,并向我显示了预期的结果,例如 Model = N95 和 Vendor = Nokia

SELECT device.model, vendor.vendor from device inner join vendor on device.vendor_id = vendor.id

现在我使用 Hibernate 从表中获取值。

public List<Device> listDevices() {
    session = HibernateUtil.getSessionFactory().openSession();
    Transaction tx = null;
    try{
        tx = session.beginTransaction();
        String sql = "SELECT device.model, vendor.vendor from device inner join vendor on device.vendor_id = vendor.id";
        SQLQuery query = session.createSQLQuery(sql);
        query.addEntity(Device.class);
        List list = query.list();
        allDevices = new ArrayList();
        for (Iterator iterator = list.iterator(); iterator.hasNext();) {
            device = (Device) iterator.next();
            allDevices.add(device);
        }
        tx.commit();
    } catch (HibernateException e) {
        if(tx!=null) tx.rollback();
            e.printStackTrace();
    } finally {
        session.close();
        return allDevices;
    }
}

但这不起作用我遇到了这个异常:

SEVERE:   Column 'id' not found.
SEVERE:   org.hibernate.exception.SQLGrammarException: could not execute query
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:67)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
at org.hibernate.loader.Loader.doList(Loader.java:2223)
at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2104)
at org.hibernate.loader.Loader.list(Loader.java:2099)
at org.hibernate.loader.custom.CustomLoader.list(CustomLoader.java:289)
at org.hibernate.impl.SessionImpl.listCustomQuery(SessionImpl.java:1695)
at org.hibernate.impl.AbstractSessionImpl.list(AbstractSessionImpl.java:142)
at org.hibernate.impl.SQLQueryImpl.list(SQLQueryImpl.java:152)
at com.vodafone.omisuite.model.DeviceData.listDevices(DeviceData.java:154)
at com.vodafone.omisuite.model.DeviceData.<init>(DeviceData.java:50)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
at java.lang.Class.newInstance(Class.java:374)
at com.sun.faces.mgbean.BeanBuilder.newBeanInstance(BeanBuilder.java:186)
at com.sun.faces.mgbean.BeanBuilder.build(BeanBuilder.java:100)
at com.sun.faces.mgbean.BeanManager.createAndPush(BeanManager.java:409)
at com.sun.faces.mgbean.BeanManager.create(BeanManager.java:269)
at com.sun.faces.el.ManagedBeanELResolver.resolveBean(ManagedBeanELResolver.java:244)
at com.sun.faces.el.ManagedBeanELResolver.getValue(ManagedBeanELResolver.java:116)
at com.sun.faces.el.DemuxCompositeELResolver._getValue(DemuxCompositeELResolver.java:176)
at com.sun.faces.el.DemuxCompositeELResolver.getValue(DemuxCompositeELResolver.java:203)
at com.sun.el.parser.AstIdentifier.getValue(AstIdentifier.java:116)
at com.sun.el.parser.AstValue.getBase(AstValue.java:151)
at com.sun.el.parser.AstValue.getValue(AstValue.java:200)
at com.sun.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:226)
at org.jboss.weld.el.WeldValueExpression.getValue(WeldValueExpression.java:50)
at com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:109)
at javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:194)
at javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:182)
at javax.faces.component.UIData.getValue(UIData.java:732)
at javax.faces.component.UIData.getDataModel(UIData.java:1811)
at javax.faces.component.UIData.setRowIndexWithoutRowStatePreserved(UIData.java:484)
at javax.faces.component.UIData.setRowIndex(UIData.java:473)
at com.sun.faces.renderkit.html_basic.TableRenderer.encodeBegin(TableRenderer.java:82)
at javax.faces.component.UIComponentBase.encodeBegin(UIComponentBase.java:869)
at javax.faces.component.UIData.encodeBegin(UIData.java:1133)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1854)
at javax.faces.render.Renderer.encodeChildren(Renderer.java:176)
at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:894)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1856)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1859)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1859)
at com.sun.faces.application.view.FaceletViewHandlingStrategy.renderView(FaceletViewHandlingStrategy.java:443)
at com.sun.faces.application.view.MultiViewHandler.renderView(MultiViewHandler.java:131)
at javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:337)
at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:120)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:219)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:647)
at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1682)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:318)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:160)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:734)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:673)
at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:99)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:174)
at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:357)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:260)
at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:188)
at org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:191)
at org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:168)
at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:189)
at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:288)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:206)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:136)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:114)
at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:838)
at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:113)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:115)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:55)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:135)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:564)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:544)
at java.lang.Thread.run(Thread.java:724)
Caused by: java.sql.SQLException: Column 'id' not found.
  at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1074)
 at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:988)
 at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:974)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:919)
at com.mysql.jdbc.ResultSetImpl.findColumn(ResultSetImpl.java:1167)
at com.mysql.jdbc.ResultSetImpl.getInt(ResultSetImpl.java:2851)
at org.hibernate.type.IntegerType.get(IntegerType.java:28)
at org.hibernate.type.NullableType.nullSafeGet(NullableType.java:163)
at org.hibernate.type.NullableType.nullSafeGet(NullableType.java:154)
at org.hibernate.loader.Loader.getKeyFromResultSet(Loader.java:1097)
at org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:565)
at org.hibernate.loader.Loader.doQuery(Loader.java:701)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:236)
at org.hibernate.loader.Loader.doList(Loader.java:2220)
... 76 more

如果我使用以下语句而不是它的工作,但它显示了 vendor_id 的 ID 值而不是相应的名称。

SELECT * from device inner join vendor on device.vendor_id = vendor.id

对于这两个表,我创建了 java 类和两个 *.hbm.xml 文件。在 hibernate.cfg.xml 文件中配置了两个映射。

谁能帮助并解释我做错了什么以及如何解决这个问题? 如果您对如何创建相应的 HQL 语句有任何建议,请随时发布 ;-)

这是通过 Hibernate 创建的设备类!

/**
* Device generated by hbm2java
*/
@Entity
@Table(name="device"
,catalog="myDB"
)
public class Device  implements java.io.Serializable {

private Integer id;
private String version;
private String shortname;
private int vendorId;
private String model;
private String platform;
private String appIconSize;
private String description;
private String uaProfile;
private byte[] image;
private String imageMimetype;
private int internetonly;
private int creator;
private int approvable;
private int approved;
private Date changed;

public Device() {
}


public Device(String shortname, int vendorId, String model, String platform, int  internetonly, int creator, int approvable, int approved, Date changed) {
    this.shortname = shortname;
    this.vendorId = vendorId;
    this.model = model;
    this.platform = platform;
    this.internetonly = internetonly;
    this.creator = creator;
    this.approvable = approvable;
    this.approved = approved;
    this.changed = changed;
}
public Device(String shortname, int vendorId, String model, String platform, String    appIconSize, String description, String uaProfile, byte[] image, String imageMimetype,  int  internetonly, int creator, int approvable, int approved, Date changed) {
   this.shortname = shortname;
   this.vendorId = vendorId;
   this.model = model;
   this.platform = platform;
   this.appIconSize = appIconSize;
   this.description = description;
   this.uaProfile = uaProfile;
   this.image = image;
   this.imageMimetype = imageMimetype;
   this.internetonly = internetonly;
   this.creator = creator;
   this.approvable = approvable;
   this.approved = approved;
   this.changed = changed;
}

 @Id @GeneratedValue(strategy=IDENTITY)

@Column(name="id", unique=true, nullable=false)
public Integer getId() {
    return this.id;
}

public void setId(Integer id) {
    this.id = id;
}

@Column(name="version")
public String getVersion() {
    return this.version;
}

public void setVersion(String version) {
    this.version = version;
}

@Column(name="shortname", nullable=false)
public String getShortname() {
    return this.shortname;
}

public void setShortname(String shortname) {
    this.shortname = shortname;
}

@Column(name="vendor_id", nullable=false)
public int getVendorId() {
    return this.vendorId;
}

public void setVendorId(int vendorId) {
    this.vendorId = vendorId;
}

@Column(name="model", nullable=false)
public String getModel() {
    return this.model;
}

public void setModel(String model) {
    this.model = model;
}

@Column(name="platform", nullable=false, length=7)
public String getPlatform() {
    return this.platform;
}

public void setPlatform(String platform) {
    this.platform = platform;
}

@Column(name="app_icon_size", length=10)
public String getAppIconSize() {
    return this.appIconSize;
}

public void setAppIconSize(String appIconSize) {
    this.appIconSize = appIconSize;
}

@Column(name="description")
public String getDescription() {
    return this.description;
}

public void setDescription(String description) {
    this.description = description;
}

@Column(name="ua_profile")
public String getUaProfile() {
    return this.uaProfile;
}

public void setUaProfile(String uaProfile) {
    this.uaProfile = uaProfile;
}

@Column(name="image")
public byte[] getImage() {
    return this.image;
}

public void setImage(byte[] image) {
    this.image = image;
}

@Column(name="image_mimetype", length=16)
public String getImageMimetype() {
    return this.imageMimetype;
}

public void setImageMimetype(String imageMimetype) {
    this.imageMimetype = imageMimetype;
}

@Column(name="internetonly", nullable=false)
public int getInternetonly() {
    return this.internetonly;
}

public void setInternetonly(int internetonly) {
    this.internetonly = internetonly;
}

@Column(name="creator", nullable=false)
public int getCreator() {
    return this.creator;
}

public void setCreator(int creator) {
    this.creator = creator;
}

@Column(name="approvable", nullable=false)
public int getApprovable() {
    return this.approvable;
}

public void setApprovable(int approvable) {
    this.approvable = approvable;
}

@Column(name="approved", nullable=false)
public int getApproved() {
    return this.approved;
}

public void setApproved(int approved) {
    this.approved = approved;
}
@Temporal(TemporalType.TIMESTAMP)
@Column(name="changed", nullable=false, length=19)
public Date getChanged() {
    return this.changed;
}

public void setChanged(Date changed) {
    this.changed = changed;
}

}

【问题讨论】:

  • 你是我们sing hibernate,使用HQL。这将非常简单。 H 文档在这些方面做得很好。

标签: java mysql sql hibernate


【解决方案1】:

最简单的解决方案就是返回设备列表。这不是普通的 SQL,在这里您使用关联。默认情况下,多对一关联(您的情况)是渴望的,您无需额外努力即可获得它,即 device.getVendor().getVendor()。

如果你只想返回 2 个字符串,你可以返回 map:

select new map (device.model as model, vendor.vendor as vendor) from Model model, Vendor vendor where device.vendor = vendor

编辑:

您还必须创建关联。为此删除 vendorId 属性并更改您的代码,如下所示:

public class Device implements java.io.Serializable {
    ...
    private Vendor vendor;
    ...

    @ManyToOne
    @JoinColumn(name="vendor_id", nullable=false)
    public int getVendorId() {
        return this.vendorId;
    }
}

如果它解决了您的问题,请告诉我。

【讨论】:

  • 我用您发布的语句进行了尝试,但在 MySQL Workbench 中出现错误,表明 SQL 语法有错误。 GlassFish 输出中的相同消息 原因:com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException:您的 SQL 语法有错误;
  • MySQL Workbench 中的确切错误是:错误代码:1064。您的 SQL 语法有错误;检查与您的 MySQL 服务器版本相对应的手册,以在第 1 行的“(device.model as model, vendor.vendor as vendor) from Model model, Vendor vendor”附近使用正确的语法
  • 我正在使用 MySQL Workbench 6.0 和 MySQL Community Edition 5.6.13.1
  • 我明白了。这是 HQL 语句,不是 SQL。
  • 如果我执行您在 NetBeans 中提供的 HQL 语句。在 hibernate.cfg.xml 右键单击​​和“运行 HQL 查询”然后我得到这个异常:org.hibernate.hql.ast.QuerySyntaxException:模型未映射[选择新地图(device.model 作为模型,vendor.vendor 作为供应商) 来自模型模型,com.vodafone.omisuite.bean.Vendor vendor where device.vendor = vendor] 我无法将完整的堆栈跟踪复制到评论部分,因为它太长了。
【解决方案2】:

您正在尝试检索 Device 类型的实体,虽然您没有提到它,但我猜 Device 是一个持久类,它有一个名为 id 的列,它被注释为休眠@Id。因此,我猜 hibernate 会尝试创建新的 Device 对象,但它迫切需要 Device id,因为它是主键,但在选择列表中找不到它。但这不是您真正想要的,您想要的只是设备型号和供应商,而不是 Device 对象!

要解决您的问题,您必须:

  1. 删除 query.addEntity(Device.class);
  2. 使用称为构造函数的查询,例如 select new YourSimplePOJO(device.model, vendor.vendor) 当然你的 POJO 类 YourSimplePOJO 应该有一个有两个参数的构造函数。

【讨论】:

  • 是的,设备类在 Device.hbm.xml 文件中映射到设备表。设备类具有设备表中的所有属性,id 为 PK。
猜你喜欢
  • 2016-10-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-10
  • 1970-01-01
  • 2017-11-03
  • 2011-04-01
  • 1970-01-01
相关资源
最近更新 更多