Java:String转换为java.sql.Timestamp

本文详细介绍了在Java中如何将String类型转换为java.sql.Timestamp类型,包括使用SimpleDateFormat进行日期解析,以及如何通过反射机制处理基本类型和其封装类之间的转换。

Java:String转换为java.sql.Timestamp

1.JPA映射Mysql的timestamp类型应使用java.sql.Timestamp

mysql中的timestamp类型最大长度为6,如果JPA设置的长度大于6,程序执行时控制台输出有建表提示,但是在数据库中表并没有创建成功,调试状态下能看到报错的信息。
实体类中Timestamp属性定义如下:

@Column(columnDefinition = "timestamp(6)")
private Timestamp ts;

2.String类型转换为java.sql.Timestamp

首先将String转换为java.util.Date,使用unmarshal方法。如下:

public class DateAdapter extends XmlAdapter<String,Date> {
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
    
    @Override
    public Date unmarshal(String v) throws Exception {
        if (!v.contains(".")){
            v+=".000";
        }
        return sdf.parse(v);
    }
    
    @Override   
    public String marshal(Date v) throws Exception {
    return sdf.format(v);
}

然后再将java.util.Date转换为java.sql.Timestamp,如下:

Java.util.Date dateTime = DateAdapter.unmarshal(String v);	
Timestamp timestamp = new Timestamp(dateTime.getTime());

详细的JAVA中java.util.Date、java.sql.Timestamp和String之间的互相转换参考了:
https://www.cnblogs.com/zhang-yan/p/7733005.html

3. java其他类型和String类型的相互转换

有时候,为了使用类的反射机制,我们把类的属性类型定义为基本封装类,如基本数据类型的int对应的封装类为Integer。
Java 八种基本类型和基本类型封装类 参考https://www.cnblogs.com/alternative/p/7520332.html
java中String类型和基本类型的转换,以及toString的用法 参考https://blog.youkuaiyun.com/Handsome2013/article/details/80700637

<think>我们遇到了一个Java类型转换异常:试图将java.util.Date对象强制转换java.sql.Timestamp类型。这是因为Date和Timestamp虽然都是表示日期时间,但在Java中是不同的类,且没有直接的继承关系(尽管Timestamp继承自java.util.Date,但在JDBC和SQL处理中,它们是不同的)。具体错误信息指出:在ArticleServlet.java的第41行,尝试将java.util.Date对象转换java.sql.Timestamp。通常,这种情况发生在从数据库读取数据或向数据库写入数据时,ORM框架或我们自己的代码尝试进行类型转换。解决方案:1.不要强制转换,而是通过构造方法或转换方法将java.util.Date转换java.sql.Timestamp。2.如果是从数据库读取数据,确保在ResultSet中使用了正确的getTimestamp方法。3.如果是向数据库写入数据,应该使用PreparedStatement的setTimestamp方法,并传入java.sql.Timestamp对象。假设我们在ArticleServlet.java的第41行附近有类似这样的代码:Timestamptimestamp=(Timestamp)someDateObject;修改方案:我们可以使用以下两种方式之一进行转换:方式1:使用Timestamp的构造方法(因为Timestampjava.util.Date的子类,所以可以用Date对象初始化)Timestamptimestamp=newTimestamp(someDateObject.getTime());方式2:如果someDateObject实际上是一个java.sql.Date或其他类型,我们需要先确保它是java.util.Date,然后同样使用上面的方法。但是,需要注意的是,错误中提示的是将java.util.Date转换java.sql.Timestamp,所以这里我们直接使用构造方法即可。另外,还有一种情况是我们在使用ORM(如Hibernate)时,实体类中可能错误地使用了java.util.Date类型,而数据库中对应的是timestamp类型的字段。在Hibernate中,我们可以使用@Temporal注解来指定日期类型,但如果是直接操作,我们需要确保使用正确的类型。我们来看一个具体的代码示例:原始有问题的代码(ArticleServlet.java:41行可能类似):java.util.DateutilDate=...//从某处获取的java.util.Date对象TimestampsqlTimestamp=(Timestamp)utilDate;//这里会抛出ClassCastException修改后的代码:java.util.DateutilDate=...;TimestampsqlTimestamp=newTimestamp(utilDate.getTime());这样就不会有类型转换异常了。另外,如果是在从ResultSet中获取数据,我们应该使用:Timestamptimestamp=resultSet.getTimestamp("column_name");而不要使用getDate,因为getDate返回的是java.sql.Date。如果是向PreparedStatement中设置参数,我们应该:preparedStatement.setTimestamp(1,newTimestamp(utilDate.getTime()));下面我们给出一个修改后的Servlet代码片段示例:假设原Servlet的第41行是:TimestampcreateTime=(Timestamp)request.getAttribute("create_time");但我们知道request.getAttribute返回的是Object类型,如果我们之前放入了一个java.util.Date对象,那么强制转换就会出错。修改为:java.util.DatecreateTimeUtil=(java.util.Date)request.getAttribute("create_time");TimestampcreateTime=newTimestamp(createTimeUtil.getTime());或者,如果我们不能确定返回的类型(可能是Date也可能是Timestamp),我们可以这样写:Objectobj=request.getAttribute("create_time");TimestampcreateTime=null;if(objinstanceofjava.util.Date){createTime=newTimestamp(((java.util.Date)obj).getTime());}elseif(objinstanceofTimestamp){createTime=(Timestamp)obj;}但是更推荐的做法是统一使用java.util.Date来获取时间,然后在需要java.sql.Timestamp的地方使用上述的转换。最后,我们还需要检查整个数据流中,哪里放入了java.util.Date对象,而后续却期望使用java.sql.Timestamp?如果可以,最好在数据存入请求属性时就转换为正确的类型。例如,在设置request属性之前,如果我们从实体对象中获取了一个java.util.Date,我们应该立即转换java.sql.Timestamp(如果确实需要这个类型的话)或者直接使用java.util.Date,然后在需要时再转换(通常我们不建议在Servlet中混合使用这两种类型)。因为异常发生在ArticleServlet的第41行,所以我们需要具体定位到那行代码,然后按上述方法修改。注意:java.sql.Timestamp包含纳秒精度,而java.util.Date只到毫秒。如果我们需要纳秒精度,必须使用Timestamp,但转换过程中只能得到毫秒精度(因为Date只有毫秒)。如果数据库字段要求更高精度,我们需要从其他途径获取(比如直接从数据库获取当前时间戳)。总结:不要直接强制转换,而是通过getTime()方法获取毫秒数然后构建Timestamp对象。示例代码修改:原始有问题的代码行(ArticleServlet.java:41)可能是:TimestampcreateTime=(Timestamp)article.getCreateTime();如果article.getCreateTime()返回的是java.util.Date,则修改为:TimestampcreateTime=newTimestamp(article.getCreateTime().getTime());但是,请注意,如果article.getCreateTime()返回的已经是Timestamp,则不需要转换。因此更好的做法是在实体类中直接使用Timestamp类型,或者在getCreateTime方法中返回Timestamp类型(如果底层是Timestamp的话)。如果实体类中使用了java.util.Date,而数据库对应的是timestamp字段,那么使用Hibernate时,我们可以用:@Column(name="create_time")@Temporal(TemporalType.TIMESTAMP)privateDatecreateTime;这样,从数据库取出时,createTime属性会被填充为java.util.Date(实际上是java.sql.Timestamp,因为Timestamp是Date的子类,所以可以被赋值给Date变量),所以这里不会出现类型转换问题。问题可能发生在将这个Date再转换Timestamp时。因此,我们在实体类中可以直接使用java.util.Date,然后在需要Timestamp的地方按上述方法转换。所以,问题根源在于错误地进行了强制类型转换,解决方案是使用正确的转换方法。下面给出修改后的代码片段:原代码(ArticleServlet.java:41行附近)://假设原始41行是这样的:TimestampcreateTime=(Timestamp)request.getAttribute("article_create_time");修改后:ObjectcreateTimeObj=request.getAttribute("article_create_time");TimestampcreateTime=null;if(createTimeObjinstanceofjava.util.Date){createTime=newTimestamp(((java.util.Date)createTimeObj).getTime());}elseif(createTimeObjinstanceofTimestamp){createTime=(Timestamp)createTimeObj;}else{//根据情况处理其他类型或错误}或者,如果我们确定这个属性一定是Date(包括Timestamp类型,可以简化为:DatecreateTimeDate=(Date)request.getAttribute("article_create_time");TimestampcreateTime=newTimestamp(createTimeDate.getTime());因为Timestamp是Date的子类,所以无论是java.util.Date还是java.sql.Timestamp都可以用getTime()获取毫秒数。但注意:java.sql.Date(也是java.util.Date的子类)表示日期(没有时间部分),而Timestamp有日期和时间(包括纳秒)。如果原始数据是java.sql.Date,那么转换Timestamp时会丢失时间部分?实际上不会,因为java.sql.Date的时、分、秒、毫秒都是0。所以转换时要根据业务需求考虑是否合适。以上便是解决该类型转换异常的方案。§§相关问题§§:1.Java中,java.util.Date、java.sql.Date和java.sql.Timestamp有什么区别?2.如何正确在Java实体类和数据库日期时间类型(如DATE、TIMESTAMP)之间进行映射?3.使用JDBC操作数据库时,处理日期时间有哪些最佳实践?4.Java8及以上版本中,使用新的日期时间API(如LocalDateTime)与数据库交互应该注意什么?</think> ### 解决 Java 类型转换异常:Date 无法强制转换Timestamp #### 问题分析 这个异常发生在尝试将 `java.util.Date` 对象强制转换为 `java.sql.Timestamp` 时。虽然 `Timestamp` 是 `Date` 的子类,但**直接强制转换是不安全的**,因为: - `java.util.Date` 表示日期和时间(精度到毫秒) - `java.sql.Timestamp` 扩展了 `Date`,增加了纳秒精度和特定于 SQL 的格式 - JDBC 要求特定的时间类型来处理数据库操作 #### 完整解决方案 ##### 1. 推荐方法:直接创建 Timestamp 对象 ```java // 错误示例(会导致异常): // Timestamp timestamp = (Timestamp) new Date(); // 正确做法:使用getTime()创建Timestamp java.util.Date utilDate = new Date(); java.sql.Timestamp sqlTimestamp = new Timestamp(utilDate.getTime()); ``` ##### 2. JDBC 操作中的安全转换 ```java // 从数据库读取时: try (ResultSet rs = statement.executeQuery()) { if (rs.next()) { // 使用getTimestamp()安全获取值 Timestamp dbTimestamp = rs.getTimestamp("create_time"); // 转换java.util.Date Date utilDate = new Date(dbTimestamp.getTime()); } } // 向数据库插入时: try (PreparedStatement ps = connection.prepareStatement( "INSERT INTO articles (title, content, created_at) VALUES (?, ?, ?)")) { ps.setString(1, "My Article"); ps.setString(2, "Article content"); // 正确设置Timestamp ps.setTimestamp(3, new Timestamp(new Date().getTime())); // 或者使用当前时间 // ps.setTimestamp(3, new Timestamp(System.currentTimeMillis())); ps.executeUpdate(); } ``` ##### 3. 实体类中的正确处理 ```java public class Article { private Long id; private String title; // 使用java.util.Date存储 private java.util.Date createdAt; // JDBC专用方法 public Timestamp getCreatedAtTimestamp() { return createdAt != null ? new Timestamp(createdAt.getTime()) : null; } // ORM设置方法 public void setCreatedAt(Timestamp timestamp) { this.createdAt = new Date(timestamp.getTime()); } } ``` ##### 4. Servlet 修复示例 (ArticleServlet.java) ```java public class ArticleServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) { // 获取参数 String title = request.getParameter("title"); String content = request.getParameter("content"); // 安全处理时间参数 java.util.Date utilDate = new Date(); // 当前时间 java.sql.Timestamp createTime = new Timestamp(utilDate.getTime()); // 创建文章对象 Article article = new Article(); article.setTitle(title); article.setContent(content); article.setCreatedAt(createTime); // 使用正确的Timestamp类型 // 保存到数据库 articleDao.save(article); } } ``` #### 核心注意事项 1. **不要直接强制转换**:`(Timestamp) dateObject` 总是危险的 2. **统一存储类型**:在实体类中统一使用 `java.util.Date` 3. **使用正确转换方法**: ```java // Date -> Timestamp Timestamp ts = new Timestamp(date.getTime()); // Timestamp -> Date Date date = new Date(timestamp.getTime()); ``` 4. **ORM 框架配置**:Hibernate/JPA 中的正确映射: ```java @Column(name = "created_at") @Temporal(TemporalType.TIMESTAMP) // 重要注解 private Date createdAt; ``` #### 不同类型转换参考表 | 方向 | 代码 | 使用场景 | |------|------|----------| | Date → Timestamp | `new Timestamp(date.getTime())` | 存入数据库 | | Timestamp → Date | `new Date(timestamp.getTime())` | 业务逻辑处理 | | 当前时间戳 | `new Timestamp(System.currentTimeMillis())` | 创建时间记录 | #### Java 8+ 最佳实践 使用 `java.time` API 避免此类问题: ```java import java.time.LocalDateTime; // 获取当前时间 LocalDateTime now = LocalDateTime.now(); // JDBC 4.2+ 支持直接设置 preparedStatement.setObject(1, now); // 从结果集获取 LocalDateTime dbTime = resultSet.getObject("column", LocalDateTime.class); ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值