【手把手】JavaWeb 入门级项目实战 -- 文章发布系统 (第六节)

本文介绍了如何在Java中使用queryForMap和queryForBean方法进行数据库查询,将查询结果转化为Map和JavaBean对象,展示了反射API和泛型在处理单条数据映射中的应用。
摘要由CSDN通过智能技术生成

[{id=24cb5136-39cf-4109-a28b-d412efd6ad2d, sex=0, headerPic=null, username=赵六, update_time=2016-10-05 13:01:33.0, address=保密, email=null, create_time=2016-10-05 00:00:00.0, is_delete=0, telephone=保密, password=123456}, {id=319600c3-550a-4f9f-80cf-deebe2376528, sex=0, headerPic=null, username=张三, update_time=2016-10-04 22:52:01.0, address=保密, email=null, create_time=2016-10-04 00:00:00.0, is_delete=0, telephone=保密, password=123456}, {id=3fe31336-a792-488f-9445-f3ebd30f9de3, sex=0, headerPic=null, username=王五, update_time=2016-10-05 13:01:33.0, address=保密, email=null, create_time=2016-10-05 00:00:00.0, is_delete=0, telephone=保密, password=123456}, {id=5830e229-06d5-463c-b17d-639977f7c60c, sex=0, headerPic=null, username=李四, update_time=2016-10-05 13:01:33.0, address=保密, email=null, create_time=2016-10-05 00:00:00.0, is_delete=0, telephone=保密, password=123456}]

成功了。

09 查询方法:queryForMap 实现

这个方法的作用是查询出一条数据,因为一个HashMap实际上就对应数据库表的一行数据。刚才,我们已经实现了queryForList方法,所以,现在只需要稍微调用一下,queryForMap 方法就出来了。

思路就是我先查出一个list,然后取第一条就OK了。

代码:

/**

  • 查询出数据,并且map返回

  • @param sql

  • @param objects

  • @return

  • @throws SQLException

*/

public static Map<String,Object> queryForMap(String sql,Object…objects) throws SQLException{

Map<String,Object> result = new HashMap<String,Object>();

List<Map<String,Object>> list = queryForList(sql, objects);

if(list.size() != 1){

return null;

}

result = list.get(0);

return result;

}

测试,查询所有的数据:

DataBaseUtils.config(“jdbc.properties”);

Map map = DataBaseUtils.queryForMap(“select * from t_user”);

System.out.println(map);

运行结果为 null

因为查询出来的不止一条数据,所以返回了null。

现在我们就查一条数据

DataBaseUtils.config(“jdbc.properties”);

Map map = DataBaseUtils.queryForMap(“select * from t_user where username = ?”,“王五”);

System.out.println(map);

运行结果:

{id=3fe31336-a792-488f-9445-f3ebd30f9de3, sex=0, headerPic=null, username=王五, update_time=2016-10-05 13:01:33.0, address=保密, email=null, create_time=2016-10-05 00:00:00.0, is_delete=0, telephone=保密, password=123456}

这样就对了。

10 查询方法:queryForBean 实现

终于到queryForBean了,这个方法的意思就是说,将查询出来的一条数据(注意,只能是一条数据)转换成JavaBean,也就是一个Java对象。

比如,我从t_user表中查一条数据出来,然后它就能给我返回一个User对象。很显然,这个方法肯定需要用到Java的反射API和泛型。

因为我们之前已经写好了queryForMap,所以在这个方法中,可以直接调用那个方法,这样省去了很多的工作量。

大体的思路就是:

1.拿到map。

2.新建一个JavaBean,因为事先不知道JavaBean的类型,所以要传进来一个class属性,然后方法的返回值需要用到泛型,不然没法new。

3.遍历map中所有的key,想办法获取对应的set方法。(注意,你的JavaBean必须要符合Bean规范,否则会有问题的)

4.通过反射来调用set方法。

5. 返回已经注入好的JavaBean。

这个方法呢,我大概写了2个小时,因为实在没有写过类似的代码,只能自己在那一点点摸索。

代码的话呢,肯定还有不足的地方,我大概测试了一下,不论怎么样,差不多可以用。

OK,上代码:

/**

  • 查询出数据,并且返回一个JavaBean

  • @param sql

  • @param clazz

  • @param objects

  • @return

  • @throws NoSuchFieldException

  • @throws SecurityException

*/

public static T queryForBean(String sql,Class clazz,Object…objects){

T obj = null;

Map<String,Object> map = null;

Field field = null;

try {

obj = (T) clazz.newInstance(); //创建一个新的Bean实例

map = queryForMap(sql, objects); //先将结果集放在一个Map中

} catch (InstantiationException | IllegalAccessException e) {

e.printStackTrace();

} catch (SQLException e) {

e.printStackTrace();

}

if(map == null){

return null;

}

//遍历Map

for (String columnName : map.keySet()) {

Method method = null;

String propertyName = StringUtils.columnToProperty(columnName); //属性名称

try {

field = clazz.getDeclaredField(propertyName);

} catch (NoSuchFieldException e1) {

e1.printStackTrace();

} catch (SecurityException e1) {

e1.printStackTrace();

}

//获取JavaBean中的字段

String fieldType = field.toString().split(" ")[1]; //获取该字段的类型

//System.out.println(fieldType);

Object value = map.get(columnName);

if(value == null){

continue;

}

/*获取set方法的名字 */

String setMethodName = “set” + StringUtils.upperCaseFirstCharacter(propertyName);

//System.out.println(setMethodName);

try {

/*获取值的类型 */

String valueType = value.getClass().getName();

/*查看类型是否匹配 */

if(!fieldType.equalsIgnoreCase(valueType)){

//System.out.println(“类型不匹配”);

if(fieldType.equalsIgnoreCase(“java.lang.Integer”)){

value = Integer.parseInt(String.valueOf(value));

}else if(fieldType.equalsIgnoreCase(“java.lang.String”)){

value = String.valueOf(value);

}else if(fieldType.equalsIgnoreCase(“java.util.Date”)){

valueType = “java.util.Date”;

//将value转换成java.util.Date

String dateStr = String.valueOf(value);

Timestamp ts = Timestamp.valueOf(dateStr);

Date date = new Date(ts.getTime());

value = date;

}

}

/*获取set方法 */

//System.out.println(valueType);

method = clazz.getDeclaredMethod(setMethodName,Class.forName(fieldType));

/*执行set方法 */

method.invoke(obj, value);

}catch(Exception e){

e.printStackTrace();

/*如果报错,基本上是因为类型不匹配 */

}

}

//System.out.println(obj);

return obj;

}

这段代码涉及到两个方法,我这边也分享出来吧,我已经把它们放在StringUtils里面了。如果你自己也打算写类似的小框架的话呢,这两个方法很可能会被用到。

Paste_Image.png

/**

  • 把数据库字段名改为驼峰方式

  • @param column

  • @return

*/

public static String columnToProperty(String column) {

/*如果字段名为空,就返回空字符串 */

if(isEmpty(column)) return “”;

/*获取字段的长度,一般来说字段长度不可能有几百个字节的,所以用Byte就行了 */

Byte length = (byte) column.length();

StringBuilder sb = new StringBuilder(length);

int i = 0;

/*遍历字段的每一个字符 */

for (int j = 0; j < length; j++) {

/*匹配到第一个_ */

if (column.charAt(j) == ‘_’) {

/*如果后面还有_,也就是连续的_,那么j就需要自增一个单位,直到后面不是_为止 */

while (column.charAt(j + 1) == ‘_’) {

j += 1;

}

sb.append((“” + column.charAt(++j)).toUpperCase());

} else {

/*如果循环到的字符不是_,那么就保存下来 */

sb.append(column.charAt(j));

}

}

return sb.toString();

}

/**

  • 将一个字符串的首字母改成大写

  • @param str

  • @return

*/

public static String upperCaseFirstCharacter(String str){

StringBuilder sb = new StringBuilder();

char[] arr = str.toCharArray();

for (int i = 0; i < arr.length; i++) {

if(i==0) sb.append((arr[i] + “”).toUpperCase());

else sb.append((arr[i]+“”));

}

return sb.toString();

}

测试

User user = DataBaseUtils.queryForBean(“select * from t_user limit 1”, User.class);

System.out.println(user);

结果(我已经给User类改写了toString方法):

User [id=24cb5136-39cf-4109-a28b-d412efd6ad2d, username=赵六, password=123456, headerPic=null, email=null, sex=0, createTime=2016-10-05 00:00:00.0, updateTime=2016-10-05 13:01:33.0, isDelete=0, address=保密, telephone=保密]

那么,好的,我们的DataBaseUtils暂时告一段落了。虽然还不完善,可是已经有了一个雏形了。所以,写代码不要怕,只要有时间,你肯定能写出来,最多就是不完善罢了。你也可以利用网络上的资源,有些东西慢慢琢磨,基本上都是可以弄出来的。很多初学者最大的问题就是不敢去尝试,仅此而已。

接下来,我们继续写业务。

11 从controller层到service层

为了方便起见,我们就写到Service就OK了,省去dao层。反正我经历的几个公司都是这么做的,他们似乎都有意弱化了dao层,直接写到service层就结束了。

我们继续编写controller的代码,因为要调用service的方法,所以,我们需要把必要的包导入进来。

<%@ page language=“java” import=“java.util.,service.LoginService,util.StringUtils,bean.” pageEncoding=“UTF-8”%>

controller代码

<%

//获取客户端传递过来参数

String username = request.getParameter(“username”);

String password = request.getParameter(“password”);

//System.out.println(username);

//System.out.println(password);

//如果用户名和密码不为空

if(StringUtils.isEmpty(username) || StringUtils.isEmpty(password)){

out.print(“-1”);//错误码-1 : 用户名和密码不能为空!

}else{

//初始化LoginService

LoginService loginService = new LoginService();

//接下来判断用户名是否存在

User user = loginService.getUser(username);

if(user == null){

out.print(“-2”);//错误码-2 : 用户名不存在!

}else

//如果用户名存在,那么验证用户名和密码是否匹配

if(!username.equals(user.getUsername()) || !password.equals(user.getPassword())){

out.print(“-3”);//错误码-3 : 用户名或密码错误!

}else{

//如果能到这一步,就说明用户的确存在,而且账号密码也正确。那么就把user放在session中

out.print(“1”);

session.setAttribute(“user”, user);

session.setAttribute(“username”, user.getUsername());

}

}

%>

流程是这样的,首先判断用户名和密码是否为空,如果为空,就直接返回一个错误码-1,接下来依次判断用户名是否存在,以及用户名密码是否都正确。

只要有一个不符合,就直接返回对应的错误码。out对象是JSP九大隐式对象的一员,可以将某个值返回给前台。

然后,如果账号密码都正确,那么就返回一个1,表示登录成功,同时,把user对象和用户名放到session中。

session的话,就是浏览器作用域,只要你浏览器开着,里面的值就存在着。浏览器一关,存在session中的东西就没了。当然,你也可以自己设定session失效的时间。

你可以把session想象成一个篮子。篮子嘛,肯定是用来放东西的,就这么简单。

service类:

Paste_Image.png

代码

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

Docker步步实践

目录文档:

①Docker简介

②基本概念

③安装Docker

④使用镜像:

⑤操作容器:

⑥访问仓库:

⑦数据管理:

⑧使用网络:

⑨高级网络配置:

⑩安全:

⑪底层实现:

⑫其他项目:

《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》点击传送门即可获取!
②基本概念

③安装Docker

[外链图片转存中…(img-m2MOMsYU-1712259358131)]

④使用镜像:

[外链图片转存中…(img-UzlT1l5q-1712259358131)]

⑤操作容器:

[外链图片转存中…(img-1H5P89BP-1712259358131)]

⑥访问仓库:

[外链图片转存中…(img-ZFvLPKaY-1712259358131)]

⑦数据管理:

[外链图片转存中…(img-5HrLlJzm-1712259358132)]

⑧使用网络:

[外链图片转存中…(img-jIcYnd6e-1712259358132)]

⑨高级网络配置:

[外链图片转存中…(img-ObGuOLak-1712259358132)]

⑩安全:

[外链图片转存中…(img-2hoAGrcn-1712259358132)]

⑪底层实现:

[外链图片转存中…(img-y2H6xGgM-1712259358133)]

⑫其他项目:

[外链图片转存中…(img-DvuEAkhb-1712259358133)]

《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》点击传送门即可获取!

  • 12
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值