[英]Hibernate merge make both insertion and deletion
我對Hibernate真的很陌生。 這是我的問題:
我有一個中央數據庫,用於重組來自許多代理的數據。
每個代理都必須僅將與他有關的數據存儲到自己的數據庫中。
我需要在服務器/代理之間同步數據
我有2種情況:
1)第一次同步(代理上的數據庫為空)
2)完全同步(刪除/添加新元素/更改等...)
我有一個盒子實體和一個用戶實體,它們之間的關系是多對多的
框實體的描述(部分)如下:
@Entity
//@Cache(usage=CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
@Table(name="box")
@NamedQuery(name="Box.findAll", query="SELECT b FROM Box b")
@JsonIdentityInfo(generator= ObjectIdGenerators.IntSequenceGenerator.class, property="@id")
public class Box extends BasicData implements Serializable {
....
//bi-directional many-to-many association to User
@ManyToMany(mappedBy="boxs")
private Set<User> users;
//bi-directional many-to-one association to BoxUser
@OneToMany(mappedBy="box", orphanRemoval=true)
@Cascade({ org.hibernate.annotations.CascadeType.ALL})
private Set<BoxUser> boxUsers;
getters /setters
....
BoxUser實體的描述(部分)如下:
public class BoxUser implements Serializable {
private static final long serialVersionUID = 1L;
@EmbeddedId
private BoxUserPK id;
//bi-directional many-to-one association to Box
@ManyToOne
@JoinColumn(name="boxid", nullable=false, insertable=false, updatable=false)
@Cascade({ org.hibernate.annotations.CascadeType.ALL})
private Box box;
//bi-directional many-to-one association to User
@ManyToOne
@JoinColumn(name="userid", nullable=false, insertable=false, updatable=false)
@Cascade({ org.hibernate.annotations.CascadeType.ALL})
private User user;
getters /setters
....
用戶實體的描述(部分)如下:
public class User extends BasicData implements Serializable {
private static final long serialVersionUID = 1L;
//bi-directional many-to-one association to BoxUser
@OneToMany(mappedBy="user")
private Set<BoxUser> boxUsers;
//bi-directional many-to-many association to Box
@ManyToMany
@JoinTable(
name="box_user"
, joinColumns={
@JoinColumn(name="userid", nullable=false)
}
, inverseJoinColumns={
@JoinColumn(name="boxid", nullable=false)
}
)
private Set<Box> boxs;
getters /setters
....
當我嘗試保存/更新(我正在使用merge方法)時,代理端的數據我看到該數據已插入但被立即刪除。
我不明白為什么。 這里是休眠的輸出:
Hibernate:
insert
into
box_user
(role, boxid, userid)
values
(?, ?, ?)
2015-05-20 15:14:23.818 TRACE: org.hibernate.type.EnumType - Binding [ADMIN_BOX] to parameter: [1]
2015-05-20 15:14:23.819 TRACE: org.hibernate.type.descriptor.sql.BasicBinder - binding parameter [2] as [BIGINT] - [1]
2015-05-20 15:14:23.819 TRACE: org.hibernate.type.descriptor.sql.BasicBinder - binding parameter [3] as [BIGINT] - [4]
Hibernate:
delete
from
box_user
where
userid=?
2015-05-20 15:14:23.831 TRACE: org.hibernate.type.descriptor.sql.BasicBinder - binding parameter [1] as [BIGINT] - [4]
這里是進行同步的方法:
private void synchroUser(Box internalBox, Long boxId)
{
RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
BoxUser[] remoteBUList = restTemplate.getForObject(DOMITIK_URL + RestURIConstant.DOMITIK_WS + "getboxuserbyboxid/{boxid}" ,BoxUser[].class,boxId);
if(internalBox == null)
{
boolean firstAdd = true;
for (BoxUser curBoxUser : remoteBUList)
{
// this avoid to save more than one time the box (exception occurred if trying to save several time.
if(!firstAdd)
curBoxUser.setBox(null);
boxUserService.mergeElement(curBoxUser);
firstAdd = false;
}
}
else
{
List<BoxUser> localBUList = boxUserService.findAll();
//deleting users that were removed from server
for (BoxUser localBoxUser : localBUList)
{
boolean userFound = false;
for (BoxUser remoteBoxUser : remoteBUList)
{
if(localBoxUser.getUser().getId() == remoteBoxUser.getUser().getId())
{
userFound = true;
break;
}
}
if(!userFound)
userService.deleteElement(localBoxUser.getUser());
}
//adding new users
for (BoxUser curBoxUser : remoteBUList)
{
boolean userFound = false;
for (BoxUser localBoxUser : internalBox.getBoxUsers())
{
if(localBoxUser.getUser().getId() == curBoxUser.getUser().getId())
{
userFound = true;
break;
}
}
if(!userFound)
{
curBoxUser.setBox(null);
boxUserService.mergeElement(curBoxUser);
}
}
}
}
我真的被困住了,需要了解我做錯了什么...
感謝您的時間和幫助
我想在您的配置中,您將擁有屬性hbm2ddl.auto
,其值為"create-drop"
,該值將在會話結束后自動刪除數據並刪除架構
我找到了解決問題的辦法。
問題在於類上的多個級聯定義。
我刪除了Box實體上的級聯,並將其保留在Box實體上:
public class Box extends BasicData implements Serializable {
....
//bi-directional many-to-many association to User
@ManyToMany(mappedBy="boxs")
private Set<User> users;
//bi-directional many-to-one association to BoxUser
@OneToMany(mappedBy="box")
private Set<BoxUser> boxUsers;
並將其保留在BoxUser實體上
public class BoxUser implements Serializable {
private static final long serialVersionUID = 1L;
@EmbeddedId
private BoxUserPK id;
@Enumerated(EnumType.STRING)
@Column(nullable=false)
private UserRole role;
//bi-directional many-to-one association to Box
@ManyToOne
@JoinColumn(name="boxid", nullable=false, insertable=false, updatable=false)
@Cascade({ org.hibernate.annotations.CascadeType.ALL})
private Box box;
//bi-directional many-to-one association to User
@ManyToOne
@JoinColumn(name="userid", nullable=false, insertable=false, updatable=false)
@Cascade({ org.hibernate.annotations.CascadeType.ALL})
private User user;
現在一切正常。
由於我剛進入休眠狀態,所以我希望這是一個好的解決方案
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.