【问题标题】:Why em.persist() has no effect on database table?为什么 em.persist() 对数据库表没有影响?
【发布时间】:2018-06-04 21:16:19
【问题描述】:

我有一个名为 AuthenticationEndpoint 的 RESTful 服务,它检查用户的用户名/密码对、创建令牌、将令牌保存到数据库并将令牌返回给应用程序客户端。 代码工作没有错误和异常。 UserEJB bean 应该将令牌保存到 Token 数据库表中,而 AuthenticationEJB bean 应该更新 User 数据库表中的令牌字段。但正如我在 MySQL Workbench 中看到的,没有保存或更新任何内容。 UserEJB.getUsers() 方法工作正常并返回用户列表,似乎 EJB 容器找到了持久性单元 ForthDynamicWebProject,但为什么我不能保存和更新实体?感谢您的关注。

AuthenticationEndpoint RESTful 服务

@ApplicationScoped
@Path("/authentication")
public class AuthenticationEndpoint {

    @Inject
    AuthenticateEJB authenticateEJB;

    @POST
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    public Response authenticateUser(String jsonString) {
        Gson gson = new Gson();
        Credentials credentials = gson.fromJson(jsonString, Credentials.class);
        String userName = credentials.getUserName();
        String password = credentials.getPassword();

        try {
            User user = authenticateEJB.checkUser(userName, password);
            if ((user instanceof User) && user != null) {
                return Response.ok().header("token", user.getToken().getToken()).build();
            } else {
                return Response.status(Response.Status.FORBIDDEN).build();
            }
        } catch (Exception e) {
            return Response.status(Response.Status.FORBIDDEN).build();
        }
    }
}

这是 EJB 的代码:

验证EJB

@LocalBean
@Stateless
public class AuthenticateEJB {

@PersistenceContext(unitName = "ForthDynamicWebProject")
EntityManager em;

@Inject
UserEJB userEJB;

public User checkUser(String userName, String password) {
    List<User> users = userEJB.getUsers();

    for (User user : users) {
        if (user.getUsername().equals(userName) && user.getPassword().equals(password)) {
            user.setToken(userEJB.updateToken());
            em.merge(user);
            return user;
        }
    }
    return null;
}
}

用户EJB

@LocalBean
@Stateless
public class UserEJB {

@PersistenceContext(unitName = "ForthDynamicWebProject")
EntityManager em;

@Inject
Token token;

public List<User> getUsers() {
    Query query = em.createQuery("from User");
    return (List<User>) query.getResultList();
}

public Token updateToken() {
    em.persist(token);
    return token;
}
}

persistence.xml:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" 
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
            xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence 
            http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
    <persistence-unit name="ForthDynamicWebProject" transaction-type="JTA">
    <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
    <jta-data-source>jdbc/second_attempt_hibernate</jta-data-source>
    <class>converters.ConverterLocalDateTime</class>
    <class>entity.DocStatus</class>
    <class>entity.DocType</class>
    <class>entity.Document</class>
    <class>entity.Employee</class>
    <class>entity.MailOrder</class>
    <class>entity.MailOrderStatus</class>
    <class>entity.Token</class>
    <class>entity.User</class>
    </persistence-unit>
</persistence>

更新:

令牌实体

@Entity
@Table(name = "tokens")
@NamedQuery(name = "Token.findAll", query = "SELECT t FROM Token t")
public class Token implements Serializable {
private static final long serialVersionUID = 1L;

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;

@Temporal(TemporalType.TIMESTAMP)
private Date loginTime;

private String token;

// bi-directional one-to-one association to User
@OneToOne(mappedBy = "token")
private User user;

public Token() {
    ConverterLocalDateTime converter = new ConverterLocalDateTime();
    loginTime = converter.convertToDatabaseColumn(LocalDateTime.now());
    token = Double.toString(Math.random());
}

*getters and setters are not showed*

用户实体

@Entity
@NamedQuery(name="User.findAll", query="SELECT u FROM User u")
public class User implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private int id;

    private String password;

    private String username;

    //bi-directional one-to-one association to Employee
    @OneToOne(mappedBy="user")
    private Employee employee;

    //bi-directional one-to-one association to Token
    @OneToOne
    @JoinColumn(name="tokID")
    private Token token;

    public User() {
    }

*getters and setters are not showed*

【问题讨论】:

  • 首先,您应该始终使用从 merge() 返回的实体。其次,您为什么不创建一个查询来获取用户而不是遍历所有用户?第三,只要您不实现远程或本地接口,您就可以删除@LocalBean。但这不是问题所在。请告诉我们更多关于:什么是Token?它从何而来?用户可能已经分配了这个令牌吗?
  • @SimonMartinelli 我已经更新了这个问题。 User 和 Token 是实体,我是通过 Eclipse 中的 Tables 生成实体来获得的。
  • 好的,但是注入的东西是从哪里来的?
  • @SimonMartinelli 我认为,容器在 UserEJB 中自行完成:'@Inject Token token;'
  • 您如何(何时)检查数据库记录未被创建的事实? em.persist() 所做的只是将实体标记为持久的。这并不一定意味着持久化的实体会立即插入到数据库中。这通常发生在事务提交时。

标签: jpa transactions ejb


【解决方案1】:

也许我遗漏了一些东西,但是如果您的用户 ejb 旨在绑定到单个用户,则情况并非如此,因为无状态可以被其他几个客户端重用,因此令牌将与ooled 实例。检查这是否是正确的行为。

其次,您不能注入令牌 JPA 实体,或者至少不能使用当前代码注入,该变量将始终为空。也许这就是您没有看到它持续存在的原因。

第三,还有其他一些事情我会改变,但这是另一个不同的问题。

【讨论】:

    猜你喜欢
    • 2013-01-18
    • 2019-09-03
    • 1970-01-01
    • 2020-04-25
    • 2018-06-29
    • 2015-02-08
    • 1970-01-01
    • 1970-01-01
    • 2019-09-28
    相关资源
    最近更新 更多