0

使用并发请求线程保存数据时面临问题。详情如下:

  1. 春天 3.0.5
  2. 雄猫 1.6
  3. 休眠 3

通过示例应用程序模拟问题:

数据库详细信息:

  1. 用户
  2. 用户信息

一个用户可以包含多个用户信息,这意味着这些表之间将存在oneToMany关系。

领域类

用户类

@Entity
@Table(name = "user")
public class User implements java.io.Serializable {

    private static final long serialVersionUID = 5753658991436258019L;
    private Integer idUser;
    private String Name;    
    private Set<UserInfo> userInfos = new HashSet<UserInfo>(0);

    public User() {
    }

    @Id
    @Column(name = "iduser", unique = true, nullable = false)
    public Integer getIdUser() {
        return idUser;
    }

    public void setIdUser(Integer idUser) {
        this.idUser = idUser;
    }

    @Column(name = "name", nullable = false, length = 256)
    public String getName() {
        return this.Name;
    }

    public void setName(String tenantName) {
        this.Name = tenantName;
    }

    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "user")
    public Set<UserInfo> getUserInfos() {
        return userInfos;
    }

    public void setUserInfos(Set<UserInfo> userInfos) {
        this.userInfos = userInfos;
    }
}

用户信息类

@Entity
@Table(name = "userInfo")
public class UserInfo implements java.io.Serializable {

    private static final long serialVersionUID = 5753658991436258019L;
    private Integer iduserInfo;
    private User user;
    private String address; 

    public UserInfo() {
    }

    @Id
    @GeneratedValue(strategy = IDENTITY)
    @Column(name = "iduserInfo", unique = true, nullable = false)
    public Integer getIduserInfo() {
        return iduserInfo;
    }

    public void setIduserInfo(Integer iduserInfo) {
        this.iduserInfo = iduserInfo;
    }

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "userId", nullable = false)
    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    @Column(name = "address", nullable = false, length = 256)
    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }
}

所以我试图通过休眠将UserInfo保存在db中但在保存UserInfo之前创建用户并尝试从DB中获取它,如果找到则在UserInfo对象中设置否则保存它(用户)然后再次从DB中获取(用于持久状态用户对象)。然后在 UserInfo 中设置并将 UserInfo 对象保存在 DB 中。

注意:这一切都适用于顺序请求

但是在多个 UserInfo 需要相同用户对象时的并发请求,即使保存后也无法加载用户对象。

ServiceLayer 方法saveUserAndInfo如下:

@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Throwable.class)
@Override
public void saveUserAndInfo(String tenantName) throws Exception {

    User user = new User();
    user.setName("Name - " + tenantName + " - "
            + System.currentTimeMillis());


    UserInfo userInfo = new UserInfo();
    userInfo.setAddress("India - " + tenantName + " - "
            + System.currentTimeMillis());
    Set<UserInfo> setUserInfos = new HashSet<UserInfo>();
    setUserInfos.add(userInfo);

    user.setIdUser(1);

    user = findByCriteria(user);
    userInfo.setUser(user);

    saveUserInfo(userInfo);
}

/**
 * This method will return <code>User</code> object in persistent state, 
 * 
 * If exist fetch from DB, it NOT then insert and again fetch from db 
 * @param user
 * @return
 * @throws Exception
 */
public User findByCriteria(User user) throws Exception {

    List<Criterion> criterionList = new ArrayList<Criterion>();
    criterionList.add(Restrictions.eq("idUser", user.getIdUser()));

    Criteria crit = openSession().createCriteria(User.class);

    for (Criterion c : criterionList) {
        crit.add(c);
    }
    List<User> entityList = null;
    try {
        entityList = crit.list();
    } catch (Exception ex) {
        ex.printStackTrace();
    }

    if (entityList == null || entityList.isEmpty()) {
        log.error("No User Found - " + user.getIdUser() + " now adding...");
        saveUser(user);
        try {
            crit = openSession().createCriteria(User.class);
            entityList = crit.list();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        if (entityList != null && !entityList.isEmpty()) 
            return entityList.get(0);
        else {
            log.error("No User Found - " + user.getIdUser() + " Even after adding");
            throw new Exception("No User Found - " + user.getIdUser() + " Even after adding");
        }
    }
    else {
        return entityList.get(0);
    }
}

请帮忙 !!!

4

0 回答 0