【问题标题】:Update only changed entity fields and check for changes by other users in EJB仅更新已更改的实体字段并检查 EJB 中其他用户的更改
【发布时间】:2013-05-22 18:40:38
【问题描述】:

在 EJB 类中,我有两种远程接口方法:

Class MyBean {
    public CustomerEntity getCustomer(String id) {......}
    public void updateCustomer(CustomerEntity newValues, CustomerEntity oldValues) {......}
}

客户实体由一些带有 getter 和 setter 的字段组成。

@Entity 
public class Customer {
    @ID private String id;
    @Column private String name;
    @Column private String phone;
    // Getters and setters 
    .
    .
}

客户端应用:

Customer customer myBeanRemoteInterface.getCustomer("some id");
Customer oldCustomer = customer;    //Save original customer data
displayCustomerFormAndAcceptChanges(customer);
myBeanRemoteInterface.updateCustomer(customer, oldCustomer);

EJB updateCustomer 现在应该更新服务器上的客户。为避免覆盖其他用户对其他字段所做的任何更改,应仅提交用户已更改的字段。像下面这样:

public void updateCustomer(CustomerEntity newValues, CustomerEntity oldValues) {
    Customer customer = entityManager.find(Customer.class, oldValues.getId());
    if (!newValues.getName().equals(oldValues.getName()) { // Value updated
        // If the value fetched by entityManager.find is different from what was originally fetched that indicates that the value has been updated by another user.
        if (!customer.getName().equals(oldValues.getName()) throw new CustomerUpdatedByOtherUserException();
        else customer.setName(newValues.getName());
    }
    // repeat the code block for every field in Customer class
    entityManager.flush();
}

现在的问题是 updateCustomer 中的代码块需要为 Customer 类中的每个字段重复一次。如果将新字段插入到 Customer 类中,则 EJB 也需要更新。

如果将更多字段添加到 Customer 类,我需要一个无需更新 EJB 即可工作的解决方案。

有什么建议吗?

【问题讨论】:

    标签: java ejb entitymanager


    【解决方案1】:

    使用 Java 反射:

         Method[] methods = Customer.class.getDeclaredMethods();
         Class<?>[] methodParams = null;
         Object[] paramValue = new Object[1];
    
         for (Method method : methods) {
    
           if(method.getName().contains("set")) //This is for set methods. 
           {
               methodParams = method.getParameterTypes();
               if(methodParams[0].equals(String.class))
               {
                   paramValue[0] = "some string"; // Assigning some value to method parameter
               }
    
               method.invoke(customer, paramValues); // customer is your object you are executing your methods on.
           }
        }
    

    【讨论】:

    • 是的,当我们想在运行时了解类结构并对其进行操作时,反射会派上用场。
    【解决方案2】:

    您真的应该考虑向您的实体添加一个@Version 注释字段,以让您的 JPA 实现处理乐观锁定,然后处理您尝试使用“陈旧”数据进行更新的情况。 否则,您将危及您的数据完整性。

    干杯 //Lutz

    【讨论】:

    • 谢谢!但是,此解决方案不允许两个或更多人同时更新实体中的不同字段。
    • 我认为这个解决方案可以适用于我项目中的其他bean。 entityManager.merge() 是否会自动检查 @Version 中的值并在版本不匹配时拒绝合并?
    • 它将拒绝保存版本号过低的实体,因此您将收到 StaleObjectException。我们通常会捕捉到这些并向用户呈现有意义的消息。
    猜你喜欢
    • 1970-01-01
    • 2013-08-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-28
    • 2016-01-10
    • 1970-01-01
    • 2019-06-24
    相关资源
    最近更新 更多