标签:git 对象类型 转换 listen sources jar 原理 线程 import
Create database 数据库名 default character set utf8
Createtable 表名(
列名 类型 约束 auto_increament comment "备注"
);
/** */
/* */
或//
C: Controller 控制器,现在使用servlet
先设计数据库
再写实体类:用于封装数据
持久层DAO
业务逻辑
控制器
视图
常用概念
类库:提供的类没有封装一定逻辑。
举例:类库就是名言警句,写作文时引入名言警句
框架:区别于类库,里面有一些约束。
举例:框架是填空题
Mybatis 开源免费框架。原名叫 iBatis,2010 在 google code,2013 年迁移到 github
包名 | 作用 |
---|---|
mybatis.jar | MyBatis 的核心包 |
mysql-connector-java.jar | MySQL 驱动包 |
cglib.jar | 动态代理包 |
asm.jar | cglib 依赖包 |
javassist-GA.jar | cglib 依赖包(负责字节码解析的包) |
commons-logging.jar | 日志包 |
log4j.jar | 日志包 |
log4j-api.jar | 日志包 |
log4j-core.jar | 日志包 |
slf4j-api.jar | 日志包 |
slf4j-log4j.jar | 日志包 |
<?xml version="1.0" encoding="UTF-8"?>
<!--注意这里是 configuration ,下面为 mybatis-3-config -->
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- default 为引用 environment 的 id,即当前所使用的环境 -->
<environments default="default">
<!-- 声明可以使用的环境 -->
<environment id="default">
<!-- 使用原生 JDBC 事务 -->
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/数据库名"/>
<property name="username" value="root"/>
<property name="password" value="GJXAIOU"/>
</dataSource>
</environment>
</environments>
<mappers>
<!-- 配置实体类 Mapper 文件,一般使用 package -->
<mapper resource="com/mapper/FlowerMapper.xml"/>
</mappers>
</configuration>
注: mybatis.xml 中的 <mappers>
中配置的 resource 是整个项目中的所有其他 实体类Mapper.xml
文件;
mappers 标签下有许多 mapper 标签,每一个 mapper 标签中配置的都是一个独立的映射配置文件的路径,配置方式有以下几种。
第一种:使用相对路径进行配置。示例代码如下:
<mappers>
<mapper resource="org/mybatis/mappers/UserMapper.xml"/>
<mapper resource="org/mybatis/mappers/ProductMapper.xml"/>
<mapper resource="org/mybatis/mappers/ManagerMapper.xml"/>
</mappers>
第二种:使用绝对路径进行配置。示例代码如下:
<mappers>
<mapper url="file:///var/mappers/UserMapper.xml"/>
<mapper url="file:///var/mappers/ProductMapper.xml"/>
<mapper url="file:///var/mappers/ManagerMapper.xml"/>
</mappers>
第三种:使用接口信息进行配置。示例代码如下:
<mappers>
<mapper class="org.mybatis.mappers.UserMapper"/>
<mapper class="org.mybatis.mappers.ProductMapper"/>
<mapper class="org.mybatis.mappers.ManagerMapper"/>
</mappers>
第四种:使用接口所在包进行配置。示例如下:
<mappers>
<package name="org.mybatis.mappers"/>
</mappers>
实体类名+Mapper.xml
FlowerMapper.xml 文件内容为:【注意抬头中的信息不同,将上面抬头中的 config 全部换为 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">
<!-- namespace:理解成实现类的全路径(包名+类名),用于绑定 Dao 接口(即面向接口编程),使用 namespace 之后就不用写实现类,业务逻辑会直接通过这个绑定寻找到对应点的 SQL 语句进行对应的数据处理 -->
<mapper namespace="a.b" >
<!-- 如果方法返回值是list,在resultType中写List的泛型,因为mybatis
对jdbc封装,一行一行读取数据-->
<!--id:表示方法名; parameterType:定义参数类型;resultType:返回值类型 -->
<select id="selAll" resultType="com.pojo.Flower">
select * from flower
</select>
</mapper>
import com.pojo.Flower;
public class Test {
public static void main(String[] args) throws IOException {
InputStream is = Resources.getResourceAsStream("mybatis.xml");
//使用工厂设计模式
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
//生产SqlSession
SqlSession session=factory.openSession();
List<Flower> list = session.selectList("a.b.selAll");
for (Flower flower : list) {
System.out.println(flower.toString());
}
session.close();
}
}
全局配置文件中内容
<transactionManager/>
type 属性可取值如下:
setAutoMapping(false)
;<dataSouce/>
type 属性可取值如下:
<?xml version="1.0" encoding="UTF-8"?>
<Context>
<Resource
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/lianxi"
username="root"
password="moyue"
maxActive="50"
maxIdle="20"
name="test"
auth="Container"
maxWait="10000"
type="javax.sql.DataSource"
/>
</Context>
@WebServlet("/pool")
public class DemoServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
try {
Context cxt = new InitialContext();
DataSource ds = (DataSource) cxt.lookup("java:comp/env/test");
Connection conn = ds.getConnection();
PreparedStatement ps = conn.prepareStatement("select * from flower");
ResultSet rs = ps.executeQuery();
res.setContentType("text/html;charset=utf-8");
PrintWriter out = res.getWriter();
while(rs.next()){
out.print(rs.getInt(1)+" "+rs.getString(2)+"<br/>");
}
out.flush();
out.close();
rs.close();
} catch (NamingException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
selectList()
返回值为 List<resultType 属性控制>
适用于查询结果都需要遍历的需求
selectOne()
返回值 Object
适用于返回结果只是变量或一行数据时
selectMap()
返回值 Map<key,resultType 属性控制>
public class Test {
public static void main(String[] args) throws IOException {
/** MyBatis 默认不加载配置文件,因此需要先加载配置文件,返回整个配置文件的流对象;
* 在数据访问层处理异常和在控制器中处理异常,一般在 service 中只抛出异常;
*/
InputStream is = Resources.getResourceAsStream("mybatis.xml");
// 使用工厂设计模式
// 前面是工厂 实例化工厂对象时使用的是构建者设计模式 它的名称标志:后面有Builder
// 构建者设计模式意义: 简化对象实例化过程
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
// 生产 SqlSession, 整个 sqlsession 就是 MyBatis 中 API 封装的对象,增删改查都在里面
SqlSession session=factory.openSession();
// selectList
List<Flower> list = session.selectList("a.b.selAll");
for (Flower flower : list) {
System.out.println(flower.toString());
}
// selectOne
int count = session.selectOne("a.b.selById");
System.out.println(count);
// selectMap
// 把数据库中哪个列的值当作 map 的 key
Map<Object, Object> map = session.selectMap("a.b.c", "name123");
System.out.println(map);
session.close();
}
}
对应的 实体类 Mapper.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="a.b" >
<select id="selAll" resultType="com.pojo.Flower">
select id,name name123,price,production from flower
</select>
// 这里的 int 相当于 Ingeter
<select id="selById" resultType="int">
select count(*) from flower
</select>
<select id="c" resultType="com.pojo.Flower">
select id,name name123,price,production from flower
</select>
</mapper>
@XXXX(属性名= 值)
属性名=值
;属性名={值,值}
;
属性名=@名称
编写路径为了告诉编译器如何找到其他资源;
<img/> <script/>
,<style/>
,location.href 等/都表示服务器根目录(tomcat/webapps 文件夹)由 apache 推出的开源免费日志处理的类库;
// 遇到什么级别才输出以及输出位置:调试信息输出, 输出到控制台,输出到 log 文件
log4j.rootCategory=DEBUG, CONSOLE, LOGFILE
// 向控制台输出相关的配置
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout log4j.appender.CONSOLE.layout.ConversionPattern=%C %d{YYYY-MM-dd hh:mm:ss}%m %n
// 向日志文件输出的相关的配置
log4j.appender.LOGFILE=org.apache.log4j.FileAppender log4j.appender.LOGFILE.File=E:/my.log
log4j.appender.LOGFILE.Append=true log4j.appender.LOGFILE.layout=org.apache.log4j.Patter nLayout log4j.appender.LOGFILE.layout.ConversionPattern=%C %m %L %n
在实际使用:新建一个类,例如:Test类
Logger logger = Logger.getLogger(Test.class);
// 这里以 debug 为例,具体的方法看上面输出级别调用不同的方法
logger.debug("这是调试信息");
使用方法二:
在 catch 中 : logger.error(e.getMessage());
即可,注意在log4j配置文件中加上相关的表达式;
<settings>
标签==该标签必须配置在最前面==
<settings>
标签控制 mybatis 全局开关<settings>
<setting name="logImpl" value="LOG4J"/>
</settings>
<mapper>namespace 属性中除了最后一个类名
namespace=”com.mapper.PeopleMapper”
其中包级别为 com.mapper
,需要在 log4j.propeties
中做两件事情传递多个参数时候,可以使用对象或者 map,和第二部分的多参数实现方法;
在 XXXMapper.xml 中<select>
<delete>
等标签的 parameterType
可以控制参数类型(例如可以传入 select 语句的参数,控制输入参数的类型)
selectList()
和 selectOne()
的第二个参数和 selectMap()
的第三个参数都表示方法的参数 。
People p = session.selectOne("a.b.selById",1);
System.out.println(p);
#{}
获取参数(代码见下)
parameterType
控制参数类型#{}
获取参数内容
#{0}
表示第一个参数(尽量不使用这个方法)#{param1}
,表示第一个参数#{}
里面内容没有要求只要写内容即可。#{属性名}
#{key}
:当需要传递多个参数时候,目前只能使用 map 或者对象<select id="selById"
resultType="com.pojo.People" parameterType="int">
select * from people where id=#{0}
</select>
#{}
和 ${}
的 区 别
#{}
获取参数的内容,支持索引获取,或者使用 param1 获取指定位置参数,并且 SQL 使用?占位符${}
字符串拼接,不使用?,默认找${内容}
内容的 get/set 方法,如果写数字,就是一个数字配置示例:
PeopleMapper.xml
<select id="test" resultType="com.pojo.People" parameterType="com.pojo.People">
select * from people where id = ${id}
</select>
Test.java
People peo =new People();
peo.setId(1);
People p = session.selectOne("a.b.selById",people);
如果在 xml 文件中出现 “<” , “>” ,双引号 等特殊字符时可以使用 XML 文件转义标签(XML 自身的),格式为:<![CDATA[ 内 容 ]]>
? 中不允许在关键字前后进行数学运算,需要在代码中计算完成后传递到 mapper.xml 中;
Java 中代码为:
//显示几个
int pageSize = 2;
//第几页
int pageNumber = 2;
//如果希望传递多个参数,可以使用对象或map
Map<String,Object> map = new HashMap<>();
map.put("pageSize", pageSize);
map.put("pageStart", pageSize*(pageNumber-1));
List<People> p = session.selectList("a.b.page",map);
mapper.xml 中代码为:
<select id="page" resultType="com.pojo.People" parameterType="map">
select * from people limit #{pageStart},#{pageSize}
</select>
==别名配置必须在 <environments>
前面==
一共有三类:分别是系统内置的别名,给某个类的别名,
<typeAliases>
<typeAlias type="com.pojo.People" alias="peo"/>
</typeAliases>
mapper.xml 中内容为:
<select id="page" resultType="peo" parameterType="map">
select * from people limit #{pageStart},#{pageSize}
</select>
<typeAliases>
<package name="com.pojo" />
</typeAliases>
<select id="page" resultType="People" parameterType="map">
select * from people limit #{pageStart},#{pageSize}
</select>
session.commit()
提交事务.openSession(true);
自动提交底层为:.setAutoCommit(true);
<insert> <delete> <update>
标签没有 resultType 属性,认为返回值都是 int。session.rollback()
回滚事务.<insert>
标签,标签没有返回值类型session.insert()
调用新增方法mapper.xml 值为;
<insert id="ins" parameterType="People">
insert into people values(default,#{name},#{age})
</insert>
int index1 = session.insert("a.b.ins", p);
if(index1>0){
System.out.println("成功");
}else{
System.out.println("失败");
}
<update>
标签<update id="upd" parameterType="People">
update people set name = #{name} where id = #{id}
</update>
People peo = new People();
peo.setId(3);
peo.setName("王五");
int index = session.update("a.b.upd", peo);
if(index>0){
System.out.println("成功");
}else{
System.out.println("失败");
}
session.commit();
<delete>
标签<delete id="del" parameterType="int">
delete from people where id = #{0}
</delete>
int del = session.delete("a.b.del",3);
if(del>0){
System.out.println("成功");
}else{
System.out.println("失败");
}
session.commit();
作用: 实现创建一个接口后把 mapper.xml 由mybatis 生成接口的实现类,通过调用接口对象就可以获取 mapper.xml 中编写的 sql。后面 mybatis 和 spring 整合时使用的是这个方案.
LogMapper
<mapper>
namespace 相同com.mapper
包下面包含一个接口:LogMapper
和LogMapper.xml
,然后 LogMapper.xml
中的<mapper>
namespace 标签格式为:<mapper namespace = "com.mapper.LogMapper> </mapper>
<package>
进行扫描接口和 mapper.xml;<mappers>
下使用<package>
<mappers>
<package name="com.mapper"/>
</mappers>
com.mapper
包下新建接口:LogMapper
public interface LogMapper {
List<Log> selAll();
}
com.mapper
中新建一个 LogMapper.xml
<mapper namespace="com.mapper.LogMapper">
<select id="selAll" resultType="log">
select * from log
</select>
</mapper>
绑定的使用:在其它 Java 类中
public class Test {
public static void main(String[] args) throws IOException {
InputStream is = Resources.getResourceAsStream("mybatis.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
SqlSession session = factory.openSession();
LogMapper logMapper = session.getMapper(LogMapper.class);
List<Log> list = logMapper.selAll();
for (Log log : list) {
System.out.println(log);
}
一共有两种方法:一般方法和使用注解
LogMapper
中声明方法List<Log> selByAccInAccout(String accin, String accout);
然后在 LogMapper.xml 中添加即可,#{}
中可以使用 param1,param2
<select id="selByAccInAccout" resultType="log">
select * from log where accin=#{param1} and accout=#{param2}
</select>
/**
mybatis 把参数转换为 map 了,其中@Param("key") 参数内容就是 map 的 value
*/
List<Log> selByAccInAccout(@Param("accin") String accin123,@Param("accout") String accout3454235);
然后在 mapper.xml 中添加
<!-- 当多参数时,不需要写 parameterType -->
<select id="selByAccInAccout" resultType="log" >
select * from log where accin=#{accin} and accout=#{accout}
</select>
注:#{}
里面写@Param(“内容”)参数中内容。
多参数的使用
当然 log 是存在数据库中的一个表中,同时要新建实体类的;
在其它 Java 类中使用:
public class Test {
public static void main(String[] args) throws IOException {
InputStream is = Resources.getResourceAsStream("mybatis.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
SqlSession session = factory.openSession();
LogMapper logMapper = session.getMapper(LogMapper.class);
List<Log> list = logMapper.selByAccInAccout("3", "1");
for (Log log : list) {
System.out.println(log);
}
session.close();
System.out.println("程序执行结束");
}
}
MyBatis 中动态 SQL 的实现是在 实体类mapper.xml
中添加逻辑判断即可。
注:以下的 xml 配置均在 LogMapper.xml 中;
<select id="selByAccinAccout" resultType="log">
select * from log where 1=1
<!-- OGNL 表达式,直接写 key 或对象的属性.不需要添加任何特字符号,这里的 and 执行的时候都会被转换为 & -->
<if test = "accin != null and accin != ''">
and accin = #{accin}
</if>
<if test= "accout != null and accout != ''">
and accout=#{accout}
</if>
</select>
如果 <where>
中有内容会生成 where 关键字,如果没有内容不生成 where 关键字;
使用示例 :效果:比直接使用 <if>
少写了 where 1 = 1;
<select id="selByAccinAccout" resultType="log">
select * from log
<where>
<if test="accin!=null and accin!=''">
and accin=#{accin}
</if>
<if test="accout!=null and accout!=''">
and accout=#{accout}
</if>
</where>
</select>
只要有一个成立,其他都不执行;
代码示例
如果 accin 和 accout 都不是 null 或不是””生成的 sql 中只有 where accin=?
<select id = "selByAccinAccout" resultType = "log">
select * from log
<where>
<choose>
<when test = "accin != null and accin != ''">
and accin = #{accin}
</when>
<when test = "accout != null and accout != ''">
and accout = #{accout}
</when>
</choose>
</where>
</select>
作用:去掉最后一个逗号
<set>
用在修改 SQL 中 set 从句,如果<set>
里面有内容则生成 set 关键字,没有就不生成
示例
其中:id=#{id}
目的防止<set>
中没有内容,mybatis 不生成 set 关键字,如果修改中没有 set 从句 SQL 语法错误.
<update id="upd" parameterType="log" >
update log
<set>
id=#{id},
<if test="accIn!=null and accIn!=''">
accin=#{accIn},
</if>
<if test="accOut!=null and accOut!=''">
accout=#{accOut},
</if>
</set>
where id=#{id}
</update>
里面的主要方法如下:
suffixOverrieds 去掉后面内容
执行顺序:首先去掉内容然后添加内容;
代码示例
<update id = "upd" parameterType = "log">
update log
<trim prefix = "set" suffixOverrides = ",">
a = a,
</trim>
where id=100
</update>
%
然后执行语句;见示例<select id="selByLog" parameterType="log" resultType="log">
<bind name="accin" value="'%'+accin+'%'"/>
#{money}
</select>
用于循环参数内容,还具备在内容的前后添加内容,以及添加分隔符功能;
适用场景:主要用于 in
查询以及批量新增中(但是 mybatis 中 foreach 效率比较低)
批量新增操作:
默认的批量新增的 SQL 语句为:insert into log VALUES (default,1,2,3),(default,2,3,4),(default,3,4,5)
在执行批处理的时候,需要将 openSession()必须指定下面命令
factory.openSession(ExecutorType.BATCH);
,这里底层 是 JDBC 的 PreparedStatement.addBatch();
#{迭代变量名}
获取内容<select id="selIn" parameterType="list" resultType="log">
select * from log where id in
<foreach collection="list" item="abc" open="(" close=")" separator=",">
#{abc}
</foreach>
</select>
<sql>
和 <include>
搭配使用<sql>
定义这个片段;<sql id="mysql">
id,accin,accout,money
</sql>
<select>
或 <delete>
或 <update>
或 <insert>
中使用 <include>
引用<select id="">
select <include refid="mysql"></include>
from log
</select>
主要优化 service中的方法
线程容器:给线程绑定一个 Object 内容后只要线程不变,可以随时取出。但是一旦改变线程,无法取出内容。
final ThreadLocal<String> threadLocal = ThreadLocal<>();
threadLocal.set("测试");
new Thread(){
public void run() {
String result = threadLocal.get();
System.out.println("结果:"+result);
};
}.start();
<select>
时,只有第一次访问数据库,第一次之后把查询结果缓存到 SqlSession 缓存区(内存)中<select>
)
<select>
对应一个 statement 对象<cache readOnly = "true"></cache>
一共三种方式
Auto Mapping
特性,在实现两表联合查询时通过别名完成映射;<resultMap>
标签进行实现;相当于现在直接设置映射关系,进行两者(SQL 查询结果和实体类之间)的匹配。
<resultMap>
标签写在 实体类Mapper.xml
中,由程序员控制SQL 查询结果与实体类的映射关系;
默认 MyBatis 使用 Auto Mapping
特性进行映射:即保持查询的数据库中的列名和实体类中的属性名相同即可;
使用 <resultMap>
标签时,<select>
标签不写 resultType 属性,而是使用 resultMap 属性来引用<resultMap>
标签.
首先进行数据库设计
示例:数据库表 teacher 中两个字段: id、name
然后进行实体类设计
public class Teacher{
private int id1;
private String name1;
}
<!-- 其中 type 的值为返回值类型-->
<resultMap type="teacher" id="mymap">
<!-- 主键使用id 标签配置映射关系-->
<!-- column 值为数据库中列名; property 值为实体类中的属性名 -->
<id column="id" property="id1" />
<!-- 其他列使用result 标签配置映射关系-->
<result column="name" property="name1"/>
</resultMap>
<select id="selAll" resultMap="mymap">
select * from teacher
</select>
上面代码如果使用原来的数据库中字段的名称和实体类相同的话,代码如下:
<select id = "selAll" resultType = "teacher">
select * from teacher
</select>
public class Student {
private int id;
private String name;
private int age;
private int tid;
private Teacher teacher;
// 该 POJO 类中其他信息省略
}
<select id="selById" resultType="teacher" parameterType="int">
select * from teacher where id=#{0}
</select>
最后在下面的 StudentMapper.xml 中完成装配
<association>
表示当装配一个对象时使用property
: 是对象在类中的属性名select
:通过哪个查询查询出这个对象的信息column
: 把当前表的哪个列的值做为参数传递给另一个查询大前提使用 N+1 方式时:如果列名和属性名相同可以不配置,使用 Auto mapping 特性.但是 mybatis 默认只会给列装配一次
<resultMap type="student" id="stuMap">
<id property="id" column="id"/>
<result property="name" column="name"/>
<result property="age" column="age"/>
<result property="tid" column="tid"/>
<!-- 如果关联一个对象,使用 association 标签,调用 teacher 中的查询,如果关联多个对象,使用 collection 标签 -->
// 老师查询中需要一个 Int 类型的参数,这里要通过 column 告诉他传入哪一列的值
<association property="teacher" select="com.mapper.TeacherMapper.selById" column="tid">
</association>
</resultMap>
<select id="selAll" resultMap="stuMap">
select * from student
</select>
<resultMap type="student" id="stuMap">
<result column="tid" property="tid"/>
<!-- 如果关联一个对象-->
<association property="teacher"
select="com.mapper.TeacherMapper.selById"
column="tid"></association>
</resultMap>
<select id="selAll" resultMap="stuMap">
select * from student
</select>
<association/>
只要装配 一个对象就用这个标签<association/>
小的javaType
属性:<resultMap type="Student" id="stuMap1">
<id column="sid" property="id"/>
<result column="sname" property="name"/>
<result column="age" property="age"/>
<result column="tid" property="tid"/>
<association property="teacher" javaType="Teacher" >
<id column="tid" property="id"/>
<result column="tname" property="name"/>
</association>
</resultMap>
<select id="selAll1" resultMap="stuMap1">
select s.id sid,s.name sname,age age,t.id tid,t.name tname FROM student s left outer join teacher t on s.tid=t.id
</select>
select * from 学生
select * from 老师 where id=学生的外键
使用多条 SQL 命令查询两表数据时,如果希望把需要的数据都查询出来,需要执行 N+1 条 SQL 才能把所有数据库查询出来;
优点:如果有的时候不需要查询学生是同时查询老师,只需要执行一个 select * from student;
适用场景: 有的时候需要查询学生同时查询老师,有的时候只需要查询学生.
<resultMap>
查询关联集合对象(N+1 方式)实现查询老师的时候,把关联的学生也查询出来
以为老师和学生是一对多的关系,因此查询结果是一个集合;
public class Teacher {
private int id;
private String name;
private List<Student> list;
// 省略其他 get、set 方法
}
<select id="selByTid" parameterType="int" resultType="student">
select * from student where tid=#{0}
</select>
<collection/>
是当属性是集合类型时使用的标签;<resultMap type="teacher" id="mymap">
<id column="id" property="id"/>
<result column="name" property="name"/>
<collection property="list" select="com.mapper.StudentMapper.selByTid" column="id">
</collection>
</resultMap>
<select id="selAll" resultMap="mymap">
select * from teacher
</select>
<resultMap>
实现加载集合数据(联合查询方式)<resultMap type="teacher" id="mymap1">
<id column="tid" property="id"/>
<result column="tname" property="name"/>
<collection property="list" ofType="student" >
<id column="sid" property="id"/>
<result column="sname" property="name"/>
<result column="age" property="age"/>
<result column="tid" property="tid"/>
</collection>
</resultMap>
<select id="selAll1" resultMap="mymap1">
select t.id tid,t.name tname,s.id sid,s.name sname,age,tid from teacher t LEFT JOIN student s on t.id=s.tid;
</select>
只能查询对象,查询结合只能使用上面的方法
.
在 SQL 是关键字符,因此两侧添加反单引号;<select id="selAll" resultType="student">
select t.id `teacher.id`, t.name `teacher.name`, s.id id, s.name name, age, tid from student s LEFT JOIN teacher t on t.id=s.tid
</select>
注解是写在类中的,不是XML中的,相当于将 实体类Mapper.xml 中的内容直接在对应的接口中实现即可,不在需要 实体类Mapper.xml 文件。
实体类Mapper.xml
文件;
mapper.xml 和注解可以共存.
<package/>
<mapper class=””/>
可以在测试的时候使用下面:因为是接口:
TeacherMapper tm = session.getMapper(TeachterMapper.class)
List<Teacher> = tm.selAll(info)
下面语句直接在 TeacherMapper.java 接口中书写即可
@Select("select * from teacher")
List<Teacher> selAll();
@Insert("insert into teacher values(default,#{name})")
int insTeacher(Teacher teacher);
@Update("update teacher set name=#{name} where id=#{id}")
int updTeacher(Teacher teacher);
@Delete("delete from teacher where id=#{0}")
int delById(int id);
使用注解实现
以 N+1 举例
@Select("select * from student where tid=#{0}")
List<Student> selByTid(int tid);
@Results(value={
@Result(id=true,property="id",column="id"),
@Result(property="name",column="name"),
@Result(property="list",column="id",many=@Many(select="com.mapper.StudentMapper.selByTid"))
})
@Select("select * from teacher")
List<Teacher> selTeacher();
Resources
: MyBatis 中 IO 流的工具类
SqlSessionFactoryBuilder()
: 构建器
XMLConfigBuilder
: MyBatis 全局配置文件内容构建器类
Configuration
: 封装了全局配置文件所有配置信息
DefaultSqlSessionFactory
: 是SqlSessionFactory 接口的实现类Transaction
: 事务类
TransactionFactory
: 事务工厂
Executor
: MyBatis 执行器
DefaultSqlSession
:是 SqlSession 接口的实现类ExceptionFactory
: MyBatis 中异常工厂在 MyBatis 运行开始时需要先通过 Resources 加载全局配置文件.下面需要实例化 SqlSessionFactoryBuilder 构建器.帮助 SqlSessionFactory 接口实现类 DefaultSqlSessionFactory.
在实例化 DefaultSqlSessionFactory 之前需要先创建 XmlConfigBuilder 解析全局配置文件流,并把解析结果存放在 Configuration 中.之后把Configuratin 传递给 DefaultSqlSessionFactory.到此 SqlSessionFactory 工厂创建成功.
由 SqlSessionFactory 工厂创建 SqlSession.
每次创建 SqlSession 时,都需要由 TransactionFactory 创建 Transaction 对象, 同时还需要创建 SqlSession 的执行器 Excutor, 最后实例化DefaultSqlSession,传递给 SqlSession 接口.
根据项目需求使用 SqlSession 接口中的 API 完成具体的事务操作. 如果事务执行失败,需要进行 rollback 回滚事务.
如果事务执行成功提交给数据库.关闭 SqlSession
到此就是 MyBatis 的运行原理.
标签:git 对象类型 转换 listen sources jar 原理 线程 import
原文地址:https://www.cnblogs.com/qq438649499/p/12128221.html