文章目录
说明
因为是个人复习java的总结,所以结构稍显杂乱,有些语句过于口语化.
回顾Mybatis基础配置
- 写一个dao接口还有对应实体类
- 创建主配置xml文件,存放在resources下.copy一下限定头,设置environment,注意一下数据库uel的编码设置问题.
- 设置影响配置文件mapper路径,并创建mapper的配置xml文件
- copy一下mapper配置头,设置mapper对应dao中的查找方法.注意设置返回类型.
- 使用单元测试,创建一个类用于测试.
- 测试前,先获取数据库的连接
- 使用输入流读取配置文件,调用建造者创建工厂类对象
- 通过工厂获取对象连接,获取代理对象
- 调用方法获得返回值
- 关闭连接
其实配置整体上不难,主要是回顾一下.
CRUD操作
其实Mybatis所有的操作都和查询所有的操作差不多,整体上的思路都是通过xml或者注解配置,获取连接,代理对象,调用方法.
插入操作
基于上面的查询所有写好的内容,再dao中增加一个方法,再在映射配置文件中配置方法对应的内容,如下
<insert id="addOne" parameterType="cjlu.cct.domain.Person">
insert into person(name,age,sex,birthday) values(#{name},#{age},#{sex},#{birthday});
</insert>
这里需要注意,通过parameterType设置传入数据的类型,然后在sql语句中调用对象的属性,然后就可以在单元测试中新建测试.
为了测试方便,对于连接获取和关闭的操作可以封装到方法中,然后通过注解配置,使得这些方法在单元测试开始前或者结束后运行.具体如下:
/**
* 测试初始化获取连接
* @throws IOException
*/
@Before //设置再测试之前执行
public void init() throws IOException {
inputStream = Resources.getResourceAsStream("SqlMapperConfig.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
sqlSession = factory.openSession();
personDao = sqlSession.getMapper(PersonDao.class);
}
/**
* 测试摧毁方法
* @throws IOException
*/
@After //设置测试结束之后调用
public void destory() throws IOException {
//注意提交事务,因为Mybatis插入,删除,更新等采用了事务管理
sqlSession.commit();
sqlSession.close();
inputStream.close();
}
这里特别需要注意一点,Mybatis的操作中,对于插入,修改,删除使用了事务,因此在调用完方法之后需要提交事务,不然不会在数据库中生效.
更新方法
其实跟增加没什么区别,只是sql语句的不同
<update id="updateOne" parameterType="cjlu.cct.domain.Person">
update person set name=#{name},age=#{age},sex=#{sex},birthday=#{birthday} where id=#{id};
</update>
删除方法就不赘述了,练习一下就好了.
注意一点,如果在传入的参数只有唯一一个的时候,不需要特定的名称来设置数据的传入,可以设置成任意名称.
我想应该是因为,如果是一个封装数据的时候,会通过反射去获取javaBean的属性,所以才需要传入特定属性的名称.
这里注意一下模糊查询的两种传参方式,一种会采用预编译的方式执行,这也是比较常用的一种方式.另一种是普通的执行.
<select id="findByName" resultType="cjlu.cct.domain.Person" parameterType="String">
<!-- 这里如果不想采用name传入模糊查询的%的方式,可以通过'%#{value}%'. -->
<!-- 但是需要注意一点,现在的方式采用的是预编译的模式解析,改为''则变为普通执行. -->
select * from person where name like #{name};
</select>
通过sql语句select last_insert_id();
可以获取刚插入的数据的id.说实话我还真第一次知道sql还有这种方法.
在Mybatis中使用的话,可以通过在配置的insert中添加selectKey来实现,细节的参数意义,其实根据参数名就可以看出来,没什么好解释的,具体如下
<insert id="addOne" parameterType="cjlu.cct.domain.Person">
<selectKey keyProperty="id" keyColumn="id" resultType="int" order="AFTER">
select last_insert_id();
</selectKey>
insert into person(name,age,sex,birthday) values(#{name},#{age},#{sex},#{birthday});
</insert>
映射配置文件中设置的返回值类型
也就是#{value}
是怎么确定属性值的.其实跟之前我想的一样,就是通过反射和自省的方式来确认的.首先我们通过传入的数据类型确认了,到底是哪个类对象作为传入数据.然后就可以直接通过属性名来获取属性值.这个我记得在之前JavaBean的时候有提到过一个概念跟这个很像.
这里使用的是OGNL技术,对象导航图技术,暂时整不明白,也不想深究的内容.
自定义类作为配置参数的问题
根据上面的内容,其实可以联想到一个问题,就是在传入自定义类作为传入数据的时候,如果出现配置中的属性名和JavaBean中的属性名不同,那么就会造成找不到属性的问题.同时还有一个问题,因为之前了解原理的时候也发现,Mybatis是通过配置的属性名和数据库中的字段名形成对应的.如果设置的属性名和数据库中的字段名不同,那么就会造成找不到对应填充字段或属性,然后出现错误.
这个问题有两种解决方式
第一种,很简单使用sql语句的as来设置别名,使得实体类的属性和数据库的字段名形成一一对应的效果.但是这种方式明显不太好,特别是对于一些比较复杂的数据库.
第二种,通过在配置信息Mapper中设置resultMap,设置属性和字段的对应关系,然后在下面的配置中使用这个resultMap,从而达到效果.具体的应用如下:
<!-- 配置数据库的字段名和实体类属性的一一对应关系 -->
<resultMap id="personMap" type="cjlu.cct.domain.Person">
<!-- 主键信息的配置 -->
<id property="id" column="id"></id>
<!-- 其他字段的配置 -->
<result property="name" column="name"></result>
<result property="age" column="age"></result>
<result property="sex" column="sex"></result>
<result property="birthday" column="birthday"></result>
</resultMap>
<select id="findAll" resultMap="personMap">
select * from person;
</select>
很明显,这种方式更加地直观,但是也带来了解析配置的麻烦,效率比较低.
至于使用dao实现类来使用Mybatis,就真的没什么好说的.其实本质上大多还是用Mybatis的内容,只是传入工厂到实现类中,然后实现类中不解析配置文件,直接调用底层的方法传入正确的拼接参数.然后返回结果就好了.只是比Mybatis少了解析配置,效率稍微高一些.
property配置属性中resource和url的使用
其实之前配置mysql的环境数据的时候应该稍微有一点疑惑,之前写的时候都是把配置信息放在properties文件中,但是现在怎么直接卸载xml中了.
这里就牵扯到对于resource的使用,其实这些信息是可以放在propertie中的,但是需要在environment外配置properties信息,并且使用resource定位properties文件.然后在下面的property配置中,就可以使用${键}来获取properties文件中的内容.
这里需要注意键名不要写错了,不然定位不到properties文件中的键值.
<properties resource="jdbc.properties"></properties>
<environments default="mysql">
<environment id="mysql">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
typeAlias配置属性
其实就是一个能对当前配置文件的配置信息,设置别名的属性.比如说原本需要写全类名的输入类型,定义别名之后,直接使用别名.并且这个别名是不区分大小写的.但是很明显,如果这个使用多了,也很复杂.
<typeAliases>
<typeAlias type="cjlu.cct.domain.Person" alias="person"></typeAlias>
</typeAliases>
package配置属性
其实就是针对上面单条属性配置的复杂,可以像导包一样,加载一个包下的目录结构到配置文件中.然后就可以在配置文件中直接调用写这个包下的类名,就能直接找到.
这里需要知道一下,在mappers下也可以加入package配置,相当于是批量导入接口.某个包下的接口都会去匹配映射配置.
如有错误欢迎读者批评指正!!