我想在我的一个实体中拥有只读功能。我知道在JPA 2.0中,我们本身没有这样的功能。我认为我们可以使用updateable=false, insertable=false
来实现它,但我不认为我知道它是如何工作的。@ManyToOne(updatable = false) - 它应该如何工作?
假设我有两个实体:OrderedItem
和Customer
:
@Entity
public class OrderedItem {
@Id
@GeneratedValue
private int id;
private String name;
@ManyToOne
@JoinColumn(updatable = false)
private Customer owner;
// bunch of simple getters and setters
}
@Entity
public class Customer {
@Id
@GeneratedValue
private int id;
private String name;
@OneToMany(mappedBy="owner")
private Set<OrderedItem> orderedItems;
// bunch of simple getters and setters
}
现在考虑下面的代码:
Customer john = new Customer();
john.setName("John");
OrderedItem milk = new OrderedItem();
milk.setName("Milk");
milk.setOwner(john);
Set<OrderedItem> items = new HashSet<OrderedItem>();
items.add(milk);
john.setOrderedItems(items);
// This starts the EM transaction
startTx();
em.persist(john);
em.persist(milk);
stopTx();
startTx();
OrderedItem milkFromPC = em.find(OrderedItem.class, milk.getId());
System.out.println(milkFromPC.getName() + " ordered by customer: " +
milkFromPC.getOwner().getName());
// Changing the state of Owner entity through the OrderedItem
milkFromPC.getOwner().setName("Terrence");
stopTx();
现在,没有@JoinColumn(updatable = false)
在OrderedItem
实体,该OrderedItem
将从中获取PC,我可以访问它的所有者 - 一个Customer
- 并且会成功修改它的名字。这并不令人意外,因为Customer
也处于托管状态,所以它必须反映在数据库中。
然而,我认为updateable=false
在@JoinColumn
集上的关系的一个侧面将防止UPDATE SQL语句的发生。不幸的是在最后我可以看到数据库(这是“泰伦斯”,而不是“约翰”)更改的名称。我还可以看到执行的SQL UPDATE查询:
[EL精细]:2011-11-30 23:41:27.941 - ClientSession的(16862753) - 连接(11024915) - 线程(线程[ main,5,main]) - UPDATE CUSTOMER SET NAME =? WHERE(ID =?)bind => [Terrence,1]
那么 - 这个updateable=false
真的在做什么?我为什么需要它?它是否只保护我的外键不被更改?它是否像'你不能改变实体,但你可以改变实体的状态'?
谢谢您的回答。这将符合我的经验。但是,在第288页的“专业版JPA 2掌握Java持久性API”*中,有一个“updateable = false,insertable = false”的示例,并且存在以下注释:*“没有新实体将被保留,并且现有的实体永远不会被更新“。*它们严格地指”实体“......不知道该怎么想:-) –