错误:交易未激活

时间:2017-05-11 13:04:03

标签: hibernate jpa servlets

这是导致错误的源代码:

@Override
@Transactional
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public Object queryObject(String query) throws Exception {
    Object o = null;
    EntityTransaction tr = em.getTransaction();

    try {
        if (!tr.isActive()) {
            tr.begin();
        }

        List<Object> objectsList = em.createQuery(query).getResultList();
        if (!objectsList.isEmpty()) {
            o = objectsList.get(0);
        }
        em.flush();
        em.clear();
        em.close();
        tr.commit();
    } catch (Exception e) {
        tr.rollback();
        System.out.println("" + e.getMessage());
    }
    return o;
}

这是调用方法的指令:

UserAccount userAccount =(UserAccount)accountDao.queryObject(“从UserAccount中选择u.identifier,u.email,u.password作为u,其中identifier =”+ account.getIdentifier()+“和password =”+ account.getPassword ());

2 个答案:

答案 0 :(得分:0)

您正在使用容器管理的交易 - 您不需要自己执行此操作。

您的代码可以折叠为:

@Override
@Transactional
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public Object queryObject(String query) throws PersistenceException {
    try {
        return em.createQuery(query).getSingleResult();
    } catch (NonUniqueResultException e) {
        // too many results
        return null;
    } catch (NoResultException e) {
        // not enough results
        return null;
    }
}

<强>然而

撰写如下查询:

"select u.identifier,u.email,u.password from UserAccount as u where identifier=" 
  + account.getIdentifier() + " and password=" + account.getPassword())

可以导致SQL injection attacks

JPA javax.persistence.Query类有一堆setParameter方法,您必须使用这些方法来规避这一点。

因此,通常更容易编写特定的查询方法,而不是您在此尝试的通用方法。

答案 1 :(得分:0)

您是否检查了other answers未处理的有效交易?如果您使用@Transactional

,为什么要手动管理交易?

我还想告诉你如何更好地编写dao(查看自动强制转换为UserAccount.class并使用参数来避免注入):

@Stateless
@Transactional
public class UserAccountDao {
    private static final String SELECT_USERACCOUNT_BY_IDENTIFIER_AND_PASSWORD = "select ua from UserAccount ua where ua.identifier = :identifier and ua.password = :password";

    @PersistenceContext
    EntityManager em;

    public UserAccount selectUserAccountByIdentifierAndPAssword(final String identifier, final String password) {
        List<UserAccount> userAccounts = em.createQuery(SELECT_USERACCOUNT_BY_IDENTIFIER_AND_PASSWORD, UserAccount.class)
            .setParameter("identifier", identifier)
            .setParameter("password", password)
            .getResultList();
        return userAccounts == null || userAccounts.isEmpty() ? null : userAccounts.get(0);
    }
}

您可以将其用于:

UserAccount userAccount = uadao.selectUserAccountByIdentifierAndPAssword(account.getIdentifier(), account.getPassword());
if (userAccount == null) {
    // manage error
}

此代码是手写的,因此可能包含一些错误。