Hibernate合并同时进行插入和删除

时间:2015-05-20 12:37:28

标签: java mysql spring hibernate jpa

我是Hibernate的新手。 这是我的问题:

我有一个中央数据库,可以从很多代理重新组合数据。

每个代理商必须只将与他有关的数据存储在自己的数据库中。

我需要在服务器/代理之间同步数据

我有2个案例:

1)首次同步(代理上的DB为空)

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
    ....

当我尝试保存/更新(我正在使用合并方法)时,代理端的数据我看到数据已插入但已立即删除。

我不明白为什么。这里是hibernate的输出:

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);
            }
        }

    }
}

我真的被困住了,需要了解我做错了什么......

感谢您的时间和帮助

2 个答案:

答案 0 :(得分:0)

我猜测在您的配置中,您拥有值为hbm2ddl.auto的属性"create-drop",会自动删除数据并在会话结束后删除架构

答案 1 :(得分:0)

我找到了解决问题的方法。

问题在于类的多级级别定义。

我删除了Box实体上的级联并将其保留在Box实体上:

   ' Generalized example for pulling integer portion from
   ' a textbox of the form 'a=12345'; amend as appropriate. Untested.

   Dim a as integer
   Dim receivedData as String
   ' Assuming txtBox1 as the name of the textbox in the client
   receivedData = txtBox1.Text
   receievedData = mid$(value,3)
   a = Val(receivedData)

将其保留在BoxUser实体

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;

现在它工作正常。

由于我是hibernate的新手,我希望这是一个很好的解决方案