簡體   English   中英

Hibernate合並可同時進行插入和刪除

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM