Spring-Hibernate Many-to-Many : 保存一个实体,或者创建一个关系(如果它存在于数据库中)
Spring-Hibernate Many-to-Many : Save an entity, or create a relationship if it exists in the database
我是 Spring 和 Hibernate 的新手,运行 遇到了一个我几天都无法解决的问题。
在我的项目中,我在服务器和用户实体之间使用多对多关系。一个用户可以存在于多个服务器上。
我的想法是:
服务器 <-> Server_Users <-> 用户
创建 tables 的代码:
CREATE TABLE public.servers (
id bigint NOT NULL,
s_snowflake bigint NOT NULL,
name character varying(64) NOT NULL
);
CREATE TABLE public.users (
id bigint NOT NULL,
u_snowflake bigint NOT NULL,
name character varying(64) NOT NULL
);
CREATE TABLE public.server_users (
id bigint NOT NULL,
server_id bigint NOT NULL,
user_id bigint NOT NULL
);
这是我的 class 的样子:
@Entity
@Table(name = "servers")
public class Server {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@Column(name = "s_snowflake", unique = true)
private long snowflake;
private String name;
@ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@JoinTable(
name = "server_users",
joinColumns = @JoinColumn(name = "server_id"),
inverseJoinColumns = @JoinColumn(name = "user_id")
)
private Set<User> users = new HashSet<>();
}
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@Column(name = "u_snowflake", unique = true)
private long snowflake;
private String name;
@ManyToMany(mappedBy = "users", targetEntity = Server.class, fetch = FetchType.EAGER)
private Set<Server> servers = new HashSet<>();
}
这在我初始化数据时效果很好。我创建了一个服务器对象并用用户填充它,所有内容都已正确保存。
但是当我尝试保存包含已经在用户 table 中的用户的服务器时,我遇到了问题(如果我从数据库中级联删除服务器,用户不应该被删除)。
有什么方法可以配置 Hibernate 以便在必要时添加新用户,但如果用户存在,则使用 Server_Users table 将其“创建关系”到新服务器?
我试过 Cascade.SAVE_UPDATE 和其他方法,但没有结果。
成瘾:
这是我用来保存和更新的 DAO class 方法:
public abstract class AbstractDAOImpl<T> implements AbstractDAO<T> {
public void save(T entity) {
Session session = HibernateSessionFactoryUtil.getSessionFactory().openSession();
Transaction trx = session.beginTransaction();
session.save(entity);
trx.commit();
session.close();
}
public void update(T entity) {
Session session = HibernateSessionFactoryUtil.getSessionFactory().openSession();
Transaction trx = session.beginTransaction();
session.update(entity);
trx.commit();
session.close();
}
}
服务器添加逻辑。首先,我将它保存到数据库中,然后用用户填充Set并执行update()
如果 table with users 为空,则此方法有效,所有必要的记录和连接都在 Server_Users 和 Users tables:
中创建
public static void addServer(Guild guild) {
Server server = new Server(Long.parseLong(guild.getId()), guild.getName());
serverDAO.save(server);
for (Member m : guild.getMembers()) {
User user = new User(Long.parseLong(m.getId()), m.getUser().getName());
user.addServer(server);
server.addUser(user);
}
serverDAO.update(server);
}
我找到了解决方案
@Cascade({
org.hibernate.annotations.CascadeType.SAVE_UPDATE,
org.hibernate.annotations.CascadeType.MERGE,
org.hibernate.annotations.CascadeType.PERSIST
})
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(
name = "server_users",
joinColumns = @JoinColumn(name = "server_sn"),
inverseJoinColumns = @JoinColumn(name = "user_sn")
)
private Set<User> users = new HashSet<>();
我向服务器和用户代码添加了 CascadeTypes SAVE_UPDATE、MERGE 和 PERSIST
另外,我重新设计了base的架构,把snowflakes做成了Primary Keys,因为values都是唯一的
我是 Spring 和 Hibernate 的新手,运行 遇到了一个我几天都无法解决的问题。
在我的项目中,我在服务器和用户实体之间使用多对多关系。一个用户可以存在于多个服务器上。
我的想法是: 服务器 <-> Server_Users <-> 用户
创建 tables 的代码:
CREATE TABLE public.servers (
id bigint NOT NULL,
s_snowflake bigint NOT NULL,
name character varying(64) NOT NULL
);
CREATE TABLE public.users (
id bigint NOT NULL,
u_snowflake bigint NOT NULL,
name character varying(64) NOT NULL
);
CREATE TABLE public.server_users (
id bigint NOT NULL,
server_id bigint NOT NULL,
user_id bigint NOT NULL
);
这是我的 class 的样子:
@Entity
@Table(name = "servers")
public class Server {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@Column(name = "s_snowflake", unique = true)
private long snowflake;
private String name;
@ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@JoinTable(
name = "server_users",
joinColumns = @JoinColumn(name = "server_id"),
inverseJoinColumns = @JoinColumn(name = "user_id")
)
private Set<User> users = new HashSet<>();
}
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@Column(name = "u_snowflake", unique = true)
private long snowflake;
private String name;
@ManyToMany(mappedBy = "users", targetEntity = Server.class, fetch = FetchType.EAGER)
private Set<Server> servers = new HashSet<>();
}
这在我初始化数据时效果很好。我创建了一个服务器对象并用用户填充它,所有内容都已正确保存。
但是当我尝试保存包含已经在用户 table 中的用户的服务器时,我遇到了问题(如果我从数据库中级联删除服务器,用户不应该被删除)。
有什么方法可以配置 Hibernate 以便在必要时添加新用户,但如果用户存在,则使用 Server_Users table 将其“创建关系”到新服务器?
我试过 Cascade.SAVE_UPDATE 和其他方法,但没有结果。
成瘾:
这是我用来保存和更新的 DAO class 方法:
public abstract class AbstractDAOImpl<T> implements AbstractDAO<T> {
public void save(T entity) {
Session session = HibernateSessionFactoryUtil.getSessionFactory().openSession();
Transaction trx = session.beginTransaction();
session.save(entity);
trx.commit();
session.close();
}
public void update(T entity) {
Session session = HibernateSessionFactoryUtil.getSessionFactory().openSession();
Transaction trx = session.beginTransaction();
session.update(entity);
trx.commit();
session.close();
}
}
服务器添加逻辑。首先,我将它保存到数据库中,然后用用户填充Set并执行update()
如果 table with users 为空,则此方法有效,所有必要的记录和连接都在 Server_Users 和 Users tables:
public static void addServer(Guild guild) {
Server server = new Server(Long.parseLong(guild.getId()), guild.getName());
serverDAO.save(server);
for (Member m : guild.getMembers()) {
User user = new User(Long.parseLong(m.getId()), m.getUser().getName());
user.addServer(server);
server.addUser(user);
}
serverDAO.update(server);
}
我找到了解决方案
@Cascade({
org.hibernate.annotations.CascadeType.SAVE_UPDATE,
org.hibernate.annotations.CascadeType.MERGE,
org.hibernate.annotations.CascadeType.PERSIST
})
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(
name = "server_users",
joinColumns = @JoinColumn(name = "server_sn"),
inverseJoinColumns = @JoinColumn(name = "user_sn")
)
private Set<User> users = new HashSet<>();
我向服务器和用户代码添加了 CascadeTypes SAVE_UPDATE、MERGE 和 PERSIST
另外,我重新设计了base的架构,把snowflakes做成了Primary Keys,因为values都是唯一的