为什么Hibernate会在字段名称中添加太多反引号来破坏查询?

时间:2017-03-28 00:49:17

标签: spring hibernate

我正在使用一个使用hibernate作为JPA提供程序的spring-boot应用程序。我在使用内存H2数据库测试它时没有遇到任何问题,但是当我尝试使用生产mysql服务器时,我不得不将spring.jpa.properties.hibernate.globally_quoted_identifiers=true添加到a​​pplication.properties,因为其中一个表名是一个保留关键字MySQL的。 但是,它的hibernate现在会在标识符中间添加额外的反引号,导致mysql拒绝查询格式错误。这是一个查询:

select scorecard0_.`id` as id1_10_3_, scorecard0_.`default_role_`id`` as default_2_10_3_, scorecard0_.`game_`id`` as game_3_10_3_, robotrole1_.`id` as id1_8_0_, robotrole1_.`description` as descript2_8_0_, robotrole1_.`name` as name3_8_0_, robotrole1_.`scorecard_`id`` as scorecar4_8_0_, scorecard2_.`id` as id1_10_1_, scorecard2_.`default_role_`id`` as default_2_10_1_, scorecard2_.`game_`id`` as game_3_10_1_, game3_.`id` as id1_3_2_, game3_.`name` as name2_3_2_, game3_.`type` as type3_3_2_, game3_.`year` as year4_3_2_ from `scorecard` scorecard0_ left outer join `robot_role` robotrole1_ on scorecard0_.`default_role_`id``=robotrole1_.`id` left outer join `scorecard` scorecard2_ on robotrole1_.`scorecard_`id``=scorecard2_.`id` inner join `game` game3_ on scorecard0_.`game_`id``=game3_.`id` where scorecard0_.`game_`id``=?

你可能不需要re the整个事情,但有几个scorecard0_.`default_role_`id``和类似的实例,其中id中的default_role_id被引用了一段额外的时间。有没有办法解决这个问题?或者我是否需要提交错误报告并等待?

以下是查询中某些实体的类:

@Entity
public class Scorecard implements Identifiable<Long> {
    @Id
    @GeneratedValue
    private long id;

    @OneToOne(optional = false)
    private Game game;

    @OneToMany(cascade = CascadeType.PERSIST,mappedBy = "scorecard")
    @NotEmpty(groups = {Default.class,Creating.class})
    private Set<ScorecardSection> sections = new HashSet<>();

    @OneToMany(mappedBy = "scorecard")
    private Set<Result> results = new HashSet<>();

    @OneToMany(cascade = CascadeType.PERSIST,mappedBy = "scorecard")
    private Set<RobotRole> robotRoles = new HashSet<>();

    @OneToOne(cascade = CascadeType.PERSIST)
    private RobotRole defaultRole;

    public Scorecard() {
    }

    public Scorecard(long id){
        setId(id);
    }

    public Game getGame() {
        return game;
    }

    public void setGame(Game game) {
        this.game = game;
    }

    public Set<ScorecardSection> getSections() {
        return sections;
    }

    public List<FieldSection> getFields() {
        return sections.stream().filter(section -> section instanceof FieldSection)
                       .map(section -> (FieldSection) section).collect(Collectors.toList());
    }

    @Override
    public Long getId() {
        return id;
    }

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

    public Set<Result> getResults() {
        return results;
    }

    public Set<RobotRole> getRobotRoles() {
        return robotRoles;
    }

    public Set<RobotRole> getRoles() {
        return robotRoles;
    }

    public RobotRole getDefaultRole() {
        return defaultRole;
    }

    public void setDefaultRole(RobotRole defaultRole) {
        this.defaultRole = defaultRole;
    }

    public interface Creating{

    }
}

@Entity
public class RobotRole {
    @Id
    @GeneratedValue
    private long id;
    @ManyToOne
    @JsonIgnore
    private Scorecard scorecard;
    @OneToMany(mappedBy = "robotRole", cascade = CascadeType.ALL)
    private Set<ScoreWeight> weights = new HashSet<>();
    @NotNull
    private String name;
    private String description;

    public RobotRole() {
    }

    public RobotRole(String name){
        setName(name);
    }

    public Scorecard getScorecard() {
        return scorecard;
    }

    public void setScorecard(Scorecard scorecard) {
        this.scorecard = scorecard;
    }

    @AssertTrue
    public boolean weightsMatchScorecard() {
        return weights.stream().map(ScoreWeight::getField)
                      .map(ScorecardSection::getScorecard)
                      .allMatch(scorecard1 -> Objects.equals(scorecard1.getId(), scorecard.getId()));
    }

    public long getId() {
        return id;
    }

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

    public Set<ScoreWeight> getWeights() {
        return weights;
    }

    public String getDescription() {
        return description;
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

注意: Hibernate 应该在启用此选项的情况下执行的操作是转换,例如default_role_id`default_role_id`。发生的事情是`default_role_`id``。注意id周围的额外反推。他们不应该在那里。

2 个答案:

答案 0 :(得分:0)

我认为这正是hibernate.globally_quoted_identifiers = true所做的。

但是,由于你有1个表的问题,你可以使用不同的解决方案,如:

@Entity
@Table(name="\"User\"")
public class User {
    ...
}

这将在保留关键字的表格周围添加反引号。

答案 1 :(得分:0)

这是hibernate中的一个错误,它在我使用的Hibernate版本(5.0.9)之后修复。我将尝试摆弄版本号,以便我可以使用修复此错误的版本,该版本不会与其他依赖项冲突。

编辑:与spring合作的最新版本的hibernate是5.0.12,没有这个bug。我可能会打开一个关于是否/如何在春天使用hibernate 5.1.x或5.2.x的新问题。