原始jdbc存在的问题:
使用原始jdbc程序来查询mysql数据库里面的记录,导入数据库驱动包(mysql-connection-java-5.1.7-bin.jar 或 ojdbc14-10.2.0.1.jar相对应的数据库的驱动)写下测试类的代码即可,但是存在下面的问题:
- 数据库连接的时候,使用时候就创建,不使用就立即释放,这样对于数据库额频繁连接开启和关闭,对于数据库资源造成浪费,而且影响数据库的性能.---->使用数据库连接池进行连接
- 之前把sql语句硬编码到java代码中.如果修改了 sqll语句那么需要重新编译java文件.,不利于系统的维护。---->把sql语句写在xml配置文件中,那么就不用重新编译了.
- 之前向preparedStatement中设置参数,对于占位符的位置以及参数值的设置,相当于把硬编码到java代码中,一样不利于系统的维护.---->所以我们把sql语句,还有占位符以及参数设置到配置文件中.
- 最后,从resultset中遍历结果集数据的时候,也才做硬编码,他是对于湖区的字段进行硬编码..---->我们把查询的结果集映射成java对象.
使用namespace命名空间:对sql进行分类化管理
select指定resultType:将单条记录映射成java对象
SqlMapConfig.xml是mybatis用来建立sessionFacctory用的,里面主要包含了数据库的连接信息,java类所对应的别名,mapper映射文件的路径。
user.xml定义sql语句,参数,返回的类型
原始jdbc方法:
1.Class.ForName("xxx");加载驱动器类
2.连接到数据库
3.创建statement对象
4.执行sql
5.解析ResultSet得到数据
什么是mybatis?
mybatis 是支持普通sql查询,是一个不完全的ORM框架,是一个持久层框架,存储过程和映射关系,消除了之前的许多麻烦事,比如几乎所有的jdbc代码,笨拙地手动设置参数,对于结果集的检索。现在:使用mybatis简单的xml或注解,用于配置和原始映射,将接口和java对象映射成数据库中的记录。
#{}和${}
#{} 接受pojo对象的属性值,mybatis通过OGNL获取对象的属性值 比如sql语句中#{username}
#{}表示一个占位符号,#{}接收输入参数,类型可以是简单类型,pojo、hashmap。
如果接收简单类型,#{}中可以写成value或其它名称。
#{}接收pojo对象值,通过OGNL读取对象中的属性值,通过属性.属性.属性...的方式获取对象属性值。
${}表示一个拼接符号,会引用sql注入,所以不建议使用${}。
${}接收输入参数,类型可以是简单类型,pojo、hashmap。
如果接收简单类型,${}中只能写成value。比如sql语句中 LIKE ‘%${value}%’
${}接收pojo对象值,通过OGNL读取对象中的属性值,通过属性.属性.属性...的方式获取对象属性值。
mybatis框架执行过程:
1、配置mybatis的配置文件,SqlMapConfig.xml(名称不固定)
2、通过配置文件,加载mybatis运行环境,创建SqlSessionFactory会话工厂
SqlSessionFactory在实际使用时按单例方式。
3、通过SqlSessionFactory创建SqlSession
SqlSession是一个面向用户接口(提供操作数据库方法),实现对象是线程不安全的,建议sqlSession应用场合在方法体内。
4、调用sqlSession的方法去操作数据。
如果需要提交事务,需要执行SqlSession的commit()方法。
5、释放资源,关闭SqlSession
MyBatis中可以使用OGNL的地方有两处:
- 动态SQL表达式中
- ${param}参数中
自增主键返回:
select LAST_INSERT_ID() 按照order属性指定的顺序,进行主键的插入。主键的属性由keyProperty指定的对应的prameterType对应的那一个属性。
非自增主键返回:
在mysql 中:select uuid()这个函数来生成主键。
在oracle中:select 序列名.nextval() 来生成主键。
hibernate适用与需求变化不多的中小型项目,比如:后台管理系统,erp、orm、oa。
mybatis适用与需求变化较多的项目,比如:互联网项目。
将来mybatis和spring整合后,使用单例模式管理sqlSessionFactory。
SqlSession最佳应用场合在方法体内,定义成局部变量使用。线程不安全,面向用户(程序员)的接口。
生成的动态代理对象中是根据mapper方法的返回值类型确定是调用selectOne(返回单个对象调用)还是selectList (返回集合对象调用 ).
输出映射:
使用resultType进行输出映射,只有查询出来的列名和pojo中的属性名一致,该列才可以映射成功。
如果查询出来的列名和pojo的属性名不一致,通过定义一个resultMap对列名和pojo属性名之间作一个映射关系。
对于需要输入多个id 的时候,动态sql 的写法是:
<foreach collection="ids" items="user_id" open="AND (" close=")" separator="or">
id = #{user_id}<!--这个是每个遍历时候,需要拼接的串-->
</foreach>
当我们动态拼接表名的时候,必须使用${}符号,
mybatis的生命周期【也就是说sqlsession,sqlsessionFactory的作用域】
一个会话一个sqlsession他的生命周期在方法里面,方法结束他的生命周期也就结束。每个方法一个。
sqlsessionFactory的生命周期是在一个项目中,保证他是单例的,只有一个对象。
面试和笔试-->mybatis缓存:
一级缓存是sqlsession。执行了一个sql语句(同一个sql语句,参数也相同。),同一个方法里面,查询到的内容放在缓存中,key是001 value就是我们查询出来的数据。hash算法拼接出来一个key。在同一个方法里面,再去使用SQLsession第二次查询,到缓存里面,执行001sql语句,就不进入数据库里面。查询缓存的效率 比 查询数据库的效率快很多倍。sqlsession一级缓存是mybatis自动开启的。
二级缓存是Mapper映射文件。需要我们手动设置。不同的session如果执行同一个mapper映射文件里面的sql,那么第二次就查询缓存。sqlMapConfig.xml里面进行设置<settings><setting name="CacheEnable" value="true"></setting></settings>。而且第一次查询之后,把session关闭。第二个查询我们手动打开,sessionFactory.openssion();二级缓存需要把缓存的信息,写到本地【序列化一下】。
缓存什么时候进行刷新呢?2次中间查询进行了增删改,缓存会帮你自动清空。那么你现在的第二次查询就是查询的数据库。能够保证数据的一致。禁用二级缓存【每次都想让他查询数据库】在<select>语句中,设置useCache="false"。增删改操作让不让刷新也可以进行设置,在里面设置flushCache="false";