Mybatis基础使用简介
这几天把SSM框架整体整理了一遍,下面将三个系统分开阐述以下他们的基本实现方式,最后写一个整体的程序整合以下,
首先是新建一个工程,因为暂时没有和Views有什么联系,我就新建了一个javaProject
学习一个新的框架,首先是引入jar包
mybatis框架所需要的jar包有
mybatis-3.5.6.jar mysql-connector-java-5.1.47.jar
上述两个包引入之后,我们新建一个conf.xml配置文件,内容如下
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <!-- 默认环境就是development --> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <!-- 数据源 --> <dataSource type="POOLED"> <property name="driver" value="com.jdbc.mysql.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/jdbcdemo"/> <property name="username" value="root"/> <property name="password" value="root"/> </dataSource> </environment> </environments> </configuration>
这里面我们就配置mybatis需要使用的数据源以及驱动方式
然后需要再数据库jdbcdemo新建一个表来满足我们测试的需要
新建表如下:
CREATE TABLE `person` ( `id` int(11) DEFAULT NULL, `name` varchar(20) DEFAULT NULL, `age` int(11) DEFAULT NULL, `sex` int(11) DEFAULT NULL, `schoolAddress` varchar(200) DEFAULT NULL, `homeAddress` varchar(200) DEFAULT NULL, `comid` int(11) DEFAULT NULL, KEY `fk_p2c` (`comid`), CONSTRAINT `fk_p2c` FOREIGN KEY (`comid`) REFERENCES `company` (`comid`) )
这里的一个外键连接是为以后的一对多测试,暂时不需要关注这个
同时,我们需要在程序中配置该实体类,如下:
package com.xjg.empty; import java.io.Serializable; public class Person implements Serializable { /** * */ private static final long serialVersionUID = 1L; private int id; private String name; private int age; private String stusex; private Address add; private int comid; private company com; public company getCom() { return com; } public void setCom(company com) { this.com = com; } public int getComid() { return comid; } public void setComid(int comid) { this.comid = comid; } public Person() { } public Person(int id, String name, int age, String stusex) { this.id = id; this.name = name; this.age = age; this.stusex = stusex; } public Person(int id, String name, int age) { this.id = id; this.name = name; this.age = age; } public Address getAdd() { return add; } public void setAdd(Address add) { this.add = add; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getStusex() { return stusex; } public void setStusex(String stusex) { this.stusex = stusex; } @Override public String toString() { return "Person [id=" + id + ", name=" + name + ", age=" + age + ", stusex=" + stusex; } }
然后我们配置一个map文件,里面就写了我们需要用到的sql语句,内容如<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.xjg.mapper.personMapper"> <!-- 返回值类型 --> <resultMap type="person" id="permap"> <result property="id" column="id"/> <result property="name" column="name"/> <result property="age" column="age"/> <result property="stusex" column="sex" javaType="String" jdbcType="INTEGER"/> </resultMap> <!-- CURD -->
<!-- 通过传入的ID选择数据--> <select id="QueryById" resultMap="permap" parameterType="int" > select * from person where id = #{id} </select> </mapper>
最后我们新建一个测试类,实现该方法
package com.xjg.service; import java.io.IOException; import java.io.Reader; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import com.xjg.empty.Address; import com.xjg.empty.Person; import com.xjg.empty.PersonAndCompany; import com.xjg.empty.company; import com.xjg.empty.snoList; import com.xjg.mapper.personMapper; public class mybatisDemo { public static void mybatis01() throws IOException {
//加载配置文件 Reader in = Resources.getResourceAsReader("conf.xml"); //获取sqlSession SqlSessionFactory sql = new SqlSessionFactoryBuilder().build(in); SqlSession stmt = sql.openSession(); //查询一个 Person per = stmt.selectOne("com.xjg.mapper.personMapper.QueryById", 1); System.out.println(per.toString()); stmt.close(); } public static void main(String[] args) throws Exception { mybatis01(); } }
上述可以得到下面查询结果
Person [id=1, name=zs, age=24, stusex=null
上述与如果执行出错,可能是返回值类型出错,因为返回值我这里写的是person,这里需要在配置文件中添加下面这个默认属性,不然系统不认识person,并且需要将map文件加入到配置文件中
在conf.xml添加
<!-- 生成别名 --> <typeAliases> <!-- <typeAlias type="com.xjg.empty.Person" alias="person"/> --> <package name="com.xjg.empty"/> </typeAliases> <!-- map文件 --> <mappers> <mapper resource="com/xjg/mapper/personMapper.xml"/> </mappers>
这样你的返回值就可以使用person了
上面在map文件中我们配置了一个resultMap标签,名字叫permap,如果我们的返回值只是person,那么可以在CURD那部分直接写person,但是我们还是配置了resultmap属性,主要目的是为了将person里面的stusex属性和表里的的sex属性对应,
并且在表里面,该属性的类型是int,但是在程序中这个属性的类型的String,很明显,类型是不一致的,我在程序中传入的性别:男 是不可以直接存储到mysql中去的,这时我们就需要类型转换器来将我们的类型自动转换
所以,我们先建一个类,然后继承BaseTypeHandler,代码如下:
package com.xjg.change; import java.sql.CallableStatement; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import org.apache.ibatis.type.BaseTypeHandler; import org.apache.ibatis.type.JdbcType; import org.apache.ibatis.type.TypeHandler; public class Converter extends BaseTypeHandler<String> { //赋值转换 @Override public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException { if(parameter=="男") { ps.setInt(i, 1); } else { ps.setInt(i, 0); } } //用列名获取结果并转换 @Override public String getNullableResult(ResultSet rs, String columnName) throws SQLException { return rs.getInt(columnName) == 1 ? "男":"女"; } //用列下标获取结果并转换 @Override public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException { return rs.getInt(columnIndex) == 1 ? "男":"女"; } //存储过程或者函数获取结果并转换 @Override public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { return cs.getInt(columnIndex) == 1 ? "男":"女"; } }
然後我們需要(怎麽變繁體了,算了不管了)在conf.xml配置文件中添加轉換器配置
<!-- 自定义类型转换器 --> <typeHandlers> <typeHandler handler="com.xjg.change.Converter" javaType="String" jdbcType="INTEGER"/> </typeHandlers>
这样我们插入的男就可以在插入到数据库时变成1,然后再执行了、
下面我们再简单说一下动态sql,再使用sql时,免不了需要使用很多的条件查询,这时我们就需要使用动态sql来编写出来我们的最终要执行的sql语句
代码实现如下:
<!-- 这里的parameterType无论是String\int还是int[] 都可以正确执行 --> <select id="QuerySnoByIdWithArrayList" parameterType="int[]" resultMap="permap"> select * from person <where> <if test="array.length>0 and array != null"> <foreach collection="array" open="id in(" close=")" item="sno" separator="," > #{sno} </foreach> </if> </where> </select>
上面的语句效果是,基础查询时select * from person 如果参数存在,那么循环读取,拼接到where 条件中去,这样就实现了条件查询,
上面我们写了这么多但是再调用的时候都是再XXmap.xml中根据id来直接调用,代码略显繁琐,我们可以添加一个接口方法,将所有实现的查询都集成到方法中去,注意,这里的接口名要和map文件的名字一样
代码如下:
package com.xjg.mapper; import java.util.List; import java.util.Map; import com.xjg.empty.Person; import com.xjg.empty.PersonAndCompany; import com.xjg.empty.company; import com.xjg.empty.snoList; public interface personMapper { Person QueryById(int id); }
这样我们再调用的时候就可以直接使用这里面的方法了,代码如下
public static void mybatisTest11() throws IOException { Reader in = Resources.getResourceAsReader("conf.xml"); SqlSessionFactory sql = new SqlSessionFactoryBuilder().build(in); SqlSession stmt = sql.openSession(); personMapper pm = stmt.getMapper(personMapper.class); List<Person> mm = pm.QueryById(1); System.out.println(mm); }
上边的数据源配置我们也可以单独提取出来,新建db.properties文件,内容如下
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/jdbcdemo
username=root
password=root
然后我们再conf.xml文件中就可以引入该配置,如下:
<environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <!-- 数据源 --> <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>
下面时一对一和一对多测试
在map.xml文件中添加如下代码
<!-- 一对一 --> <select id="QuerySnoOneByOneOther" parameterType="int" resultMap="resMap3"> select p.* ,c.* from person p inner join company c on p.comid=c.comid where p.id=#{id} </select> <resultMap type="person" id="resMap3"> <result property="id" column="id"/> <result property="name" column="name"/> <result property="age" column="age"/> <result property="stusex" column="sex"/> <association property="com" javaType="company"> <id property="comid" column="comid"/> <result property="comname" column="comname"/> </association> </resultMap> <!-- 一对多 --> <select id="QuerySnoOneToMore" parameterType="int" resultMap="resMap2"> select c.*,p.* from person p inner join company c on p.comid=c.comid where c.comid=#{id}; </select> <resultMap type="company" id="resMap2"> <id property="comid" column="comid"/> <result property="comname" column="comname"/> <collection property="pp" ofType="person"> <result property="id" column="id"/> <result property="name" column="name"/> <result property="age" column="age"/> <result property="stusex" column="sex"/> </collection> </resultMap>
同时,我们需要在接口中添加对应方法
List<PersonAndCompany> QuerySnoOneByOne(int a); List<company> QuerySnoOneToMore(int a);
上述就实现了一对一和一对多,多对一和多对多时反过来的多对一和多个一对多
有时候我们不需要一对一或者一对多的数据立刻加载出来,这就需要使用延迟加载,也叫懒加载
实现如下:
<!-- 一对多延迟加载 --> <select id="QuerySnoOneToMoreOnlazy" parameterType="int" resultMap="resMap4"> select c.* from company c where c.comid=#{id}; </select> <resultMap type="company" id="resMap4"> <id property="comid" column="comid"/> <result property="comname" column="comname"/> <collection property="pp" ofType="person" select="com.xjg.mapper.personComMapper.QueryStudentByComid" column="comid"> </collection> </resultMap>
这种方式需要在conf.中添加配置,如下
<settings> <!-- 开启延迟加载 --> <setting name="lazyLoadingEnabled" value="true"/> <!-- 关闭立即加载 --> <setting name="aggressiveLazyLoading" value="false"/> </settings>
有时候我们还需要引进缓存,mybatis自带一级缓存,并且默认开启
需要我们添加应用,即在map.xml开启声明
<!-- 开启缓存声明 --> <cache/>
一级混缓存存储在SqlSession域中,只要该对象不关闭,缓存就可以一直用
使用EhcacheCache三方缓存
首先引入jar包
ehcache-core-2.6.8.jar slf4j-api-1.7.30.jar aspectjrt-1.8.7.jar aspectjweaver-1.8.7.jar
然后再map中引入二级缓存
<cache type="org.mybatis.caches.ehcache.EhcacheCache"> </cache>
同时再conf.xml <settings>中开启二级缓存
<!-- 开启二级缓存 -->
<setting name="cacheEnabled" value="true"/>
二级缓存存储再map域中,只要在相同map域中产生的SqlSession对象,都可以使用缓存内容
一二级缓存均会在出现commit的之后失效
或者
<select id="QueryById" resultMap="permap" parameterType="int" useCache="true" flushCache="false">
使用flushCache刷新缓存使其失效。
以上就是简单的mybatis总结