为什么实体 bean 字段 (java.util.Date) 在更新后更改值

如何解决为什么实体 bean 字段 (java.util.Date) 在更新后更改值

我有这个实体 bean“用户”,它有一个 java.util.Date 字段。当我出于某种奇怪的原因更新 JSF 页面上的任何用户字段(即电话号码、公司名称等)时,数据库中日期字段的值会发生变化。我的开发环境是 Windows 10 上的 Netbeans 12.0、EclipseLink JPA、Apache Derby DB 和 GlassFish 5.1。

例如,当我添加出生日期为“1980-08-20”的用户 (Bob) 时,JSF 会为 Bob 的用户实体设置值“1/20/80 3:38 AM”,此外,无论如何一天中的时间,我向用户添加“3:38 AM”是始终附加到日期的固定时间。后来,当我从数据库中检索 Bob 并在 JSF 页面上显示他的信息时,他的出生日期正如预期的那样是“1980-08-20”。如果我更新 Bob 的任何字段(即电话号码),“1/20/80 3:38 AM”的出生日期值发送到处理更新的会话 Bean LoginRequestSessionBean(我通过调试器验证了它)。在更新成功完成并且我从数据库中检索 Bob 并显示在 JSF 页面上之后,Bob 的出生日期是“1/20/80 12:00 AM”而不是“1/20/80 3:38 AM” ”,因此我看到的是“1980-30-19”而不是“1980-08-20”?任何的想法?

这是将 Bob 添加到系统时的 SQL 日志:

  INSERT INTO PERSISTENCE_USER (ID,CELLPHONE,COMPANY,DATEOFBIRTH,FIRSTNAME,LASTNAME,OFFICEPHONE,PASSWORD,USERID,USERROLE) VALUES (?,?,?)
    bind => [5,(910)-509-3924,IBM,1980-01-20,Bob,Nittelo,(818)-456-9012,password,Bobnitello,consumer]]]

这是更新 Bob 时的 SQL 日志

  UPDATE PERSISTENCE_USER SET USERROLE = ?,CELLPHONE = ?,DATEOFBIRTH = ?,LASTNAME = ?,USERID = ?,FIRSTNAME = ?,OFFICEPHONE = ?,COMPANY = ? WHERE (ID = ?)
    bind => [consumer,(818)-456-9011,5]]]

我有一个 JSF 页面,显示所有用户并允许更新用户信息。还有另一个 JSF 页面允许向系统添加用户。这是源代码:

@NamedQuery(
        name = "updateUser",query = "UPDATE User u SET u.userId=?1,u.userRole=?2,u.cellPhone=?3,u.company=?4,"
        + "u.dateOfBirth=?5,u.firstName=?6,u.lastName=?7,u.officePhone=?8 "
        + "WHERE u.id = ?9"
)
public class User implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    @NotNull
    private String userId;
    @NotNull
    private String password;
    @NotNull
    private String userRole;
    @NotNull
    private String firstName;
    @NotNull
    private String lastName;
    @Temporal(TemporalType.DATE)
    private Date dateOfBirth;
    @NotNull
    private String officePhone;
    private String cellPhone;
    @NotNull
    private String company;
............
}

这是与数据库交互的类

Stateless
public class LoginRequestSessionBean {

public void addUser(User u) throws ListServiceException {
        try {
               em.persist(u);
              
        } catch (Exception e) {
            throw (ExceptionHandler.wrapException(
                                e,logger,"Error occured when adding a user "+u.getUserId()));
        }
    }
    public void removeUser(User u) throws ListServiceException{
        try{
              if(!em.contains(u)){
                  u = em.merge(u);
              }
              em.remove(u);
        } catch (Exception e) {
            throw (ExceptionHandler.wrapException(e,"Error occured while removing a user");
        }
    }
    public void updateUser(User u) throws ListServiceException{
        try {
              updatedRow = em.createNamedQuery("updateUser")
                          .setParameter(1,u.getUserId())
                          .setParameter(2,u.getUserRole())
                          .setParameter(3,u.getCellPhone())
                          .setParameter(4,u.getCompany())
                          .setParameter(5,u.getDateOfBirth())
                          .setParameter(6,u.getFirstName())
                          .setParameter(7,u.getLastName())
                          .setParameter(8,u.getOfficePhone())
                          .setParameter(9,u.getId())
                          .executeUpdate();
        } catch (Exception e) {
            throw ExceptionHandler.wrapException(e,"Error occured while updating user");
        }
    }
   public User getUser(Long id) throws ListServiceException{
        User user;
        try {
               user = em.find(User.class,id);
        } catch (Exception e) {
            throw ExceptionHandler.wrapException(e,"Error occured in"+className+".getuser()");
        }
        return user;
   }
}

这是更新 JSF 页面处理日期列的相关部分

<h:column>
           <f:facet name="header">#{bundle.loginmanagementdob}</f:facet>
           <h:inputText 
                   p:type="date"
                   value = "#{l.dateOfBirth}"
                   size ="15" rendered = "#{l.canUpdate}" >
                   <f:convertDateTime type="date"
                         pattern = "yyyy-mm-dd" />
          </h:inputText>
          <h:outputText value = "#{l.dateOfBirth}"
                  rendered = "#{not l.canUpdate}" >
                  <f:convertDateTime 
                          type="date"
                          pattern = "yyyy-mm-dd" />
          </h:outputText>
 </h:column>
 <h:column>
         <f:facet name = "header">Update</f:facet>
                <h:commandLink value = "Update" 
                             disabled="#{login.currentUser.userRole == 'delete' or login.currentUser.userRole == 'consumer'}"
                             action = "#{loginManagment.updateLinkAction(l)}" 
                                           rendered = "#{not l.canUpdate}">
                            </h:commandLink>
  </h:column>
<f:facet name="footer">
                <h:panelGroup style="display: block; border-color: aquamarine;text-align: center;">
                            <h:commandButton id="update"
                                             tabindex="1"
                                             value="Save updates"
                                             action="#{loginManagment.saveUpdate}" />
                </h:panelGroup>
</f:facet>

这是 JSF 页面的托管 bean:

@Named
@SessionScoped
public class LoginManagment implements Serializable {

    private static final long serialVersionUID = 1009L;
    
    private LoginRequestSessionBean request;
    private final ResourceBundle bundle; //application resource bundle
    public LoginManagment() {
        //Get the application's resource bundle
        bundle = ResourceBundle.getBundle("webmessages");
    }
    public List<User> getUsers() {
        if ((users == null) || refresh) {
            try {
                users = request.getUsers();
            } catch (EJBException e) {
                FacesMessage errMsg = new FacesMessage(e.getMessage());
                FacesContext.getCurrentInstance().addMessage(null,errMsg);
            }
            refresh = false;
        }

        return users;
    }

    public void resetUpdateLink() {
        users
                .stream()
                .filter(e -> e.getCanUpdate() == true)
                .forEach(e -> e.setCanUpdate(false));
    }

    public String updateLinkAction(User u) {
        u.setCanUpdate(true);
        return null;
    }

    public String saveUpdate() {
        
        Function<User,User> update = n -> {
            request.updateUser(n);
            return n;
        };
        try {
            users
                    .stream()
                    .filter(e -> e.getCanUpdate() == true)
                    .forEach(update);
            resetUpdateLink();
            FacesMessage msg = new FacesMessage(bundle.getString("loginmanagementupdatesuccess"));
            FacesContext.getCurrentInstance().addMessage(null,msg);
        } catch (ListServiceException e) {
            FacesMessage errMsg = new FacesMessage(e.getMessage());
            FacesContext.getCurrentInstance().addMessage(null,errMsg);
        }
        logger.exiting(className,"saveUpdate()");
        return null;
    }
}

这是处理日期字段的添加用户 JSF 页面的相关部分:

  <h:outputLabel id="adddoblabel"
              for="adduserdob"
              style="color: green; font: caption; font-size: large;
              font-family: cursive; border-color: aquamarine"
              value="#{bundle.adduserdob}" />

 <h:inputText id="adduserdob"
              p:type="date"
              label="Date Of Birth "
              title="Date Of Birth"
              style="border-color: aquamarine"
              value="#{addUser.dateOfBirth}"
              required="true"
              requiredMessage="#{bundle.adduserdoberror}"
              maxlength="30" >
                                 
              <f:convertDateTime type="date"
                     pattern = "yyyy-mm-dd" />
 </h:inputText>
 <f:facet name="footer">
           <h:panelGroup style="display: block; border-color: aquamarine;text-align: center;">
                      <h:commandButton id="addusercommandbutton"
                                 value="Add"
                                 immediate="false"
                                 style="font-size: large; font-family: cursive"
                                 action="#{addUser.addAction}">
                       </h:commandButton>
                       
           </h:panelGroup>
</f:facet>
</h:panelGrid>

这是 JSF 添加用户页面的托管 bean:

@Named
@SessionScoped
public class AddUser implements Serializable {

    private static final long serialVersionUID = 1100L;
    private String firstName;
    private String lastName;
    private Date dateOfBirth;
    @EJB
    private LoginRequestSessionBean request;
    private ResourceBundle bundle; //application resource bundle
    public AddUser() {
        bundle = ResourceBundle.getBundle("webmessages");
    }

    public Date getDateOfBirth() {
        return dateOfBirth;
    }
    public void setDateOfBirth(Date date){
        dateOfBirth=date;
    }
    private void clearDataField() {
        this.password = null;
        this.userId = null;
        this.role = null;
        this.cellPhone = null;
        this.officePhone = null;
        this.company = null;
        this.dateOfBirth = null;
        this.firstName = null;
        this.lastName = null;
    }

    public void addAction() {
        try {
            User u = new User(getUserId(),getPassword(),getRole(),getFirstName(),getLastName(),getDateOfBirth(),getOfficePhone(),getCellPhone(),getCompany());
            request.addUser(u);
            clearDataField();
            FacesMessage successMsg = new FacesMessage(bundle.getString("addusersuccess"));
            FacesContext.getCurrentInstance().addMessage(null,successMsg);
        } catch (EJBException e) {
            FacesMessage successMsg = new FacesMessage(e.getMessage());
            FacesContext.getCurrentInstance().addMessage(null,successMsg);
        }
    }    
}

解决方法

这是因为您已将日期转换器配置为将连字符之间的部分解释为分钟。

<f:convertDateTime type="date" pattern="yyyy-mm-dd" />

根据 its documentation,模式符号在 java.text.SimpleDateFormat 的文档中指定。此文档says您应该使用 M 数月。

日期或时间组件 介绍 示例
M 月份(上下文敏感) 七月;七月; 07
一小时一分钟 数量 30

因此,相应地调整模式:

<f:convertDateTime type="date" pattern="yyyy-MM-dd" />

与具体问题无关:指定 type 属性时忽略 pattern 属性。以下声明同样适用。

<f:convertDateTime pattern="yyyy-MM-dd" />

这也在 its documentation 中指定。

如果指定了 pattern,其语法必须符合 java.text.SimpleDateFormat 指定的规则。这样的模式将用于解析,typedateStyletimeStyle 属性将被忽略。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-