我在深入了解使用 ManyToOne 注释保存新条目时遇到了问题。
我有两个表:
1( 用户组
@Entity
@Table(name="usergroup")
public class UserGroup{
@Id
@Column(name = "id", unique = true, nullable = false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name="name")
private String name;
@OneToMany(mappedBy="userGroup",
cascade= {CascadeType.PERSIST, CascadeType.MERGE,
CascadeType.DETACH, CascadeType.REFRESH}, fetch = FetchType.LAZY)
private List<User> users= new ArrayList<>();
//constructor, getter and setter
2( 用户
@Entity
@Table(name="user")
public class User{
@Id
@Column(name = "id", unique = true, nullable = false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "name")
private String name;
@ManyToOne(fetch = FetchType.LAZY, cascade= {CascadeType.PERSIST, CascadeType.MERGE,
CascadeType.DETACH, CascadeType.REFRESH}, optional = false)
@JoinColumn(name="user_group_id", referencedColumnName = "id")
private UserGroup userGroup;
第一个表 - 用户组 - 是用数据初始化的。这非常重要。我想在为用户创建新条目时连接该信息。
所以用户有数据,例如
select * from usergroup;
id name
1 name1
2 name2
3 name3
我创建了用户存储库
public interface UserRepository extends JpaRepository<User, Long> {
}
这是有问题的部分!
我想添加新的用户,提供 -> 名称和 id 用户组。
服务:
@Override
@Transactional
public void create(String name, Long groupId) {
UserGroup userGroup = userGroupRepository.getOne(groupId);
User user = new User();
user.setName(name);
user.setUserGroup(userGroup)
userRepository.save(user);
}
问题出在哪里?
-> 新用户的 id 为空;->错误:无法执行语句;SQL [n/a];约束 [唯一];嵌套异常是 org.hibernate.exception.ConstraintViolationException: 无法执行语句
这是使用连接到现有条目保存新条目的正确方法吗?我的意思是,我应该通过 id 找到存在条目并设置为新条目?
谢谢你的建议!
对于这两个实体,更新如下。
@Id
@Column(name = "id") //removed attributes unique = true, nullable = false
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
通过指定 Hibernate nullable = false,
在写入数据库之前检查 ID 是否为空。但是,对于GenerationType.IDENTITY
,只有在数据库写入后才会设置ID,因此会出现错误。
您的问题不在于ManyToOne关系本身,而在于用户的ID生成。有了GenerationType.IDENTITY
,您应该为要保存的每个用户提供一个标识符(我在您提供的代码部分中没有看到该部分(,除非数据库具有内部 ID 生成(如 postgres 中的串行(。
至于保存连接到其他现有条目的条目的方法,您正在做的事情应该可以正常工作。另一种方法是通过仅设置已知 ID 而不从数据库加载它来初始化用户组。当然,如果 id 无效,您将面临引用错误。