【问题标题】:@NamedQuery adding CROSS JOIN syntax to SQL and its failing in MySQL@NamedQuery 向 SQL 添加 CROSS JOIN 语法及其在 MySQL 中的失败
【发布时间】:2015-03-23 04:31:59
【问题描述】:

我正在尝试在 Spring JPA 中设置 NamedEntity Graph。在我尝试加入第二个实体之前,它一直有效。由于 MySQL 语法异常,它现在失败了。

输出到 Hibernate 的查询包含 CROSS JOIN 语法。为简洁起见,输出中的连接如下所示:

FROM layouts layout0_
LEFT OUTER JOIN layouts_layout_positions layoutposi1_ ON layout0_.id=layoutposi1_.layouts_id
LEFT OUTER JOIN layout_positions layoutposi2_ ON layoutposi1_.layoutPositions_id=layoutposi2_.id
LEFT OUTER JOIN layout_widgets layoutwidg3_ ON layoutposi2_.defaultWidget_id=layoutwidg3_.id
CROSS JOIN
LEFT OUTER JOIN system_users systemuser4_ ON layout0_.lastUpdateUser_id=systemuser4_.id
WHERE layout0_.id=?

我已直接在终端上将其隔离,如果我删除该 CROSS JOIN 语句,则查询通过。

查询提示:

@NamedEntityGraph(
    name = "graph.layouts.and.positions",
    attributeNodes = {
            @NamedAttributeNode(value = "layoutPositions", subgraph="layoutPositions"),
            @NamedAttributeNode(value="lastUpdateUser")
    },
    subgraphs =
            @NamedSubgraph(name = "layoutPositions", attributeNodes = @NamedAttributeNode("defaultWidget")))

还有我的 JPA 属性,我在 Spring Data/JPA 上使用 Hibernate 4:

HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
factory.setDataSource(dataSource());
factory.setJpaVendorAdapter(vendorAdapter);
factory.setPackagesToScan("com.ideafactory.mvc");


Properties jpaProperties = new Properties();
jpaProperties.put("hibernate.dialect", "org.hibernate.dialect.MySQLDialect");
jpaProperties.put("hibernate.hbm2ddl.auto","update");
jpaProperties.put("hibernate.show_sql", true);
jpaProperties.put("hibernat.format_sql", true);
jpaProperties.put("jadira.usertype.autoRegisterUserTypes", true);

可能有方言设置或我缺少的东西吗?


我也只是尝试删除实体图中的子图,它会生成正确的 SQL。我怀疑这是一个 Hibernate 错误....

============================= 在这里编辑============== 这个问题确实很奇怪。它只出现在lastUpdatedUser 字段上。在同一个基类中,我有createdUser,它与 SystemUser 表具有相同的一对一关系。如果我将命名属性节点更改为createdUser,则查询工作正常......我将在此处发布基类,因为我显然缺少lastUpdatedUser 字段的内容,也许其他人可以看到什么问题是什么?

package com.ideafactory.mvc.systemusers.common.utils;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.ideafactory.mvc.general.forms.DateConstants;
import com.ideafactory.mvc.systemusers.common.model.SystemUser;
import org.hibernate.annotations.Type;
import org.joda.time.DateTime;
import org.springframework.data.domain.Auditable;
import org.springframework.data.jpa.domain.AbstractPersistable;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import javax.persistence.*;

/**
 * This is a new base class for auditing entities.
 */
@MappedSuperclass
@SuppressWarnings("serial")
@EntityListeners({AuditingEntityListener.class})
public class AbstractAuditableEntity extends AbstractPersistable<Long> implements Auditable<SystemUser, Long> {

    @Column(length = 30)
    private String externalIdentifier;

    @Basic
    @Type(type = "org.jadira.usertype.dateandtime.joda.PersistentDateTime")
    @org.springframework.format.annotation.DateTimeFormat(pattern = DateConstants.DEFAULT_TIME_FORMAT)
    private DateTime lastUpdated;

    @Basic
    @Type(type = "org.jadira.usertype.dateandtime.joda.PersistentDateTime")
    @org.springframework.format.annotation.DateTimeFormat(pattern = DateConstants.DEFAULT_TIME_FORMAT)
    private DateTime created;

    @OneToOne(fetch = FetchType.LAZY)
    private SystemUser lastUpdateUser;

    @OneToOne(fetch = FetchType.LAZY)
    private SystemUser createUser;

    /**
     * Gets created by audit user.
     */
    @Override
    public SystemUser getCreatedBy() {
        return createUser;
    }

    /**
     * Sets created by audit user.
     */
    @Override

    public void setCreatedBy(SystemUser createdBy) {
        this.createUser = createdBy;
    }

    /**
     * Gets create audit date.
     */
    public DateTime getCreated() {
        return created;
    }

    /**
     * Sets create audit date.
     */
    public void setCreated(DateTime creationDate) {
        this.created = creationDate;
    }

    /**
     * Gets last modified by audit user.
     */
    public SystemUser getLastUpdateUser() {
        return lastUpdateUser;
    }

    /**
     * Sets last modified by audit user.
     */
    public void setLastUpdateUser(SystemUser lastUpdateUser) {
        this.lastUpdateUser = lastUpdateUser;
    }


    public SystemUser getCreateUser() {
        return createUser;
    }

    public void setCreateUser(SystemUser createUser) {
        this.createUser = createUser;
    }

    /**
     * Gets last modified audit date.
     */
    public DateTime getLastUpdated() {
        return lastUpdated;
    }

    /**
     * Sets last modified audit date.
     */
    public void setLastUpdated(DateTime lastModifiedDate) {
        this.lastUpdated = lastModifiedDate;
    }

    @Override
    public DateTime getCreatedDate() {
        return lastUpdated;
    }

    @Override
    public void setCreatedDate(DateTime dateTime) {
        setCreated(dateTime);

    }

    @Override
    public SystemUser getLastModifiedBy() {
        return lastUpdateUser;
    }

    @Override
    public void setLastModifiedBy(SystemUser systemUser) {
        lastUpdateUser = systemUser;

    }

    @Override
    public DateTime getLastModifiedDate() {
        return lastUpdated;
    }

    @Override
    public void setLastModifiedDate(DateTime dateTime) {
        lastUpdated = dateTime;

    }

    @JsonIgnore
    @Override
    public boolean isNew(){
        return super.isNew();
    }

    public String getExternalIdentifier() {
        return externalIdentifier;
    }

    public void setExternalIdentifier(String externalIdentifier) {
        this.externalIdentifier = externalIdentifier;
    }

    public void setId(Long id)
    {
        super.setId(id);
    }

    public Long getId()
    {
        return super.getId();
    }
}

【问题讨论】:

    标签: hibernate spring-mvc jpa spring-data


    【解决方案1】:

    这看起来像下面的休眠错误(仍然打开):

    https://hibernate.atlassian.net/browse/HHH-9392

    【讨论】:

    • 看起来确实像,在原始查询中没有,但在底部的 cmets 中它提到了交叉连接。奇怪的是他们不会关闭这个,我的意思是我真的不需要做任何复杂的事情来解决这个问题......
    【解决方案2】:

    我也遇到过这个问题。也许这是 Hibernate 4.x 中的一个错误(或不受支持的功能)。就我而言,我通过将https://github.com/hibernate/hibernate-orm/blob/4.3/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/SqlGenerator.java#L390 更改为:

    if (right.isEntity() && (right.getType() != SqlTokenTypes.JOIN_FRAGMENT)) {
       writeCrossJoinSeparator();
    }
    

    【讨论】:

    • 谢谢,但我认为我无法更改核心休眠代码。我再次使用实体图来解决这个问题。我想我只是要宣布它失败了,然后切换到 Fetch Joins 这似乎正在做我需要的事情......
    猜你喜欢
    • 1970-01-01
    • 2013-07-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-03
    • 1970-01-01
    • 2010-12-09
    • 1970-01-01
    相关资源
    最近更新 更多