JPA中的嵌套查找插入Rethrows相同的错误

时间:2017-05-15 04:27:54

标签: java hibernate jpa

User.java

@Entity
@Table(name = "User", uniqueConstraints = @UniqueConstraint(columnNames = { "emailAddress" }) )
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long userId;

    private String emailAddress;

}

UserDAO.java

@Repository("UserDAO")
@Transactional
public class UserDAO {

    @PersistenceContext
    private EntityManager entityManager;

    public String insert(User user) {

        try {
            entityManager.persist(user);
        } catch (PersistenceException e) {
            if (e.getCause() != null && e.getCause().getClass() == ConstraintViolationException.class) {
                try {
                    insertedUserId = getIdByEmail(user.getEmailAddress());
                } catch (Exception exception) {
                    //some error handling
                }
            }
        }

    }

    private long getIdByEmail(String emailAddress) {
        Query query = entityManager
                .createQuery(
                        "FROM User WHERE emailAddress = :emailAddress")
                .setParameter("emailAddress", emailAddress);
        User user = (User) query.getSingleResult();
        return user.getUserId();
    }

}

我正在尝试将记录插入到用户表中,如果电子邮件地址(这是一个唯一列)已经存在,我想获取现有记录而不是插入新记录。现在,我想首先插入然后尝试捕获异常以找到记录。但是当我这样做时,即使在查找查询的catch子句中,我也会得到以下ConstraintViolationError。

  

javax.persistence.PersistenceException:org.hibernate.exception.ConstraintViolationException:无法执行语句

     

引起:org.h2.jdbc.JdbcSQLException:唯一索引或主键违规:“ON PUBLIC.USER(EMAILADDRESS)VALUES('abc_fgh@aol.com',1)”; SQL语句:   插入User(emailAddress,UserId)值(?,?)

2 个答案:

答案 0 :(得分:0)

在实际情况中,我建议您先检查电子邮件是否已经存在。如果不存在则继续存在。

编辑1:如果您的目的是保存用户,那么实际上作为第二个选项,我会使用merge(user)代替persist(user)

答案 1 :(得分:0)

如@manish所述,您首先需要清除entityManager,但随后可能会出现以下错误。

  

org.springframework.transaction.TransactionSystemException:无法提交JPA事务;嵌套异常是javax.persistence.RollbackException:事务标记为rollbackOnly

要解决此错误,只需在代码中添加以下行。 (original answer

TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();

所以我的案例中的try块最终看起来像 -

try {
    entityManager.clear();
    insertedUserId = getIdByEmail(user.getEmailAddress());
    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
}