Hibernate通过join生成奇怪的表名

时间:2014-08-13 00:20:23

标签: hibernate jpa

我正在尝试删除我的webapp上的一些数据,我有一个名为 post_it 的表和另一个名为 check_list 的表。问题是,hibernate生成一个组合两个名称的查询,例如,它们只有一个ManyToOne关系:

    Hibernate: 
        delete 
        from
            post_it_check_list 
        where
            (
                post_it_id
            ) in (
                select
                    id 
                from
                    post_it 
                where
                    id=?
            )

然后抛出一个SQLException ... Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'pinleaf.post_it_check_list' doesn't exist

我正在使用Spring-Data JPA,所以我的查询是:

 @Query(value = "delete from PostIt as p where p.id=:postItId")

这些是涉及的映射实体:

@Entity
@Table(name = "check_list")
public class CheckList extends BaseEntity {

    private PostIt postIt;

    @ManyToOne(cascade = {CascadeType.MERGE, CascadeType.REMOVE})
    @JoinColumn(name = "post_it", referencedColumnName = "id", nullable = true)
    public PostIt getPostIt() {
        return postIt;
    }

    public void setPostIt(PostIt postIt) {
        this.postIt = postIt;
    }
}

@Entity
@Table(name = "post_it")
public class PostIt extends BaseEntity {

    private String title;

    private String content;

    private Timestamp createdAt;

    private Timestamp dueDate;

    private Integer urgency;

    private boolean archived;

    private Board board;

    private Collection<CheckList> checkLists;

    private Collection<Tag> tags;

    @Column(name = "title")
    public String getTitle() {
        return title;
    }


    public void setTitle(String title) {
        this.title = title;
    }

    @Column(name = "content")
    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
    @Column(name = "created_at")
    public Timestamp getCreatedAt() {
        return createdAt;
    }

    public void setCreatedAt(Timestamp createdAt) {
        this.createdAt = now(createdAt);
    }

    private Timestamp now(Timestamp incommingTimestamp) {
        return incommingTimestamp == null ? Timestamp.valueOf(java.time.LocalDateTime.now()) : incommingTimestamp;
    }

    @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
    @Column(name = "due_date")
    public Timestamp getDueDate() {
        return dueDate;
    }

    public void setDueDate(Timestamp dueDate) {
        this.dueDate = dueDate;
    }

    @Column(name = "urgency")
    public Integer getUrgency() {
        return urgency;
    }

    public void setUrgency(Integer urgency) {
        this.urgency = urgency;
    }

    @Column(name = "archived")
    public boolean isArchived() {
        return archived;
    }

    public void setArchived(boolean archived) {
        this.archived = archived;
    }

    @ManyToOne(cascade = {CascadeType.MERGE, CascadeType.REMOVE})
    @JoinColumn(name = "board", referencedColumnName = "id", nullable = false)
    public Board getBoard() {
        return board;
    }

    public void setBoard(Board board) {
        this.board = board;
    }

    @OneToMany(cascade = {CascadeType.MERGE, CascadeType.REMOVE})
    public Collection<CheckList> getCheckLists() {
        return checkLists;
    }

    public void setCheckLists(Collection<CheckList> checkLists) {
        this.checkLists = checkLists;
    }

    @ManyToMany
    @LazyCollection(LazyCollectionOption.FALSE)
    @JoinTable(name = "post_it_tags",
            joinColumns = @JoinColumn(name = "post_it", nullable = true),
            inverseJoinColumns = @JoinColumn(name = "tag", nullable = true))
    public Collection<Tag> getTags() {
        return tags;
    }

    public void setTags(Collection<Tag> tags) {
        this.tags = tags;
    }
}

1 个答案:

答案 0 :(得分:0)

两个实体之间有两种不同的单向关联。一个是从CheckList到PostIt的ManyToOne:

@ManyToOne(cascade = {CascadeType.MERGE, CascadeType.REMOVE})
@JoinColumn(name = "post_it", referencedColumnName = "id", nullable = true)
public PostIt getPostIt() {
    return postIt;
}

,第二个是从PostIt到CheckList的OneToMany,与第一个没关系:

@OneToMany(cascade = {CascadeType.MERGE, CascadeType.REMOVE})
public Collection<CheckList> getCheckLists() {
    return checkLists;
}

由于您没有指定如何映射此单向OneToMany,因此Hibernate采用默认设置,即在两个表之间使用连接表。

如果您打算使用单个双向关联,则必须使用mappedBy属性将第二个关联标记为第一个关联:

@OneToMany(mappedBy = "postIt", cascade = {CascadeType.MERGE, CascadeType.REMOVE})
public Collection<CheckList> getCheckLists() {
    return checkLists;
}

请注意,使用此删除查询会让您的生活变得困难。你可以简单地使用

em.remove(em.getReference(PostIt.class, id));