因为是个人复习java的总结,所以结构稍显杂乱,有些语句过于口语化. 之前地时间在回顾前面基础内容和数据结构,原本想要整理,但是复习地太碎,整理失败。接下来开始ssm的学习,会慢慢整理内容。
其实就是一个面向数据操作的框架,其中封装了jdbc的相关操作,使用时只需要去关注sql语句本身。
相关环境的配置信息 参考https://mybatis.org/mybatis-3/zh/getting-started.html 包括之后xml文件需要的配置格式标准,在文档中也有
这里需要注意几个细节问题: 1. 操作类的类名问题上,在Mybatis中因为一个映射配置文件对应一个Mapper,所以命名上区分之前的Dao。实质上的内容是一致的,都是针对数据持久化操作的封装。 2. Mybatis映射配置文件的路径结构和dao接口保持一致。 3. 映射配置文件中mapper的namespace对应的值是接口的全限定类名。 4. 映射配置文件中的select中id取值对应接口中的方法名。
上面的配置达到的效果,其实就是配置了xml提供给Mybatis,然后就不用自己实现数据库操作的具体实现类方法。Mybatis会根据配置的内容去实现。仔细想想就是其中封装了获取数据库连接,执行sql语句的操作。而我们做的就是根据提供的配置格式,提供数据库连接必要信息,sql语句,方法名,返回类型等。
主配置中需要配置以下信息,目前暂且使用
<!-- Mybatis主配置文件 --> <configuration> <!--配置环境--> <environments default="mysql"> <!-- 配置mysql的环境 --> <environment id="mysql"> <!-- 配置事务类型 --> <transactionManager type="JDBC"></transactionManager> <!-- 配置数据源(连接池) --> <dataSource type="POOLED"> <!-- 配置连接数据库的基本信息 --> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql:///mybatis?characterEncoding=utf8"/> <property name="username" value="root"/> <property name="password" value="111"/> </dataSource> </environment> </environments> <!-- Mybatis映射文件配置文件,也就是每个类一个配置文件--> <mappers> <mapper resource="cjlu/cct/dao/PersonDao.xml"/> </mappers> </configuration>
Mapper中需要设置对应的类,对应的方法,对应的sql语句,以及数据映射类型
<mapper namespace="cjlu.cct.dao.PersonDao"> <select id="findAll" resultType="cjlu.cct.domain.Person"> select * from person </select> </mapper>实际操作的执行语句
//读取配置文件 InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml"); //创建SqlSessionFactory工厂 SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder(); SqlSessionFactory sessionFactory = builder.build(in); //通过工厂获取数据库连接中的session对象 SqlSession session = sessionFactory.openSession(); //使用session对象获取dao的代理对象 PersonDao personDao = session.getMapper(PersonDao.class); //使用代理对象执行具体方法 List<Person> all = personDao.findAll(); for (Person p : all) { System.out.println(p); } //返还session给数据库连接池 session.close(); //关闭输入流 in.close();其实从代码也可以看出来,使用方式和之前web为了dao方便设置的工具类的使用差不多。只是myBatis框架做了更好的封装,采用了工厂模式,代理模式等。另外使用xml来配置一些程序中的必要信息。之前自己写的工具类则是通过properties来设置,但是不规范,毕竟只有自己用。
上面xml的配置方式十分麻烦,其实Mybatis支持注解的配置方式,会稍微简便一点。
整体上看,首先Mybatis是获取配置文件的信息。这部分很好理解,就是为了之后的数据库连接读取必要的环境信息,以及映射文件的信息。这部分实质上就是读取文件,一般分为通过类加载器读取文件和ServletContext获取真实地址。上面的简单使用就是通过类加载器反射读取文件,实际和之前写JDBC的工具类思路差不多,使用Classloader和Properties。
接下来就是获取数据库session的工厂,也相当于之前数据库连接池的工厂。只是这里使用了建造者模式,通过builder来创建工厂。
然后是工厂类生成session对象,这里采用了工厂模式
再接下来就是使用代理模式,传入之前定义的未实现的操作接口类,然后在Mybatis中补充具体功能。使用getMapper方法,虽然没有看源码,但是也可以想到应该是关联接口方法和主配置文件中配置的映射文件信息,然后根据映射文件信息获取sql语句,返回对象之类的信息。主要就是为了在不修改源码的基础上,实现功能的扩展。
最后就是调用方法,获取返回对象,输出,关闭资源,没什么好理解的。
整体上获取xml中内容是通过dom4j解析,暂时先不细究获取数据这个过程。 首先为了获取数据库的连接,需要通过驱动属性,用户密码等信息,获取连接的Connection,因此最先配置的是主配置中的环境信息,其中主要是数据库的四个连接属性,通过这四个连接属性。
获取完Connection,就需要通过Connection对象进行预编译语句的输入。这时就需要主配置中关于映射配置文件的信息,获取到映射配置文件信息,主要是关于sql语句以及对应方法和返回类型的Mapper数据。然后就能获取对应的Statement,比如说预编译的PreparedStatement,获取到sql语句并传入。
然后就调用Statement执行sql语句,如果是预编译sql语句就在上面读取,如果是普通执行,就在这里调用对应的sql语句,然后获取结果。
得到结果集ResultSet之后就需要进行数据封装。封装的时候肯定遍历结果集,然后添加到对应的返回类型数据中去。这时候就使用到映射配置文件中的返回类型,通过反射获取具体的类型。因此这里设置的返回类型是全限定名的类型,方便查找正确的返回类。
至于Mapper中配置的namespace,id信息主要是为了让Mapper能够和java进行一一对应。
其实就是通过一个builder类封装一个复杂的对象,这个复杂对象是由很多零件对象组成的。主要是因为这些零部件整体上不会有大的变动,但是每个零件组成细节可能存在不同,这时候使用一个builder,通过构造函数来设置一些细节零件。但是整体对象来说区别不大,因为都是那么几个零件组成的。
上面针对工厂类使用建造者模式是为什么,就是因为这个工厂实际上组成就是那么几部分,输入流,Properties,环境,只是具体的细节不太一样可以设置。那么通过这个建造类去创建我们实际需要的工厂类,这就相当于在给代码解耦。不然的话,这些代码写在工厂类里面也没有关系,但是代码就冗杂了。这样分开之后,不同类就各司其职,在我的理解里是更加合适的方式。
这个模式其实就是针对一个类型的抽象类,提供这个抽象类的对象创造工厂,这个抽象类下有很多继承了这个类接口的实现类。我们在外部使用的时候,不需要关心到底是怎样的具体对象,我们只要通过这个顶层的抽象工厂,调用方法获取我们需要的对象就可以。比如说之前在做图形学课设的时候,针对不同的图形,当然需要定义是一个顶层的Shape图形,其下面有很多具体的图形类,然后定义了一个图形的工厂类,其中的方法就是返回具体的图形对象。虽然当时是用c++写的,和java的接口实现存在一些区别,但是整体实现思路上是一样的。
而上面对于Session通过工厂类实现也很明显,就是通过上面建造者模式建造的工厂对象调用方法,获取到具体需要的Session对象。源码暂时看不大明白,但是应该就是创建Session的一系列操作。
其实就是说,一般情况下我们访问某个对象操作某个方法就是获取这个对象然后调用这个对象的方法。但是这个对象可能是一个整体化的对象,其中部分方法是有条件的向外开放的。那么这时候就可以使用一个代理对象,也就是能够访问实际对象,但是对于访问存在一定控制的类去访问。使用时访问这个代理对象,那么这个访问就能被控制。
代理模式整体上有几种,像静态代理,动态代理。 静态代理就是实际类和代理类实现同一个接口,代理类中重写方法达到权限控制。 而上面使用的其实是动态代理。之前其实学习过动态代理,就是通过Proxy来创建代理,需要传入和被代理对象相同的类加载器,代理对象要实现的接口,还有InvocationHandler接口实现类的具体实现方法。其实源码上也是这样实现的,只是封装了很多层。
动态代理其实就是说,不需要写好代理实现类,而是通过类加载器,传入具体实现方法,需要继承的接口来动态地生成代理类。感觉上就是将生成代理这个过程封装,而且封装地很巧妙。 下一部分内容打算在上面理解的基础上,简单实现一下基础的Mybatis操作流程中的相关类。
如有错误欢迎读者批评指正!!