如果我有这样的配置?这可以工作吗?
@ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
@JoinColumn(name = "FOREIGN_ID", nullable = false, insertable = false, updatable = false)
ForeignClass foreignClass;
我认为不,因为级联类型的行为与可插入和可更新的参数冲突。
你怎么看?
长话短说,不,这些设置不会互相排斥。
想象一下,我们有以下模型。
create table APP_USER
(
USER_ID number,
USER_NAME varchar2(400),
constraint APP_USER_PK primary key(USER_ID)
);
create table APP_BILLING_NUMBER
(
BILL_ID number,
BILL_ACCOUNT varchar2(20),
BILL_BANK_NAME varchar2(300),
BILL_USER_ID number,
constraint APP_BILLING_NUMBER_PK primary key(BILL_ID),
);
以及适当的休眠映射:
@Entity
@Table(name = "APP_USER")
public class User
{
@Id
@Column(name = "USER_ID")
private Long id;
@Column(name = "USER_NAME")
private String name;
}
@Entity
@Table(name = "APP_BILLING_NUMBER")
public class BillingNumber
{
@Id
@Column(name = "BILL_ID")
private Long id;
@Column(name = "BILL_ACCOUNT")
private String account;
@Column(name = "BILL_BANK_NAME")
private String bankName;
@ManyToOne
@JoinColumn(name="BILL_USER_ID")
private User user;
}
如果我们尝试做这样的事情:
User user = new User();
user.setId(1L);
user.setName("Alex");
BillingNumber bill = new BillingNumber();
bill.setId(1L);
bill.setAccount("EA12345678");
bill.setBankName("BNP Paribas");
bill.setUser(user);
session.persist(bill);
我们将发现帐单已添加到APP_BILLING_NUMBER
表,
SQL> select * from APP_BILLING_NUMBER;
BILL_ID BILL_ACCOUNT BILL_BANK_NAME BILL_USER_ID
------- ------------ -------------- ------------
1 EA12345678 BNP Paribas 1
但用户不是。发生这种情况是因为默认情况下,我们有@ManyToOne(cascade={})
。如果我们想将User
实体与BillingNumber
实体保持在一起,则应添加CascadeType.PERSIST
:
@ManyToOne(cascade = {CascadeType.PERSIST})
@JoinColumn(name="BILL_USER_ID")
private User user;
然后,如果我们要使用session.merge(bill)
操作,我们也应该添加CascadeType.MERGE
。
现在想像,我们有
@ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
@JoinColumn(name="BILL_USER_ID", insertable = false, updatable = false)
private User user;
执行上述持久操作后,我们将得到:
SQL> select * from APP_USER;
USER_ID USER_NAME
------- ---------
1 Alex
SQL> select * from APP_BILLING_NUMBER;
BILL_ID BILL_ACCOUNT BILL_BANK_NAME BILL_USER_ID
------- ------------ -------------- ------------
1 EA12345678 BNP Paribas (null)
您可以看到,两个实体都已插入,但是由于APP_BILLING_NUMBER.BILL_USER_ID
,null
引用为@JoinColumn(..., insertable = false, ...)
。而且由于updatable = false
,您无法更新它。
所以,这是一个有效的但非常奇怪的情况。