ORM:Object Relational Mapping 对象关系映射,这种思想目标是把面向对象开发中的对象映射到基于SQL的关系型数据库中。
addStu(Student stu) orm: addStu(Student stu)
jdbc:手动造车 手动执行 ORM框架.save(stu)–>XML 映射文件
手动处理结果 手动写SQL 映射文件: 类=表 类中属性-表中字段
}
ORM是一种思想,其中最著名的实现: Hibernate.
Hibernate是一款“全自动”的ORM映射框架:实现了Pojo到数据库表的全套映射机制,开发人员只需要定义好映射文件。Hibernate会自动的根据映射文件逻辑生成SQL语句、自动的执行SQL语句、自动的返回结果。
Hibernate save()–>insert语句 翻译过程 效率非常低、SQL语句不灵活
MyBatis也是一款ORM思想的实现框架,底层也是封装的JDBC。
MyBatis是一款"半自动的"ORM框架. MyBatis也会执行SQL,返回结果。具体的SQL语句需要开发人员自己写。 灵活 效率高。
MyBatis在2010年之前叫IBatis,属于ASF(apache software foundation),后来退出ASF,改名为MyBatis。
文档地址:
https://mybatis.org/mybatis-3/zh/configuration.html
MyBatis中有两类配置文件:
mybatis-config.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>
<!--引入外部的配置文件-->
<properties resource="db.properties"></properties>
<settings><!--logImpl:LOG4J 采用log4j做日志-->
<setting name="logImpl" value="LOG4J"></setting>
</settings>
<typeAliases>
<!--注册别名 所有需要完成包名+类名的地方都可以通过 别名来替换-->
<!--<typeAlias type="com.etoak.student.entity.Student" alias="stu"></typeAlias>
<typeAlias type="com.etoak.student.entity.School" alias="sch"></typeAlias>-->
<!--给指定的包及其子包起别名 别名默认是:类名字首字母小写 ,可以通过@Alias注解修改默认规则-->
<package name="com.etoak.student.entity"/>
</typeAliases>
<environments default="m">
<environment id="m">
<!--事务管理器:JDBC:代表使用JDBC的方式管理事务
Connection.setAutoCommit();
Connection.commit();/rollback()
-->
<transactionManager type="JDBC"></transactionManager>
<!--POOLED:代表采用MyBatis使用了连接池方式实现的数据源-->
<dataSource type="POOLED">
<property name="driver" value="${m.driver}"></property>
<property name="url" value="${m.url}"></property>
<property name="username" value="${m.user}"></property>
<property name="password" value="${m.pwd}"></property>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="StudentMapper.xml" />
</mappers>
</configuration>
XXMapper.xml
<?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.et">
<!--
insert: 执行 insert语句 executeUpdate
-->
<insert id="addStu" parameterType="com.etoak.student.pojo.Student">
insert into student( name, age, birth, email, schid)
values(#{name},#{age},#{birth},#{email},#{schid})
</insert>
<!--
select:执行查询
-->
<select id="queryStuById" parameterType="int"
resultType="com.etoak.student.pojo.Student">
select * from student where id=#{id}
</select>
<!--
UPDATE executeUpdate
-->
<update id="updateStu" >
update student set name=#{name},age=#{age},birth=#{birth},
email=#{email} where id=#{id}
</update>
<!--
delete executeUpdate
-->
<delete id="deleteStu" >
delete from student where id=#{id}
</delete>
<select id="queryAll" resultType="com.etoak.student.pojo.Student">
select * from student
</select>
</mapper>
基础操作
session.insert(SQL语句id,参数)
session.update(SQL语句id,参数)
session.delete(SQL语句id,参数)
session.selectOne(SQL语句id,参数)
session.selectList(SQL语句id,参数)
#{类中的属性不是表中的字段}
起别名
<select id="queryById" parameterType="int"
resultType="stu">
select
s_id as id,
s_name name,
s_age age,
s_birth birth,
s_email as email,
s_schid as schid
from tb_stu where s_id=#{id}
</select>
使用resultMap
<resultMap id="rMap_stu" type="stu">
<id property="id" column="s_id"></id>
<result property="name" column="s_name"></result>
<result property="age" column="s_age"></result>
<result property="birth" column="s_birth"></result>
<result property="email" column="s_email"></result>
<result property="schid" column="s_schid"></result>
</resultMap>
<select id="queryById" parameterType="int" resultMap="rMap_stu">
select * from tb_stu where s_id=#{id}
</select>
Map
@Param
对象
List<Student> querySome1(@Param("start")int startadadfa,
@Param("pageSize") int pageSizeasdfadf);
List<Student> querySome(Map<String,Object> map);
使用useGeneratedKeys +keyProperty属性
<insert id="addStudent" parameterType="stu" useGeneratedKeys="true"
keyProperty="id" keyColumn="s_id" >
insert into tb_stu( s_name, s_age, s_birth, s_email, s_schid)
values(#{name},#{age},#{birth},#{email},#{schid})
</insert>
selectKey
<insert id="addStudent" parameterType="stu" >
<selectKey keyProperty="id" keyColumn="s_id" resultType="int"
order="AFTER">
select last_insert_id()
<!-- select replace(uuid(),'-','')-->
</selectKey>
insert into tb_stu( s_name, s_age, s_birth, s_email, s_schid)
values(#{name},#{age},#{birth},#{email},#{schid})
</insert>
使用就是动态标签 foreach
<insert id="addStus1" parameterType="list">
insert into tb_stu(s_name, s_age, s_birth, s_email, s_schid)
values
<foreach collection="list" item="s" separator=",">
(#{s.name},#{s.age},#{s.birth},#{s.email},#{s.schid})
</foreach>
</insert>
<insert id="addStus" parameterType="list">
insert into tb_stu(s_name, s_age, s_birth, s_email, s_schid)
<foreach collection="list" item="s" separator=" union ">
(select #{s.name},#{s.age},#{s.birth},#{s.email},#{s.schid} )
</foreach>
</insert>
1.#底层使用的是预编译的Statement,即:PreparedStatement,支持?占位符的。$:底层使用的是普通的Statement,不支持?占位符的,参数只能拼接。
2.有些情况不能使用?占位:
参考JDBC :PrearedStatement和Statement的区别。
where
if
<select id="queryByConditions1" resultMap="rMap_stu">
select * from tb_stu
<where>
<if test="name!=null and name!='' ">
and s_name like '%${name}%'
</if >
<if test="email!=null and email!='' ">
and s_email=#{email}
</if>
</where>
</select>
foreach
<insert id="addStus1" parameterType="list">
insert into tb_stu(s_name, s_age, s_birth, s_email, s_schid)
values
<foreach collection="list" item="s" separator=",">
(#{s.name},#{s.age},#{s.birth},#{s.email},#{s.schid})
</foreach>
</insert>
<insert id="addStus" parameterType="list">
insert into tb_stu(s_name, s_age, s_birth, s_email, s_schid)
<foreach collection="list" item="s" separator=" union ">
(select #{s.name},#{s.age},#{s.birth},#{s.email},#{s.schid} )
</foreach>
</insert>
trim
<select id="queryByConditions" resultMap="rMap_stu">
select * from tb_stu
<!--prefix:前缀 prefixOverrides:前边遇到什么内容干掉-->
<trim prefix="where" prefixOverrides="and">
<if test="name!=null and name!='' ">
and s_name like '%${name}%'
</if >
<if test="email!=null and email!='' ">
and s_email=#{email}
</if>
</trim>
</select>
chose…when.otherwise
<select id="queryByConditions" resultMap="rMap_stu">
select * from tb_stu
<!--prefix:前缀 prefixOverrides:前边遇到什么内容干掉-->
<trim prefix="where" prefixOverrides="and">
<choose>
<when test="name!=null and name!='' ">
and s_name like '%${name}%'
</when>
<otherwise>
and s_email=#{email}
</otherwise>
</choose>
</trim>
</select>
association
<resultMap id="rMap_stu_sch" type="stu">
<id property="id" column="s_id"></id>
<result property="name" column="s_name"></result>
<result property="age" column="s_age"></result>
<result property="birth" column="s_birth"></result>
<result property="email" column="s_email"></result>
<result property="schid" column="s_schid"></result>
<!--association:一对一关联
property:类中的属性 javaType:属性的类型-->
<association property="sch" javaType="com.etoak.student.entity.School">
<id property="id" column="id"></id>
<result property="name" column="name"></result>
<result property="phone" column="phone"></result>
<result property="info" column="info"></result>
</association>
</resultMap>
<select id="queryByIdWithSch" resultMap="rMap_stu_sch">
select
s_id, s_name, s_age, s_birth, s_email, s_schid,
sch.id, sch.name, sch.phone,sch.info
from tb_stu s left join school sch
on s.s_schid = sch.id where s.s_id=#{id}
</select>
collection:一对多
<resultMap id="rMap_sch" type="com.etoak.student.entity.School">
<id property="id" column="id"></id>
<result property="name" column="name"></result>
<result property="phone" column="phone"></result>
<result property="info" column="info"></result>
<!--
collection:表示集合 List /set都可以
property:类中的属性
ofType:集合中每一个元素的类型
-->
<collection property="stus" ofType="stu">
<id property="id" column="s_id"></id>
<result property="name" column="s_name"></result>
<result property="age" column="s_age"></result>
<result property="birth" column="s_birth"></result>
<result property="email" column="s_email"></result>
<result property="schid" column="s_schid"></result>
</collection>
</resultMap>
<select id="querySchWithStus" resultMap="rMap_sch">
select sch.id, sch.name, sch.phone,sch.info,
s_id, s_name, s_age, s_birth, s_email, s_schid
from school sch left join tb_stu s on s.s_schid = sch.id
where sch.id=#{id}
</select>
代表SQL映射文件中的标签
其中的属性:
StatementType:执行器的类型 枚举
STATEMENT:普通的执行器
PREPARED:预编译的执行器
CALLABLE:执行触发器的执行器
ResultSetType:结果集的类型 枚举
DEFAULT(-1):默认的结果集
FORWARD_ONLY(1003):不可滚动的结果集
SCROLL_INSENSITIVE(1004):可滚动结果集
SCROLL_SENSITIVE(1005):可滚动的结果集
SqlCommandType:SQL语句的类型 枚举
INSERT/UPDATE/DELETE/SELECT/UNKNOWN
SqlSource:解析SQL语句的方法+获得SQL的方法
其中有一个方法getBoundSql:BoundSql真正代表SQL语句
TypeAliasRegistry构造时默认注册一些别名: int string list
new Configuration():中 自动添加别名 如:JDBC POOLED LOG4J
我们写的别名
1. <typeAlias type="" alias="">
2. <typeAliasPackage value="">
代表解析器。解析XML的。
其中主要属性和构造方法
public abstract class BaseBuilder{
protected final Configuration configuration;
protected final TypeAliasRegistry typeAliasRegistry;
protected final TypeHandlerRegistry typeHandlerRegistry;
public BaseBuilder(Configuration configuration) {
this.configuration = configuration;
this.typeAliasRegistry = this.configuration.getTypeAliasRegistry();
this.typeHandlerRegistry = this.configuration.getTypeHandlerRegistry();
}
BaseBuilder有很多子类:
XMLConfigBuilder:解析mybatis-config.xml
1.XMLConfigBuilder中 调用 XMLMapperBuilder解析 Mapper.xml,
2.然后再XMLMapperBuilder 调用XMLStatementBuilder专门解析元素中的每一个属性和内容
2.然后再XMLStatementBuilder中调用XMLScriptBuilder 构造SQL语句 BoundSql===》SqlSource
原因: SQL语句映射文件中没有DAO层调用的语句。
A query was run and no Result Maps were found for the Mapped Statement ‘com.et2203.queryById’. It’s likely that neither a Result Type nor a Result Map was specified.
原因:执行的是查询语句,没有resultType或者resultMap。
Caused by: org.apache.ibatis.binding.BindingException: Parameter ‘start’ not found. Available parameters are [arg1, arg0, param1, param2]
原因:传递多个参数MyBatis默认不会按照形参去命名,而是自动命名为:arg0,arg1…或者param1 param2…