Mybatis入门
Mybatis是一个ORM框架,通常作为SSM中的M,可以与Spring集成搭建相应的项目。
001、依赖
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>x.x.x</version>
</dependency>
002、入门
Mybatis也是可以使用注解驱动和配置文件驱动的,再次使用配置文件测试。
首先用一个实体类对应数据库中的表。
package pojo;
public class City {
private int city_id;
private int pro_id;
private String name;
public City(){};
public City(int city_id, int pro_id, String name) {
this.city_id = city_id;
this.pro_id = pro_id;
this.name = name;
}
@Override
public String toString() {
return "City{" +
"city_id=" + city_id +
", pro_id=" + pro_id +
", name='" + name + '\'' +
'}';
}
}
一个Mybatis整体配置文件。
<?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>
<!--这是一个资源文件,下文$中取出的就是该文件中的数据-->
<properties resource="mysql.properties"/>
<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>
<mappers>
<!--Map映射文件,里面是用来写Sql的-->
<mapper resource="mapper/mapper.xml"/>
</mappers>
</configuration>
一个Mapper映射文件,里面用于写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="cityMapper">
<select id="selectMap" parameterType="int" resultType="pojo.City">
select * from city where city_id <${id}
</select>
</mapper>
此时通过SqlSession等获取到数据。
@Test
public void test() throws Exception{
String resource = "mybatis.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
try(SqlSession sqlSession = sqlSessionFactory.openSession()) {
List<City> city = sqlSession.selectList("cityMapper.selectMap", 130800);
final Iterator<City> iterator = city.iterator();
while(iterator.hasNext())
System.out.println(iterator.next());
}
}
003、SqlSession
一个SqlSession的出现有以下三个类处理。
SqlSessionFactoryBuilder
建造器,通过资源获取到SqlSessionFactory,此后基本没用。
建造者。
SqlSessionFactory
用于生产SqlSession.
工厂。
SqlSession
一个会话,通过会话处理各种sql语句。
Mybatis也可不使用Mapper的xml配置,转而使用注解。
如下用来代替映射文件的xml.
public interface MapperCity {
@Select("select * from city where city_id<${id}")
List<City> selectCitys(int id);
}
在mybatis.xml整体配置的mapper加入类名即可。
<mappers>
<mapper resource="mapper/mapper.xml"/>
<mapper class="mapper.MapperCity"/>
</mappers>
测试一下:
public class MapTest {
SqlSession sqlSession;
@Before
public void open() throws IOException {
String resource = "mybatis.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
sqlSession = sqlSessionFactory.openSession();
}
@After
public void close(){
sqlSession.close();;
}
@Test
public void test01(){
final MapperCity mapper = sqlSession.getMapper(MapperCity.class);
final List<City> cities = mapper.selectCitys(120700);
for(City city:cities){
System.out.println(city);
}
}
}
004、接口和xml的组合
有时候sql语句比较复杂的时候,也经常使用接口和xml的组合,即通过接口提供一组api,由xml具体实现。
这样在执行服务的时候,通过接口获取的对象也可以调用xml中的sql。
接口只有提供的方法。
package mapper;
//此处接口名就是xml中namespace,方法名就是语句id
public interface SelectCity {
City selectOne(int id);
List<City> selectList(int id);
}
xml中实现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="mapper.SelectCity">
<select id="selectOne" parameterType="int" resultType="pojo.City">
select * from city where city_id=${id}
</select>
<select id="selectList" parameterType="int" resultType="pojo.City">
select * from city where city_id <${id}
</select>
</mapper>
mybatis全局配置中需要这个mapper:
<mapper resource="mapper/SelectCity.xml"/>
执行查询:
final SelectCity mapper = sqlSession.getMapper(SelectCity.class);
final City city = mapper.selectOne(110100);
System.out.println(city);
005、全局xml配置
全局配置文件中有些标签比较常用。
properties
可以从外部加载properties文件,或者在子标签中配置属性。
<properties resource="org/mybatis/example/config.properties">
<property name="username" value="dev_user"/>
<property name="password" value="F2Fa3!33TYyg"/>
</properties>
settings
相关配置信息,使用缓存等,懒加载等。
<settings>
<setting name="cacheEnabled" value="true"/>
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="multipleResultSetsEnabled" value="true"/>
<setting name="useColumnLabel" value="true"/>
<setting name="useGeneratedKeys" value="false"/>
<setting name="autoMappingBehavior" value="PARTIAL"/>
<setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>
<setting name="defaultExecutorType" value="SIMPLE"/>
<setting name="defaultStatementTimeout" value="25"/>
<setting name="defaultFetchSize" value="100"/>
<setting name="safeRowBoundsEnabled" value="false"/>
<setting name="mapUnderscoreToCamelCase" value="false"/>
<setting name="localCacheScope" value="SESSION"/>
<setting name="jdbcTypeForNull" value="OTHER"/>
<setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>
</settings>
typeAliases
别名
<typeAliases>
<typeAlias alias="Author" type="domain.blog.Author"/>
<typeAlias alias="Blog" type="domain.blog.Blog"/>
<typeAlias alias="Comment" type="domain.blog.Comment"/>
<typeAlias alias="Post" type="domain.blog.Post"/>
<typeAlias alias="Section" type="domain.blog.Section"/>
<typeAlias alias="Tag" type="domain.blog.Tag"/>
</typeAliases>
mappers
有mapper等子标签,也可以直接使用包。
<!-- 将包内的映射器接口实现全部注册为映射器 -->
<mappers>
<package name="org.mybatis.builder"/>
</mappers>
006、映射xml配置
映射xml中有许多子标签。
select、update、insert、delete............. |
---|
sql、cache、resultMap。。。。。 |
有些重要的属性:
id 在命名空间中唯一的标识符,可以被用来引用这条语句。
parameterType 将会传入这条语句的参数类的完全限定名或别名。这个属性是可选的,因为 MyBatis 可以通过
resultType 从这条语句中返回的期望类型的类的完全限定名或别名。注意如果是集合情形,那应该是集合可以包含的类型,而不能是集合本身。使用 resultType 或 resultMap,但不能同时使用。
resultMap 外部 resultMap 的命名引用。结果集的映射是 MyBatis 最强大的特性,对其有一个很好的理解的话,许多复杂映射的情形都能迎刃而解。使用 resultMap 或 resultType,但不能同时使用。
1、parameterType
参数类型,Mybatis对参数类型起了别名,有些类型如int也是别名。
这个属性中的值通常就是sql语句的参数类型,这里的类型要和传入的类型对应,否则报错。
<select id="selectMap" parameterType="int" resultType="pojo.City">
select * from city where city_id <${id}
</select>
也可以使用map做映射,如下第三节。
2、$/#的区别
![](https://img-blog.csdnimg.cn/201906101443299.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzY4ODY5MQ==,size_16,color_FFFFFF,t_70)
3、map
这个map是入参parameterType的可选值之一,别和resultMap搞混。
给字段起别名,可以通过map进行映射。
Map<Object,Integer> map=new HashMap();
map.put("id",130800); //此处的map的key就是xml中的参数
List<City> list = sqlSession.selectList("cityMap.selectMap", map);
<select id="selectMap" parameterType="map" resultType="pojo.City">
select * from city where city_id <${id}; <!-- 此处的id是map的key>
</select>
4、resultType
从这条语句中返回的期望类型的类的完全限定名或别名。注意如果是集合情形,那应该是集合可以包含的类型,而不能是集合本身。使用 resultType 或 resultMap,但不能同时使用。
5、resultMap
这也是用来做映射的,类和数据库进行映射。
如果返回的类型和类的字段类型不同,使用resultMap进行处理。
class database
c_id city_id
p_id pro_id
name name
Citys类
package pojo;
public class Citys {
private int c_id;
private int p_id;
private String name;
public Citys(){};
@Override
public String toString() {
return "Citys{" +
"c_id=" + c_id +
", p_id=" + p_id +
", name='" + name + '\'' +
'}';
}
}
xml配置
<select id="resMap" parameterType="map" resultMap="c_map">
select * from city where city_id <${id};
</select>
<resultMap id="c_map" type="pojo.Citys">
<result property="c_id" column="city_id"/>
<result property="p_id" column="pro_id"/>
</resultMap>
测试类:
@Test
public void test04(){
Map<Object,Integer> map=new HashMap();
map.put("id",130800);
final List<Citys> list = sqlSession.selectList("cityMap.resMap", map);
for(Citys city:list){
System.out.println(city);
}
}
resultMap有好几个子标签,如result、association等。
association用于处理复杂字段。
<resultMap id="detailedBlogResultMap" type="Blog">
<constructor>
<idArg column="blog_id" javaType="int"/>
</constructor>
<result property="title" column="blog_title"/>
<association property="author" javaType="Author">
<id property="id" column="author_id"/>
<result property="username" column="author_username"/>
<result property="password" column="author_password"/>
<result property="email" column="author_email"/>
<result property="bio" column="author_bio"/>
<result property="favouriteSection" column="author_favourite_section"/>
</association>
<collection property="posts" ofType="Post">
<id property="id" column="post_id"/>
<result property="subject" column="post_subject"/>
<association property="author" javaType="Author"/>
<collection property="comments" ofType="Comment">
<id property="id" column="comment_id"/>
</collection>
<collection property="tags" ofType="Tag" >
<id property="id" column="tag_id"/>
</collection>
<discriminator javaType="int" column="draft">
<case value="1" resultType="DraftPost"/>
</discriminator>
</collection>
</resultMap>
constructor
- 类在实例化时,用来注入结果到构造方法中
idArg - ID 参数;标记结果作为 ID 可以帮助提高整体效能
arg - 注入到构造方法的一个普通结果
6、mybatis返回map
Map selectList(User user);
<select id="selectOne" parameterType="cn.lyn4ever.entity.User" parameterType="cn.lyn4ever.entity.User" resultType="java.util.HashMap">
select id,username,telphone from user where telphone=#{telphone} and password = #{password}
</select>
上这结果就是说,以User类的属性名为key,属性值为value。
当然,也可以查出来多条记录,将这个Map放进List中
List<Map> selectList(User user);
<select id="selectOne" parameterType="cn.lyn4ever.entity.User" resultType="java.util.HashMap">
select id,username,telphone from user
</select>
但是有时候我们想要这种结果,怎么办呢?
{
"01":{
username:"zhangsan",
telphone:"13000000000"
}
}
也就是我们要自定义一个Map<String,User>,这样的话,有以下两种解决方法:
1.使用注解
@MapKey("id")
Map<String,User> getUserInMap();
<!--xml和之前写法一样-->
<select id="getUserInMap" parameterType="cn.lyn4ever.entity.User" resultType="User">
select id,username,telphone from user where telphone=#{telphone} and password = #{password}
</select>
这个@MapKey的value写的就是User对象的一个属性
2.在xml文件中写上
HashMap<String,Object> getUserInMap();
<select id="getUserInMap" parameterType="cn.lyn4ever.entity.User" resultType="java.util.HashMap">
SELECT id as 'key', * as 'value', id,username,telphone from user where telphone=#{telphone} and password = #{password}
</select>
当然以上这两种方法,如果查出来是多条的话也会是List的形式,如下:
/**
*
* @param office
* @return 总数
*/
List<HashMap<String,Integer>> countByOffice();
<select id="countByOffice" resultType="java.util.HashMap" >
select office as 'key' ,count(1) as 'value' from doctor group by office
</select>
7、调用存储过程
<select id="queryEmp" parameterType="map" statementType="CALLABLE">
{
call pag_add(
#{p1,mode=IN,jdbcType=NUMERIC},
#{p2,mode=IN,jdbcType=NUMERIC},
#{p3,mode=OUT,jdbcType=NUMERIC}
)
}
</select>