发表于: 2018-04-01 23:52:04
1 625
今天完成的事情:
任务1.17
完成了上次留下的任务,把JDBC连接数据库的增删改查写了一遍,把JdbcTemplate连接数据库的增删改查写了一遍,把mybatis连接数据库的增删改查写了一遍。
使用mybatis时为什么不用写实现类,因为mybatis使用了Java的动态代理在运行期创建代理实现类。其实如果直接使用sqlSession根据xml的id查询,接口都不用写,接口也只是对xml配置的一个映射,使用接口的优点是不用在Java代码里以字符串方式引用xml的id了,安全性提高,毕竟手写容易出错,而且可以使用IDE的代码补全功能查看方法了。
明天计划的事情:
任务1.18-1.21,Junit测试以前用过,应该不会费太多时间,spring又是一个大块,打算先不深入研究,复习个大概,先任务优先。
遇到的问题:
1、spring配置文件引入包含数据库连接信息的properties文件时,因为还没复习spring,就想当然的使用了import命令,结果显然无法解析。
- 需要使用<context:property-placeholder location="db.properties" />组件来引用。或者还有配置相关bean的方法。
- 2、spring配置数据库信息中的用户名和密码使用${}方式获取properties文件的值总是报错,我的密码是空的,然后不使用${}获取密码了,用户名也报错,控制台输出信息显示用户名是乱码。开始我以为是编码问题,但properties里也没有中文,而且改了编码也不行,再说jdbc和url都能正常获取。后来发现properties中的属性都换成jdbc.username这种格式就正常了。看来它获取的是另一个username变量值?又查了查才知道,原来它默认获取的是本计算机的用户名。而我的计算机用户名是中文的,乱码了才没想到这个。而我计算机的密码它也获取不到。想要获取properties文件中的username和password,需要设置system-properties-mode属性,如下:
- <context:property-placeholder location="db.properties" system-properties-mode="FALLBACK"/>
- 或者把变量名设置成不冲突的。
- 收获:
- 一、关于JDBC:
- 任务里虽然没有用JDBC,但JdbcTemplate以及mybatis等连接数据库的工具都是对JDBC的封装,所以总结了一下。
- JDBC连接数据库的步骤(以mysql为例):
- 1、加入JDBC驱动jar包
- 2、注册驱动:Class.forName(com.mysql.jdbc.Driver);
- 3、获取连接:Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/dbname", "root", "password");
- 4、执行查询:
- Statement statement = connection.createStatement();
String sql = "select * from student";
ResultSet resultSet = statement.executeQuery(sql); - 5、处理结果:
- while(resultSet.next()){
int id = resultSet.getInt("id");
String name = resultSet.getString("name")
System.out.println("ID:" + id + " Name:" + name);
} - 6、关闭资源:
- resultSet.close();
statement.close();
connection.close(); - 如果没使用连接池的话,只关闭connection就可以了。另外这里面主要用到的接口都在rt.jar的ava.sql包里。
- 写了写JDBC,再去用其它的框架如JdbcTemplate等,就能感觉到它们的好处了,上面的代码大部分可以省了。对比如下:
- 二、关于JdbcTemplate
- JdbcTemplate的使用也很简单,主要是要配置好。三种配置方式:
- 1.在DAO实现类中注入一个外部DataSource引用(spring的XML文件配置),然后自己实例化JdbcTemplate,如:
- private static JdbcTemplate jdbcTemplate;
- public void setDataSource(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource) - }
- 2.在Spring的IoC容器中配置一个JdbcTemplate的bean,将DataSource注入进来,然后再把JdbcTemplate注入到自定义DAO中。
- 就是把JdbcTemplate的创建工具交给spring框架了,和其它xml文件里配置的bean一样。
- 3.继承JdbcDaoSupport类,注入DataSource。(JdbcDaoSupport类中有DataSource和JdbcTemplate属性)
- JdbcTemplate的使用之前也总结过API了,或者用到时查API就可以。
- 三、关于mybatis
- 这两天看的最多的还是mybatis,MyBatis是一款优秀的持久层框架,它支持定制化SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的JDBC。
- 另外提一下ORM,百度:
- 对象关系映射(英语:(Object Relational Mapping,简称ORM,或O/RM,或O/R mapping),是一种程序技术,用于实现面向对象编程语言里不同类型系统的数据之间的转换。从效果上说,它其实是创建了一个可在编程语言里使用的--“虚拟对象数据库”。
- 面向对象是从软件工程基本原则(如耦合、聚合、封装)的基础上发展起来的,而关系数据库则是从数学理论发展而来的,两套理论存在显著的区别。为了解决这个不匹配的现象,对象关系映射技术应运而生。
- hibernate是ORM框架,mybatis算不上完全的ORM框架,mybaits可以把数据库的表数据直接映射到Java对象里,但是却不能通过Java对象直接操作数据库表,还是要手写sql语句。
- 所以有人说mybatis是半自动ORM框架,有人说不是ORM,只是用xml标记然后用java查找占位符,说白了就是给你在java和sql之间提供更灵活的映射方案。
- 自己的感觉,这些框架的出现和发展,不管是ORM等持久层框架,还是spring,struts,springmvc等别的框架,都是由需求推动的。这些需求包括面向对象的思想、减少开发代码量、业务层数据层等各层的解耦合、提升性能、安全性等等。
- 使用这些框架有很多优点,如程序员不需要去关注太多底层的或者与业务无关的内容,从而专注在业务逻辑代码上。但优点也是缺点,比如本来一句SQL能搞定的事,用了mybatis或者hibernate之类的,还要花大量时间学习框架的内容,说是为了简化,有时却变得更麻烦了。
- 而且框架对逻辑进行了各种封装,出了问题就懵了,你还要花时间深入研究框架,看源码?不知道多少新框架又出来了,没等你学熟练这框架也许就淘汰了。
- 也许从公司的角度看,使用框架能减少很多成本,毕竟现在这么多培训出来的,谁都会几个热门框架,处理简单的业务也足够用了,而且大多数人对技术并不是真的热爱,会使几个框架能干活就得了,也不用考虑太多。但如果是对技术有追求的初级程序员,该深入学什么不该学什么,还是应该好好思考下的,毕竟现在技术更迭这么快,要有长远的眼光和知识架构的方向。
- 当然用不用框架,分不分层什么的之类的问题,也不是你来决定的,现阶段还是好好学习,不用思考太多。等工作个几年经验丰富了,自然会有更深的理解。其实是看完mybatis手册后觉得,很多东西似乎还是弄得挺复杂的,貌似hibernate更复杂,感觉持久层框架以后还会有很多改善吧。就像现在别的什么层不是又出了个springboot什么的,据说用起来很简单。总之一切都在发展之中。
- mybaits也要配置,有一个主要的配置文件,元素如下:
- properties是引入属性文件,也可以自己定义属性。environments是配置数据源(和事务)的,类型别名什么的用一次就明白了。其它的属性可以先不用深入了解,最关键的是mappers映射器。mapper映射器是写sql语句的xml文件,这里只是要把所有mapper.xml引入进来。
- mapper映射器中定义了sql语句,并能把查询结果映射到java的实体类中,这个是mybatis比较核心的功能。映射器xml文件的元素如下:
- 看起来挺简单的,不过每个元素标签下都会有许多的子标签可选。最重要最强大的是resultMap元素,它定义了如何把数据库查询的结果集映射到Java对象里。
- 当然很多简单的情况,根本不需要定义resultMap,像返回结果是一个Student类这种,mybatis会在幕后自动创建一个resultMap帮你映射。但是比较复杂的情况就需要了,像有表关联的,一对多、多对一、多对多什么的,对于这种情况,mybatis的resultMap里主要使用了collection和association元素来解决,看起来很复杂,其实熟悉一下逻辑还是挺简单的。不过表关联的内容官方文档写的感觉不如其它教程简单。关联查询暂时还没有用到,就不深入讨论了。
- 官方文档中文版:http://www.mybatis.org/mybatis-3/zh/index.html
- 其它教程:https://www.yiibai.com/mybatis/
- mybatis在获取了sqlSession后,有两种执行sql的方法,一种是直接使用sqlSession的API:
- Student s = sqlSession.selectOne("jnshu.mapper.StudentMapper.selectById", 1); //直接根据xml映射器中定义的id去查找sql然后执行
- 另一种是编写一个与xml映射器对应的Java接口,然后调用接口的方法:
- StudentMapper sm = session.getMapper(StudentMapper.class);
- Student s = sm.selectById(1);
- 接口中的方法名对应xml中的id,参数类型对应xml中的paramType,返回类型对应xml中的resultType或者resultMap。
- mybatis会根据接口的方法来找到xml映射器中定义的sql来执行,比第一种方法多了一个中间步骤。
- 第一种方法,由于是直接根据映射器id查sql执行,所以映射器xml中的namespace属性没有特别要求,只要唯一就好。但是第二种方法,由于是通过接口的方法来执行sql,所以namespace必须和接口全路径相同,不然无法通过方法名找到对应的映射器和语句。
- 当然这种绑定其实在程序运行时就已经做好了。mybatis会解析xml文件,检查namespace指定的接口类是否存在,存在的话,该接口和命名空间就会绑定。然后在方法调用的时候才能动态代理生成接口的实现类。如果namespace没有和接口绑定,则调用的时候无法生成接口的实现类。
- 所以用第二种方式的话namespace一定要指定对应接口的路径就好了。
- 最后再总结一下mybatis传入参数的问题吧。
- parameterType 将会传入这条语句的参数类的完全限定名或别名。这个属性是可选的,因为 MyBatis 可以通过 TypeHandler 推断出具体传入语句的参数,默认值为 unset。
- 所以大多时候parameterType参数都是可以省略的。如果是单一的参数,获取方法有:
基本数据类型:#{参数} 获取参数中的值
复杂数据类型:#{属性名} ,map中则是#{key}
举例:
这两个中的parameterType参数都是可以不写的,也能成功执行。
如果是多个参数,那parameterType想写也没法写了,可以有几种方法传参:
1、用#{index}序号的方式接收参数:
2、用注解的方式指定参数的名字:
3、把参数封装成map或者list等,不再细说。
任务1.17算结束了,弄了好几天,花时间最长的主要是系统的浏览了一下mybatis手册,另外鼓捣了一下编码的问题。明天开始1.18任务。
评论