Mybatis
mybatis是一个半自动的ORM映射框架(支持一对一,一对多的实现,多对多采用两个一对多进行实现
1.mybatis的优势
-
比起jdbc的操作,减少了一些重复的代码量工作,也方便能够集成到后期的管理框架中
-
mybatis提供在XML中编写sql语句,不直接入侵在代码中(方便分类修改)
-
分别提供的xml标签和mapper标签(xml标签可实现动态SQL语句,也就是嵌入条件判断和循环,比较类似存储函数),mapper标签支持对象正确的解析至数据库中
2.mybatis框架执行原理
1.sqlConfigXMl配置文件(一个全局的配置文件)(可配置映射文件和连接数据源和事务等)
2.通过配置文件构建出可构建操作数据会话的会话工厂,也就是我们常说的sqlSessionFactory(涉及工厂模式代码设计)
3.通过sqlSessionFactory生产出相互独立的sqlsession,为什么是独立的会话,既然是独立的会话,那也有全局的会话进行数据库层面上面的操作
4.sqlsession之所以能够操作,依赖一个叫Executor的执行器,通过该执行器进行数据库的CRUD操作
5.Executor的执行器需要操作CRUD的动作由谁而来,就是由mapperstatement对象读取mapper映射文件
3.mybatis使用流程
- src目录下构建mybatis的全局配置文件mybatisCfg.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>
<!-- 数据库连接环境配置 -->
<environments default="development">
<!-- 标明mybaitis环境 id唯一 -->
<environment id="development">
<!-- JDBC – 这个配置直接简单使用了 JDBC 的提交和回滚设置。 它依赖于从数据源得 到的连接来管理事务范围。JDBC默认是自动提交 -->
<transactionManager type="JDBC" />
<!-- 采用数据库连接池 -->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver" />
<!-- 避免环境的不统一,造成数据操作乱码 -->
<property name="url"
value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8" />
<property name="username" value="root" />
<property name="password" value="123456" />
</dataSource>
</environment>
</environments>
<!-- 添加需要被映射的文件 -->
<mappers>
<mapper resource="com/wcy/dao/PersonMapper.xml" />
</mappers>
</configuration>
2.mapper映射文件格式:
<?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.wwj.dao.PersonDao">
<insert id="savePerson" parameterType="com.wcy.model.Person">
insert into
person(name,address,bir) values(#{name},#{address},#{bir});
</insert>
<update id="updatePerson" parameterType="com.wcy.model.Person">
update person set
name=#{p.name},address=#{address},bir=#{bir}
where id=#{id}
</update>
<delete id="deletePersonById" parameterType="int">
delete from person
where id=#{id}
</delete>
<select id="getPersonInfos" resultType="com.wcy.model.Person">
select * from person
</select>
</mapper>
3.映射文件中属性
1.namespace:对应dao层接口全类名
2.id:和接口中方法一致
3.定义sql语句标签:
-
<insert>
-
<insert>
-
<delete>
-
<update>
4.有返回值要接收时
-
resultType:接收基本数据,复杂类型,(全类名)
-
resultmap:自定义类型接收,需要创建对应的实体类
5.parameterType:输入类型(可不写)
#{}:接收参数,在接口方法中获取参数
6.接收方式
-
索引接收
List<Person> getPersonInfosByNameAndID(String name ,int id);
<select id="getPersonInfosByNameAndID" >
select * from person where name = #{0} and id = #{1}
</select>
-
map接收
/**
* 根据map进行查询
* @param attrs
* key1 id key2 name
* @return
*/
List<Person> getPersonInfosByMap(Map attrs);
//------------------动作实现
<select id="getPersonInfosByMap" parameterType="java.util.Map" resultType="com.wwj.model.Person">
select * from person where id =
#{id} and name = #{name}
</select>
//----------------调用测试
Map<String,Object> attrs = new HashMap<>();
attrs.put("id", 2);
attrs.put("name", "小王");
session.selectList("getPersonInfosByMap", attrs);
-
注解接收
/**
* 根据用户唯一id查询信息
* @param id
* @return
*/
Person getPersonInfo(@Param("pid") int id);
//---------------动作实现
<select id="getPersonInfo"
resultType="com.wwj.model.Person">
select * from person where id =
#{pid}
</select>
//---------调用测试
session.selectOne("getPersonInfo", 2);
-
自定义结果类型接收(resultmap)
//----- 实体类
public class Card {
private String cname;
}
public class Person implements Serializable {
private Integer id;
private String name;
private Date bir;
private String address;
private List<Card> cards;
}
//----构建自定义的resultmap封装 注意 collection(集合)association(联系)
<resultMap type="com.wcy.model.Person" id="personRS">
<!--column指向数据库列名 property指向pojo对象中字段名 -->
<result column="name" property="name" />
<!-- property指的是在bean中字段名 ofType类的全定向名 -->
<collection property="cards" ofType="com.wwj.model.Card">
<result column="cname" property="cname" />
</collection>
</resultMap>
//--------映射的动作实现
<select id="getPersonsOfCard" resultMap="personRS">
select
person.name,card.cname
from person
INNER JOIN card
on person.id = card.pid
</select>
//--------代码操作
List<Person> persons = session.selectList("getPersonsOfCard");
for (Person person : persons) {
System.out.println(person.getCards().get(0).getCname());
System.out.println(person.getCards().get(1).getCname());
}
自定义resultMap封装中的标签
<id/>:数据库中的主键
其中属性:
column:数据库列名
property:在bean中字段名
<result/>:数据库中其他的字段
<collection></collection>:一对多的时候使用,映射文件引入用:ofType类的全类名
<association></association>:多对一的时候使用,javaType:类的全类名
mybatis立即返回主键值
应用场景:当我们需要在当前事务插入数据后立即获取数据的主键id,做下一步额外操作,并且不因为并发高的情况下取错值而考虑
<insert id="savePerson" parameterType="com.wcy.model.Person">
<selectKey keyProperty="id" resultType="int" order="AFTER">
select last_insert_id()
</selectKey>
insert into
person(name,address,bir) values(#{name},#{address},#{bir});
</insert>
//------------------------------------------------------------
// 操作数据
Person p = new Person();
p.setName("小小王");
p.setBir(parse);
int result = session.insert("savePerson", p);
System.out.println(result);
System.out.println(p.getId());
- keyProperty=”返回主键的id的属性名”
- resultType=”主键类型”
- order=”“什么时候执行,在SQL执行前还是执行后执行,两个取值:BEFORE和AFTER
- select last_insert_id()取到最后生成的主键,只在当前事务中取
调用
//读取配置文件
InputStream is = Resources.getResourceAsStream(“配置文件.xml”);
//产生sqlSessionFactory
SqlSessionFactory build = new SqlSessionFactoryBuilder().build(is);
//产生sqlSession对象
SqlSession session = build.openSession();
//获取映射(映射的dao层的.class文件)
TestUserDao mapper = session.getMapper(TestUserDao.class);
//调用方法
TestUser userUseWhere = mapper.getUserUseWhere(m);
session.commit();
session.close();