问题
I want to have a read-only functionality in one of my entities. I know that in JPA 2.0 we don't have such functionality per se. I thought we can achieve it using updateable=false, insertable=false
but I don't think I get how it works.
Assume that I have two entities: OrderedItem
and 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
}
Now consider the following code:
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();
Now, without @JoinColumn(updatable = false)
in OrderedItem
entity, the OrderedItem
would be fetched from the PC, I'd access it's owner - a Customer
- and would successfully modified its name. It wouldn't be a surprise because the Customer
was also in managed state, so it had to be reflected in the database.
However, I assumed that updateable=false
in @JoinColumn
set on the One side of the relationship would prevent the UPDATE SQL statement from occurring. Unfortunately in the end I can see the name changed in the database (it's "Terrence" instead of "John"). I can also see the executed SQL UPDATE query:
[EL Fine]: 2011-11-30 23:41:27.941--ClientSession(16862753)--Connection(11024915)--Thread(Thread[main,5,main])--UPDATE CUSTOMER SET NAME = ? WHERE (ID = ?) bind => [Terrence, 1]
So - what does this updateable=false
really do? Why do I need it? Does it protect only my foreign key from being changed? Is it like 'you can't change the entity but you can change the state of the entity'?
回答1:
From the documentation
Whether the column is included in SQL UPDATE statements generated by the persistence provider.
So like you said, "it protects only my foreign key from being changed"
来源:https://stackoverflow.com/questions/8334216/manytooneupdatable-false-how-it-should-work