简体   繁体   中英

Hibernate ERROR: Unknown column in delete query (mapping many2many via embedded)

I have 2 entities (User and Group) in a many-to-many relantionship. Therefore, I created the table IsIn, which is composed by userId, groupId (composed primary key) and 2 extra fields (typeId and isBlocked). I followed Vlad Mihalcea's tutorial on how to map the entities in such a situation -> see here

However, when I try to delete a user or a group, it doesn't work. I get the following error:

ERROR: Unknown column 'groups0_.user_userId' in 'field list'

javax.persistence.PersistenceException: org.hibernate.exception.SQLGrammarException: could not extract ResultSet

I will post below my classes.

UserGroupId (Embedded)

package Embedded;

import javax.persistence.Column;
import javax.persistence.Embeddable;
import java.io.Serializable;
import java.util.Objects;

@Embeddable
public class UserGroupId implements Serializable {

    @Column(name = "userId")
    private int userId;

    @Column(name = "groupId")
    private int groupId;

    public UserGroupId() {}

    public UserGroupId(int userId, int groupId) {
        this.userId = userId;
        this.groupId = groupId;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;

        if (o == null || getClass() != o.getClass())
            return false;

        UserGroupId that = (UserGroupId) o;
        return Objects.equals(userId, that.userId) &&
                Objects.equals(groupId, that.groupId);
    }

    @Override
    public int hashCode() {
        return Objects.hash(userId, groupId);
    }
}

IsIn

package entity;

import Embedded.UserGroupId;

import javax.persistence.*;
import java.util.Objects;

@Entity
@Table(name = "isin")
public class IsIn {

    @EmbeddedId
    private UserGroupId id;

    @ManyToOne(fetch = FetchType.LAZY)
    @MapsId("userId")
    private User user;

    @ManyToOne(fetch = FetchType.LAZY)
    @MapsId("groupId")
    private Group group;

    @OneToOne
    @JoinColumn(name = "typeId")
    private UserType typeId;

    @Column(name = "isBlocked", nullable = false)
    private boolean isBlocked;

    public IsIn() {}

    public IsIn(User user, Group group) {
        this.user = user;
        this.group = group;
        this.id = new UserGroupId(user.getUserId(), group.getGroupId());
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;

        if (o == null || getClass() != o.getClass())
            return false;

        IsIn that = (IsIn) o;
        return Objects.equals(user, that.user) &&
                Objects.equals(group, that.group);
    }

    @Override
    public int hashCode() {
        return Objects.hash(user, group);
    }

    public User getUser() {
        return user;
    }

    public Group getGroup() {
        return group;
    }

    public void setUser(User user) {
        this.user = user;
    }

    public void setGroup(Group group) {
        this.group = group;
    }

    public UserType getTypeId() {
        return typeId;
    }

    public void setTypeId(UserType typeId) {
        this.typeId = typeId;
    }

    public boolean isBlocked() {
        return isBlocked;
    }

    public void setBlocked(boolean blocked) {
        isBlocked = blocked;
    }
}

User

package entity;

import javax.persistence.*;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

@Entity
@Table(name = "`user`")
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "userId" ,unique = true, nullable = false)
    private int userId;

    @OneToMany(
            mappedBy = "user",
            cascade={CascadeType.ALL},
            orphanRemoval = true
    )
    private List<IsIn> groups = new ArrayList<>();

    @Column(name = "customerName", nullable = false)
    private String customerName;

    @Column(name = "password", nullable = false)
    private String password;

    @Column(name = "email", nullable = false, unique = true)
    private String email;

    @Column(name = "is_active", nullable = false)
    private boolean is_active;

    @Column(name = "notificationType", nullable = false)
    private String notificationType;

    @Column(name = "create_date", nullable = false)
    private String create_date;

    public User() { }

    public User(String customerName, String password, String email, boolean is_active, String notificationType, String create_date) {
        this.customerName = customerName;
        this.password = password;
        this.email = email;
        this.is_active = is_active;
        this.notificationType = notificationType;
        this.create_date = create_date;
    }

    public void addGroup(Group group) {
        IsIn isIn = new IsIn(this, group);
        groups.add(isIn);
    }

    public void removeGroup(Group group) {
        for (Iterator<IsIn> iterator = groups.iterator();
             iterator.hasNext(); ) {
            IsIn isIn = iterator.next();

            if (isIn.getUser().equals(this) &&
                    isIn.getGroup().equals(group)) {
                iterator.remove();
                isIn.setUser(null);
                isIn.setGroup(null);
            }
        }
    }

    public int getUserId() {
        return userId;
    }

    public void setUserId(int userId) {
        this.userId = userId;
    }

    public String getCustomerName() {
        return customerName;
    }

    public void setCustomerName(String customerName) {
        this.customerName = customerName;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getEmail() {
        return email;
    }

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

    public boolean isIs_active() {
        return is_active;
    }

    public void setIs_active(boolean is_active) {
        this.is_active = is_active;
    }

    public String getNotificationType() {
        return notificationType;
    }

    public void setNotificationType(String notificationType) {
        this.notificationType = notificationType;
    }

    public String getCreate_date() {
        return create_date;
    }

    public void setCreate_date(String create_date) {
        this.create_date = create_date;
    }
}

Group

package entity;

import org.hibernate.annotations.NaturalIdCache;
import javax.persistence.*;
import java.util.Objects;

@Entity
@Table(name = "`group`")
@NaturalIdCache
public class Group {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "groupId")
    private int groupId;

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

    @Column(name = "create_date", nullable = false)
    private String create_date;

    @OneToOne(fetch=FetchType.EAGER, cascade=CascadeType.ALL, orphanRemoval=true)
    @JoinColumn(name = "created_by", nullable = false)
    private User user;

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

    public Group() { }

    public Group(String groupName, String create_date, User user, boolean isPrivate) {
        this.groupName = groupName;
        this.create_date = create_date;
        this.user = user;
        this.isPrivate = isPrivate;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;

        if (o == null || getClass() != o.getClass())
            return false;

        Group group = (Group) o;
        return Objects.equals(groupId, group.getGroupId());
    }

    @Override
    public int hashCode() { return Objects.hash(groupId); }

    public int getGroupId() {
        return groupId;
    }

    public void setGroupId(int groupId) {
        this.groupId = groupId;
    }

    public String getGroupName() {
        return groupName;
    }

    public void setGroupName(String groupName) {
        this.groupName = groupName;
    }

    public String getCreate_date() {
        return create_date;
    }

    public void setCreate_date(String create_date) {
        this.create_date = create_date;
    }

    public boolean isPrivate() {
        return isPrivate;
    }

    public void setPrivate(boolean aPrivate) {
        isPrivate = aPrivate;
    }

    public User getCreated_by() {
        return user;
    }

    public void setCreated_by(User user) {
        this.user = user;
    }

}

And here is my delete method (which works for other entities, except for User and Group).

public static void deleteUserById(int userId) {
        Session session = sessionFactory.openSession();

        try{
            session.beginTransaction();
            User u = UserDAO.getUserById(userId);
            session.delete(u);
            session.flush();
            session.getTransaction().commit();
        } catch (HibernateException he) {
            he.printStackTrace();
        }
        finally {
            session.close();
        }
    }

Any kind of help is highly appreciated, thank you for your time.

Table DDLs

CREATE TABLE IF NOT EXISTS `chatapp`.`user` (
 `userId` INT NOT NULL UNIQUE AUTO_INCREMENT,
 `customerName` VARCHAR(50) NOT NULL,
 `password` VARCHAR(50) NOT NULL,
 `email` VARCHAR(255) NOT NULL unique,
 `is_active` boolean NOT NULL,
 `notificationType` VARCHAR(50) NOT NULL,
 `create_date` VARCHAR(50) NOT NULL,
 PRIMARY KEY (`userId`),
 INDEX `userId_idx` (`userId` ASC)
 );

CREATE TABLE IF NOT EXISTS `chatapp`.`group` (
 `groupId` INT NOT NULL UNIQUE AUTO_INCREMENT,
 `groupName` VARCHAR(255) NULL,
 `create_date` VARCHAR(50) NOT NULL,
 `created_by` INT NOT NULL,
 `isPrivate` boolean NOT NULL,
 PRIMARY KEY (`groupId`),
 INDEX `groupId_idx` (`groupId` ASC),
 FOREIGN KEY (`created_by`) REFERENCES `user` (`userId`)
 );

 CREATE TABLE IF NOT EXISTS `chatapp`.`isin` (
 `userId` INT NOT NULL,
 `groupId` INT NOT NULL,
 `typeId` INT NOT NULL,
 `isBlocked` boolean NOT NULL,
 PRIMARY KEY (`userId`,`groupId`),
 FOREIGN KEY (`userId`)  REFERENCES `user` (`userId`),
 FOREIGN KEY (`groupId`) REFERENCES `group` (`groupId`),
 FOREIGN KEY (`typeId`)  REFERENCES `usertype` (`typeId`)
);

Full StackTrace here

Complete Database design here

The @JoinColumn annotations are missing in the IsIn class.

It should look like

@Entity
@Table(name = "isin")
public class IsIn {

    @EmbeddedId
    private UserGroupId id;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn("userId")
    private User user;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn("groupId")
    private Group group;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM