问题描述
在休眠JPA中,如何更新对象?
我有一个具有两个属性的项目实体。 projectid和projectname。
这里projectid是主键。现在,在我的更新方法中,我应该能够同时修改属性projectid和projectname。查询应通过以下方式看起来像。
update PROJECT set ID=\'123\',NAME=\'Intel\' where ID=\'122\'
我想将project_id分配给user_id。
project_table
-------------
project_id project_name
-------------------------
LK987 LockSystem
MK876 MockSystem
user_project_table
---------------------
user_id project_id
--------------------------
12343 LK987
12344 MK876
12343 TK656
12675 TK656
解决方法
停止思考SQL,开始思考,2ѭ。
项目p = entityManager.find(Project.class,122);
p.setId(123);
p.setName(\“ Intel \”);
entityManager.merge(p);
也就是说,更改实体的主键几乎总是错误的选择。
您为什么要更改实体的身份?您还需要更新指向它的其他表中的所有外键。似乎很痛苦,没有收获。您最好将其设置为“业务密钥”(普通属性),并使用更永久的代理密钥。
如果确实需要更改项目的ID号,则应将主键更改为自动递增的数字。该实体看起来像这样:
@Entity
public class Project
{
@Id @GeneratedValue
private int id;
private int projectId;
private String projectName;
// getters and setters
}
因此,您想将项目与用户关联。
您可以在项目ID(字符串,例如\"LK987\"
)作为主键的情况下执行此操作(到目前为止,我确定您应该更改了此键),也可以使用单独的自动递增int
作为ID。由你决定;我个人的喜好是自动增量方法,因此您以后不必担心。
您想要做的是在Project
实体和User
实体之间建立关系。除了存储外键字段,您应该存储实体字段(用于一对一,一对多或多对一映射)或实体集合(对于一对多,多对一,或多对多映射)。如果我了解您的需求:
每个用户可以有多个项目,每个项目可以有多个用户(因此映射是多对多的)
用户了解项目,项目也可能了解用户(因此映射是双向的)。我假设User
是关系的所有者,Project
是逆关系。
这意味着您将使用ѭ10注释,并指定ѭ11以及要使用的ѭ12。
用户实体类
@Entity
public class User
{
@Id @GeneratedValue
int id; // the PK for user entities
@ManyToMany
@JoinTable(
name=\"user_project_table\",joinColumns=@JoinColumn(name=\"user_id\"),inverseJoinColumns=@JoinColumn(name=\"project_id\"))
Set<Project> projects;
// snip...
}
项目实体类
@Entity
public class Project
{
@Id @GeneratedValue
int id;
String projectId;
String projectName;
@ManyToMany(mappedBy=\"projects\")
Set<User> users;
// snip...
}
注意我们如何使用成熟的实体类,而不仅仅是外键。
进一步阅读《 Java EE 6教程》:
在实体字段和属性中使用集合
实体关系中的多重性
实体关系的方向
, 如果项目ID是主键和对象的标识符,则永远不要更改它。主键的更改意味着所表示的对象更改为完全不同的内容。
JPA假定主键是固定的。读取,更新和删除操作通过其ID来标识所涉及的对象。如果更改对象的ID并执行更新,则JPA要么更新一些完全不同的对象(这可能会导致异常),要么根本找不到要更新的对象。
为了强调这一点,JPA规范禁止更改主键。 Hibernate还可从任何生成的更新语句中排除主键。参见JSR-317的第28页
其主键的值唯一
标识一个
持久上下文和
EntityManager操作如所述
在第3章“实体操作”中。的
应用程序不得更改值
主键的值(这包括不更改作为主键的可变类型或复合主键的属性的值)。行为
如果发生这种情况,则为undefined(实现可能会(但不是必须)引发异常。可移植应用程序不得依赖任何此类特定行为)。
为了获得理想的结果,您应该删除旧对象并创建一个新对象。