Mybatias
Mybatis
1.简介
1.1丶什么是Mybaties
MyBatis 是一款优秀的持久层框架,
它支持自定义 SQL、存储过程以及高级映射。
MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。
MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
如何获得Mybaties?
Maven仓库
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>x.x.x</version>
</dependency>
中文文档: mybatis – MyBatis 3 | 简介
1.2丶持久化
数据持久化
- 持久化就是将程序的数据在持久状态和瞬时状态转化的过程
- 内存:断电即失
- 数据库(JDBC),io文件都是持久化
1.3丶为什么需要mybaties
- 简单
- 传统的JDBC代码太过复杂。实现了简化,框架,自动化
- 优点:
- 简单易学
- 灵活
- sql和代码的分离,提高了可维护性
- 提供映射标签,支持对象和数据库的orm字段关系映射
- 提供对象关系映射标签,支持对象关系组建维护
- 提供xml标签,支持编写动态sql
最重要一点:用的人多
2.第一个mybaties程序:
思路:搭建环境==》导入mybaties ==》编写代码 ==》测试
2.1丶搭建环境
CREATE DATABASE mybaties;
USE mybaties;
CREATE TABLE `user`(
id INT NOT NULL,
`name` VARCHAR(20) NOT NULL,
`pwd` VARCHAR(30) NOT NULL,
PRIMARY KEY (id)
)
INSERT INTO `user` VALUE(1,'六的很','123'),(2,'lc','1234'),(3,'zyj','075');
SELECT * FROM `user`
创建父项目
创建一个普通的maven项目
删除src(因为我们不用,这个是父模块,只是用来导依赖的)
导入依赖(mybatis,mysql,junit)
<!-- mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.2</version>
</dependency>
<!-- mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-mxj-db-files</artifactId>
<version>5.0.12</version>
</dependency>
<!-- junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
2.2丶创建新模块
- 编写mytabis的核心配置文件
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="$jdbc://localhost:3306/mybaties?useSSL=true&characterEncoding=UTF-8&useUnicode=true&serverTimezone=GMT"/>
<property name="username" value="root"/>
<property name="password" value="123"/>
</dataSource>
编写mybatis工具类
//获取SqlSessionFactory(构建工厂)
public class MybatisUtils {
public static SqlSessionFactory sqlSessionFactory=null;
static{
InputStream inputStream = null;
try {
// 1.使用mybatis获取sqlsessionFactory对象
String resource = "org/mybatis/example/mybatis-config.xml";
inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
} }
// 从工厂里获取sqlsession对象,sqlsession里有执行sql的所有方法
public static SqlSession sqlSession(){
return sqlSessionFactory.openSession();
}
2.3丶编写代码
实体类
public class User {
private int id;
private String name;
private String pwd; public User() {
} public User(int id, String name, String pwd) {
this.id = id;
this.name = name;
this.pwd = pwd;
} 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 String getPwd() {
return pwd;
} public void setPwd(String pwd) {
this.pwd = pwd;
}
}Dao接口
public interface UserDao {
List<User> getUserList();
}
- 接口实现类(由原来的userDaoImpl转换成Mapeer配置xml文件)(注意命名空间中的包名要与Dao/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">
<!--命名空间绑定一个DAO/mapper接口-->
<mapper namespace="com.LiuDeHen.Dao.UserDao">
<!--查询语句,id:绑定接口的方法,resultTyle:返回值类型-->
<select id="getUserList" resultType="com.LiuDeHen.pojo.User">
SELECT * from mybaties.user;
</select>
</mapper>
2.4丶测试
我们一般使用第二种方法执行sql
错误1
org.apache.ibatis.binding.BindingException: Type interface com.LiuDeHen.Dao.UserDao is not known to the MapperRegistry.
MapperRegistry是什么?
需要在核心配置文件中注册mappers
<mappers>
<mapper resource="com/LiuDeHen/Dao/UserMapper.xml"/>
</mappers>
错误2: resource:
java.io.IOException: Could not find resource src/main/resources/mybatis-config.xml
这个不知道原因把resource直接="mybatis-config.xml" 不需要前面路径
错误3:Maven资源文件初始化错误,因为我们的资源文件放在了Dao包下,而Maven中约定大于配置,资源文件不放在resouce下,必须写一段build配置文件
java.lang.ExceptionInInitializerError
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
</build>
总结:
一下流程:
- 首先第一步,就是环境的配置
- mysql和mybatis的jar包
- 然后写mybatis的xml文件(不要忘了注册),mapper是驱动,也就是我们写的每一个mapper(就是我们原来的操作数据库类,现在是mapper.xml文件),并且绑定上mysql驱动,和我们的数据库(连接数据库)
- 到了这里,我们要去编写工具类,根据官方文档。工具类里会根据我们前面的mybatis.xml文件得到一个sqlSessionFactory工厂,使用这个工厂我们可以获取到SqlSession对象(操作sql所有的方法)
- 然后我们就需要去写实体类,与数据库要对应
- 接下来再写上Dao层的接口和mapper.xml文件(代替原来的Dao实现类),mapper文件绑定id到接口的方法,返回值类型为实体类
- 测试
- 后面的所有操作都只需要写mapper.xml里的sql语句了,实现了和java代码的解耦,提高维护性
我们需要了解的三个接口和类
3.CURD:
3.1丶流程
对应文档xml映射文件
编写接口
public interface UserDao {
// 查询
List<User> getUserList();
User getUserName(int id);
//添加
int setUserID(User user);
//修改
int Updateuser(User user);
//删除
int DeleteUser(User user);
}
编写mapper映射文件
<!--命名空间绑定一个DAO/mapper接口-->
<mapper namespace="com.LiuDeHen.Dao.UserDao">
<!-- 查询 -->
<select id="getUserList" resultType="com.LiuDeHen.pojo.User">
SELECT * from mybaties.user;
</select>
<select id="getUserName" parameterType="int" resultType="com.LiuDeHen.pojo.User">
SELECT * from mybaties.user where id=#{id};
</select>
<!--插入-->
<insert id="setUserID" parameterType="com.LiuDeHen.pojo.User">
insert into mybaties.user(id,`name`,pwd) values(#{id},#{name},#{pwd});
</insert>
<!--修改-->
<update id="Updateuser" parameterType="com.LiuDeHen.pojo.User">
update mybaties.user set id=#{id},`name`=#{name},pwd=#{pwd} where id=#{id};
</update>
<!--删除-->
<delete id="DeleteUser" parameterType="com.LiuDeHen.pojo.User" >
delete from mybaties.user where id=#{id};
</delete>
</mapper>
这里我们的参数不需要对象来调用是因为我们上面声明了对象,mybatis会自己查找
测试
@Test
public void test(){
// 1.获取sqlsession对象
SqlSession sqlSession = MybatisUtils.getsqlSession();
// 2.执行sql
UserDao mapper = sqlSession.getMapper(UserDao.class);
List<User> users = mapper.getUserList();
for (User user:users){
System.out.println(user);
}
// 3.关闭sqlsession
sqlSession.close();
}
@Test
public void getname(){
SqlSession sqlSession = MybatisUtils.getsqlSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);
User user = mapper.getUserName(1);
System.out.println(user);
user.getName();
}
//dml增删改,都需要提交事务
@Test
public void setUser(){
SqlSession sqlSession = MybatisUtils.getsqlSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);
int i = mapper.setUserID(new User(4,"nb","111"));
if (i>0){
// 提交事务
sqlSession.commit();
System.out.println(i);
}
sqlSession.close();
}
@Test
public void UpdateUser(){
SqlSession sqlSession = MybatisUtils.getsqlSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);
int i = mapper.Updateuser(new User(4, "哇咔咔", "123"));
if (i>0){
sqlSession.commit();
System.out.println("修改成功");
}
sqlSession.close();
}
@Test
public void deletUser(){
SqlSession sqlSession = MybatisUtils.getsqlSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);
int i = mapper.DeleteUser(new User(4));
if (i>0){
sqlSession.commit();
System.out.println("删除成功");
}
sqlSession.close();
}
注意点:
- 增删改(dml)都需要提交事务
分析错误:
- CRUD对应的标签不能写错
- 一个表对应一个接口(Dao接口),对应一个Dao类(现在是mapper映射文件),每一个mapper都需要mybatis里的resource对应
- 空指针
3.2丶万能Map:
好处:当你有表有100个字段,你又只想修改其中几个字段数据对吧,那你现在是不是只能去实体类增加这几个字段的构造器,或者你传100个参实现构造器,
而这里map就不需要啦,它可以想传几个都行,灵活
接口
int InsertUserID(Map<String,Object> map);//插入
User getUserName1(Map<String,Object> map);//查询
映射文件(这时,传参的名字不需要和实体类对应了,但传参时,string必须跟这里定义的名字一样)
<insert id="InsertUserID" parameterType="map">
insert into mybaties.user (id, name, pwd) values (#{id1},#{name1},#{pwd1})
</insert>
测试
插入 @Test
public void insertUser(){
SqlSession sqlSession = MybatisUtils.getsqlSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);
HashMap<String, Object> hashMap = new HashMap<>();
hashMap.put("id1",5);
hashMap.put("name1","zz");
hashMap.put("pwd1",123);
int i = mapper.InsertUserID(hashMap);
if (i>0){
sqlSession.commit();
System.out.println("插入成功");
}
}
查询 @Test
public void getUserName1() {
SqlSession sqlSession = MybatisUtils.getsqlSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);
HashMap<String, Object> id = new HashMap<String, Object>();
id.put("idMap", 1);
User userName1 = mapper.getUserName1(id);
System.out.println(userName1);
}
Map传递参数parameterType="map"
- 而对象传递参数,parameterType="Object"
- 单个参数直接用对象
- 多个参数用Map或者注解
3.3丶模糊查询:
在sql语句中
<select id="getMohuUser" parameterType="String" resultType="com.LiuDeHen.pojo.User">
select * from mybaties.user where name like concat('%', #{value}, '%')
</select>
@Test
public void getMohuUser(){
SqlSession sqlSession = MybatisUtils.getsqlSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);
List<User> user = mapper.getMohuUser("z");
for (User u:user){
System.out.println(u);
}
sqlSession.close();
}
在传入中
<select id="getMohuUser" parameterType="String" resultType="com.LiuDeHen.pojo.User">
select * from mybaties.user where name like #{value}
</select>
@Test
public void getMohuUser(){
SqlSession sqlSession = MybatisUtils.getsqlSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);
List<User> user = mapper.getMohuUser("%z%");
for (User u:user){
System.out.println(u);
}
sqlSession.close();
}
4.配置解析:
4.1丶配置如下
- configuration(配置)
- properties(属性)
- settings(设置)
- typeAliases(类型别名)
- typeHandlers(类型处理器)
- objectFactory(对象工厂)
- plugins(插件)
- environments(环境配置)
- environment(环境变量)
- transactionManager(事务管理器)
- dataSource(数据源)
- databaseIdProvider(数据库厂商标识)
- mappers(映射器)
4.2丶环境配置(environments)
mybatis可以适应多种环境
但每个SqlSessionFactory实例只能选择一种实例
学会配置多套运行环境
mybatis默认事务管理器是jdbc,
dataSource 使用 JDBC 数据源连接对象的资源。 含池的数据源类型:POOLED
4.3丶属性([properties)
配置文件要按照顺序
mybatis.properties
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybaties?useSSL=false&;characterEncoding=UTF-8&;useUnicode=true&;serverTimezone=GMT
username=root
password=123
核心配置文件中声明properties并引入外部地址
<properties resource="mybatis.properties"/>
使用外部配置文件
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
4.4丶类型别名(typeAliases)
类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置,意在降低冗余的全限定类名书写。
- 同样要注意标签顺序
- 第一种自定义别名
- 第二种,以包名下的类起别名
<typeAliases>
<!-- 自定义 -->
<typeAlias type="com.LiuDeHen.pojo.User" alias="User"/>
<!-- 以类名 -->
<package name="com.LiuDeHen.pojo"/>
</typeAliases>
第三种就是注解了
@Alias("author")
public class Author {
...
}
在实体类少的情况下可以用自定义,多就用第二种
4.5丶设置
- cacheEnabled 缓存
- mapUnderscoreToCamelCase 将sql里 字段 index_name 转化为驼峰 indexName
4.6丶其他配置
4.7丶映射器(mappers)
MapperRegistry:注册绑定我们的Mapper文件
第一种:resource (推荐使用)进行绑定
<mappers>
<mapper resource="com/LiuDeHen/Dao/UserMapper.xml"/>
</mappers>
第二种:class进行绑定
<mappers>
<mapper class="com.LiuDeHen.Dao.UserMapper"/>
</mappers>
注意点:
- 接口和Mapper配置文件必须同名
- 接口和Mapper配置文件必须在同一个包下
第三种:使用扫描包进行绑定注册包下所有文件
<mappers>
<package name="com.LiuDeHen.Dao"/>
</mappers>
注意点:
- 接口和Mapper配置文件必须同名
- 接口和Mapper配置文件必须在同一个包下
技巧:
如果想将Dao下的Mapper文件放到resource下,在resources下建一个和接口所在相同的包,使用 resource 的方式,路径不加resources,对比老师的来如
4.8丶生命周期和作用域
生命周期和作用域,是至关重要的,因为错误的使用回导致非常严重的并发问题
SqlSessionFactoryBuilder:
- 一旦创建了 SqlSessionFactory,就不再需要它了
- 佳作用域是方法作用域(也就是局部方法变量)
SqlSessionFactory:
- 说白了可以把它当成:数据库连接池
- SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例
- 最佳作用域是应用作用域
- 使用单例模式或者静态单例模式
SqlSession:
- 连接到连接池的一个请求
- 用完需要关闭,释放池中资源
- SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域
5.解决属性名和字段名不一致的问题
5.1丶问题
那该怎么解决
起别名
<select id="getUserName" parameterType="int" resultType="com.LiuDeHen.pojo.User">
SELECT id,name,pwd AS password from mybaties.user where id=#{id};
</select>
5.2丶resultMap结果集映射
由原本的select直接指向实体类,变成select指向resultMap,resultMap再指向User实体类
<resultMap id="UserMap" type="User">
<!-- column对应着数据库的字段,property对应着实体类的属性 -->
<result column="pwd" property="password"/>
</resultMap>
<select id="getUserName" resultMap="UserMap">
SELECT id,name,pwd from mybaties.user where id=#{id};
</select>
resultMap
元素是 MyBatis 中最重要最强大的元素- ResultMap 的设计思想是,对简单的语句做到零配置,对于复杂一点的语句,只需要描述语句之间的关系就行了。
6.日志
日志工厂
如果一个数据库操作,出现了异常,我们需要排错,日志就是最好的助手
曾经:sout,debug
现在:日志工厂
SLF4J
LOG4J(掌握)
LOG4J2
JDK_LOGGING
COMMONS_LOGGING
STDOUT_LOGGING(掌握)
NO_LOGGING
在设置中设定具体使用那个日志
6.1丶STDOUT_LOGGING(掌握)
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
6.2丶LOG4J
什么是LOG4J?
- Log4j是Apache的一个开源项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件
- 我们也可以控制每一条日志的输出格式
- 通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程
- 这些可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码
导入包
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
配置文件
#将等级为DEBUG的日志信息输出到console和file这两个目的地,console和file的定义在下面的代码
log4j.rootLogger=DEBUG,console,file #控制台输出的相关设置
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.Target = System.out
log4j.appender.console.Threshold=DEBUG
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=[%c]-%m%n #文件输出的相关设置
log4j.appender.file = org.apache.log4j.RollingFileAppender
log4j.appender.file.File=./log/kuang.log
log4j.appender.file.MaxFileSize=10mb
log4j.appender.file.Threshold=DEBUG
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=[%p][%d{yy-MM-dd][%c]%m%n #日志输出级别
log4j.logger.org.mybatis=DEBUG
log4j.logger.java.sql=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.ResultSet=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG
配置log4j为日志的实现
测试运行
简单使用
导入import org.apache.log4j.Logger包
日志对象
static Logger logger = Logger.getLogger(UserDaoTest.class);
使用常用方法(日志有级别)
logger.info(提示信息);
logger.debug(Debug信息);
logger.error(错误提示);
7.分页查询
为什么需要分页?
- 减少数据的处理量
使用limit分页
select * from 表名 limit indexstart rows indexstart:起始行数 rows:多少行
使用mybatis实现分页
接口
// 分页查询
List<User> getLimit(Map<String,Object> map);
mapper文件
对应的resultMap解决字段和属性不一样
<resultMap id="UserMap" type="User">
<!-- column对应着数据库的字段,property对应着实体类的属性 -->
<result column="pwd" property="password"/>
</resultMap> <select id="getLimit" resultMap="UserMap" parameterType="map">
select * from mybaties.user limit #{start},#{rows};
</select>
测试
@Test
public void testLimit(){
SqlSession sqlSession = MybatisUtils.getsqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
HashMap<String, Object> hashMap = new HashMap<String, Object>();
hashMap.put("start",0);
hashMap.put("rows",3);
List<User> limit = mapper.getLimit(hashMap);
for (User user : limit) {
System.out.println(user);
}
sqlSession.close();
}
8.使用注解开发
在接口中使用注解
@Select("select id,name,pwd as password from mybaties.User")
List<User> getUser();
在核心配置文件中绑定接口
<mappers>
<mapper class="com.LiuDeHen.Dao.UserMapper"/>
</mappers>
测试
@Test
public void test() {
SqlSession sqlSession = MybatisUtils.getsqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> user = mapper.getUser();
for (User user1 : user) {
System.out.println(user1);
}
sqlSession.close();
}
本质:反射机制
底层:动态代理
9.mybaitis流程基本梳理
首先我们在使用时,会调用工具类MybatisUtils
里面有一个resource路径是我们的全局核心配置文件
然后会获取一个流,并将这个流传给build方法
这个build方法里有个构造器XMLConfigBuilder(),它会将流里(核心配置文件里)的环境等传进去,返回得到一个sqlSessionFactory工厂
通过工厂获取SqlSession实现crud操作sql
SqlSession可以通过getMapper方法再使用反射动态获取是哪一个接口
10.使用注解实现增删查改
//使用注解增删改查
public interface UserMapper {
@Select("select id,name,pwd as password from mybaties.User")
List<User> getUser();
@Select("select * from mybaties.User where id=#{id}")
User getUserID(@Param("id") int id);
@Insert("insert into mybaties.user values(#{id},#{name},#{pwd})")
int getInsert(User user);
@Update("update mybaties.User set name=#{name} where id=#{id}")
int getUpdate(User user);
@Delete("delete from mybaties.User where id=#{id}")
int getDelete(@Param("id") int id);
//测试:
public void test() {
SqlSession sqlSession = MybatisUtils.getsqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> user = mapper.getUser();
for (User user1 : user) {
System.out.println(user1);
}
sqlSession.close();
}
@Test
public void testId(){
SqlSession sqlSession = MybatisUtils.getsqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = mapper.getUserID(1);
System.out.println(user);
sqlSession.close();
}
@Test
public void testInsert(){
SqlSession sqlSession = MybatisUtils.getsqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
int zz = mapper.getInsert(new User(6, "zz", "222"));
if (zz>0){
System.out.println("插入成功");
}
sqlSession.close();
}
@Test
public void testUpdate(){
SqlSession sqlSession = MybatisUtils.getsqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
int zz = mapper.getUpdate(new User(6, "lc",""));
if (zz>0){
System.out.println("修改成功");
}
sqlSession.close();
}
@Test
public void testDelet(){
SqlSession sqlSession = MybatisUtils.getsqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
int zz = mapper.getDelete(3);
if (zz>0){
System.out.println("删除成功");
}
sqlSession.close();
}
注意在使用工厂回去sqlsession时,将option设置成true,就能dml事务自动提交
return sqlSessionFactory.openSession(true);
11.lombok
可以简化实体类得代码
使用步骤
安装插件
项目导入jar包
在实体类上加注解
@Getter and @setter
@Fie1dNameConstants
@Tostring
@EqualsAndHashcode
12.多对一处理(association)
多对一,每个都对应那一个类
sql:多个学生对应一个老师
use mybaties;
CREATE TABLE `teacher` (
`id` INT(10) NOT NULL,
`name` VARCHAR(30) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8;
INSERT INTO teacher(`id`, `name`) VALUES (1, '秦老师');
CREATE TABLE `student` (
`id` INT(10) NOT NULL,
`name` VARCHAR(30) DEFAULT NULL,
`tid` INT(10) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `fktid` (`tid`),
CONSTRAINT `fktid` FOREIGN KEY (`tid`) REFERENCES `teacher` (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8;
INSERT INTO `student` (`id`, `name`, `tid`) VALUES (1, '小明', 1);
INSERT INTO `student` (`id`, `name`, `tid`) VALUES (2, '小红', 1);
INSERT INTO `student` (`id`, `name`, `tid`) VALUES (3, '小张', 1);
INSERT INTO `student` (`id`, `name`, `tid`) VALUES (4, '小李', 1);
INSERT INTO `student` (`id`, `name`, `tid`) VALUES (5, '小王', 1);
12.1丶按照查询嵌套处理(子查询)
<select id="getTeather" resultType="Teather">
SELECT * from mybaties.teacher;
</select>
<resultMap id="join" type="Student">
<association property="tid" column="tid" javaType="Teather" select="getTeather"/>
</resultMap>
<select id="getStudent" resultMap="join">
select * from mybaties.student;
</select>
12.2丶按照结果嵌套处理(多表联查)
- 上面的查询语句只是查询,select后的字段并不是全部返回,因为返回类型是resultMap
<select id="getStudent" resultMap="join">
select s.id,s.name as sname,t.name as tname,t.id as tid
from mybaties.student as s,mybaties.teacher as t
where s.tid=t.id;
</select>
多对一的关系
property: 指的是属性名称, javaType:指的是属性的类型
<resultMap id="join" type="Student">
<result property="id" column="id"/>
<result property="name" column="sname"/>
<association property="tid" javaType="Teather">
<result property="id" column="tid"/>
<result property="name" column="tname"/>
</association>
</resultMap>
13.一对多(collection)
一对多,所以有集合
实体类
student
@Data
public class Student {
private int id;
private String name;
private int tid;
}
Teather
@Data
public class Teather {
private int id;
private String name;
private List<Student> student;
}
13.1丶按照结果嵌套处理(多表联查)
<select id="getTeatherStu" resultMap="join">
select t.id as tid,t.name as tname,s.name as sname,s.id as sid
from mybaties.student as s,mybaties.teacher t
where t.id=#{id};
</select>
一对多的关系
property: 指的是集合属性的值, ofType:指的是集合中元素的类型
<resultMap id="join" type="Teather">
<result property="id" column="tid"/>
<result property="name" column="tname"/>
<collection property="student" ofType="Student">
<result property="id" column="sid"/>
<result property="name" column="sname"/>
<result property="tid" column="tid"/>
</collection>
</resultMap>
13.2丶总结
- 关联:association 多对一
- 集合:collection 一对多
- javaType & ofType:
- javaType:用来指定实力类中属性的类型
- ofType:用来指定映射到List或者集合中的pojo类型,泛型中的约束类型
14.动态SQL
什么是动态sql? 根据不同的条件生成不同的sql语句
如果你之前用过 JSTL 或任何基于类 XML 语言的文本处理器,你对动态 SQL 元素可能会感觉似曾相识。在 MyBatis 之前的版本中,需要花时间了解大量的元素。借助功能强大的基于 OGNL 的表达式,MyBatis 3 替换了之前的大部分元素,大大精简了元素种类,现在要学习的元素种类比原来的一半还要少。
if
choose (when, otherwise)
trim (where, set)
foreach
搭建环境
CREATE TABLE `blog`(
`id` VARCHAR(50) NOT NULL COMMENT '博客id',
`title` VARCHAR(100) NOT NULL COMMENT '博客标题',
`author` VARCHAR(30) NOT NULL COMMENT '博客作者',
`create_time` DATETIME NOT NULL COMMENT '创建时间',
`views` INT(30) NOT NULL COMMENT '浏览量'
)ENGINE=INNODB DEFAULT CHARSET=utf8;
1.IF
<select id="getBlogIF" parameterType="map" resultType="Blog">
select * from mybaties.blog where 1=1
<if test="title !=null">
AND title=#{title}
</if>
<if test="author!=null">
AND author=#{author}
</if>
</select>
2.trim (where, set)
where:当我们做if或者when拼接的时候,没有其他限制条件,可以用where标签直接做拼接,当下面条件成立就拼接并自己省去and
set:用于update更新中
<update id="UpdateSET" parameterType="map" >
update mybaties.blog
<set>
<if test="author !=null">
author=#{author},
</if>
<if test="views !=null">
views=#{views},
</if>
</set>
where author=#{author}
</update>
当我们拼接省去不仅仅是and和,的时候,可以用trim定制
<trim prefix="SET" suffixOverrides=",">
...
</trim>
<trim prefix="WHERE" prefixOverrides="AND |OR ">
...
</trim>
3.choose (when, otherwise)
choose when:类似于switch case
<select id="getBlogIF" parameterType="map" resultType="Blog">
select * from mybaties.blog
# where标签做一个拼接,会自动帮你省去拼接的and
<where>
<choose>
<when test="title!=null">
and title=#{title}
</when>
<when test="author !=null">
and author=#{author}
</when>
<otherwise>
and title="java";
</otherwise>
</choose>
</where>
</select>
4.sql片段
- 将重复代码抽取出来复用
- 先使用sql标签提取
- 再使用include标签引用
<sql id="fuyong">
<if test="">
and title=#{title}
</if>
</sql>
<select id="One" resultType="Blog">
select * from mybaties.blog
<where>
<include refid="fuyong">
</include>
</where>
</select>
5.foreach
<!--可以使用万能的map传递集合ids-->
<select id="getBlogForearh" parameterMap="map" resultType="blog">
select *from mybaties.blog
<where>
<foreach collection="ids" item="id" open="and (" close=")" separator="or">
id=#{id};
</foreach>
</where>
</select>
测试:
@Test
public void testForearh(){
SqlSession sqlSession = MybatisUtils.getsqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
HashMap map = new HashMap<>();
ArrayList<Object> list = new ArrayList<>();
map.put("ids",list);
// list.add(1);
for (Blog blog : mapper.getBlogForearh(map)) {
System.out.println(blog);
}
sqlSession.close();
}
动态sql就是在拼接sql语句,在保证的sql准确性的情况下,按照sql的格式,排列组合
注意:
- 先写sql语句,再写对应的动态sql来实现通用
15.缓存
后面再补,现在都用不到,学了就忘。。。
16.总结
- 什么是mybatias?
- 是一个轻量级的框架
- 为了解决java和sql的解耦
- 使用了xml标签映射的方式
- mybatis的搭建流程
- 首先创建在resource资源目录下创建mybatis核心配置文件
- 再在utils包下构建一个工具类MybatisUtils
- 然后是pojo包下的实体类
- 然后就是Dao包下的Mapper接口和Mapper文件
- mybatis的配置介绍
- configuration是核心配置标签
- environments是环境标签 default是默认属性
- dataSource数据来源,连接数据库,type有三种方式,当为POOLED是有池的方式
- 别名typeAliases,通过设置某些包下的名字,就可以在mapper文件中使用时,简便调用
- properties ,调用外部资源,resource下的参数就可以使用到
- settings一些设置,可以设置日志工厂
- mappers(映射器)映射到mapper配置文件,一个Dao下的mapper对应就要映射这里一个mapper
- 映射有三种方式
- resource,使用/文件目录的方式
- class,使用类.的方式查找
- packet,使用包的方式
- mybatis的基本使用
- select标签
- insert标签
- delete标签
- update标签
- 标签基础属性id=”对应mapper接口中的方法“ parameterType=”对应参数的类型“ parameterMap=”对应我们使用万能Map的时候传的map“,resultType=”返回值的类型(这里就可以使用别名)“,resultMap=”这个就是结果集映射,可以处理数据库字段和实体类属性不同的问题,还有一对多,多对一的问题“
- 跟sql语句没有区别,只有在传参数时需要 id=#{id} 数据库字段={实体类属性/map}
- 万能map的使用,当我们需要传递特殊的参数,或者多个参数,实体类不好传参时,使用
- 分页查询 limit indexstart rows 跟sql一样
- 基础简单的增删查改,也可以使用注解来完成
- mybatis的一对多,多对一使用(resultMap结果集映射)
- 使用后是select指向resultMap结果集,结果集类型tybe指向返回值类型
- 映射分为查询嵌套映射(子查询)和结果结构映射(联表查询)(一般使用结构)
- 一对多:collection标签,对应集合的意思,ofType属性对应放在集合中的字段的类型,一对多,所以这个类中得有一个属性是集合类型保存另一个类得类型
- 多对一:association标签,对应关联的意思,属性 property="实力类属性" column="数据库字段" javaType=”对应那个一的java类型“, association可以再映射它的
- 动态sql
- where标签,再下面语句成立存在的情况下,会帮我们省去中间的and
- if标签,是否存在(一般会和where连用)
- chose(when otherwise) 对应java里的switch case差不多
- sql片段 ,sql标签把复用得代码套起来,再incluse标签到用的地方
- foreach标签,循环,属性collection=”集合“ item=”就是我们映射的字段“ open="以什么开头" close="以什么结尾i" separator="中间用什么隔开"
- 缓存!
Mybatias的更多相关文章
- spring boot配置写法
转自:http://blog.csdn.net/mickjoust/article/details/51646658 每日金句 你要搞清楚自己人生的剧本:不是你父母的续集,不是你子女的前传,更不是你朋 ...
- spring05-Spring事务管理
事务的第一个方面是传播行为(propagation behavior).当事务方法被另一个事务方法调用时,必须指定事务应该如何传播.例如:方法可能继续在现有事务中运行,也可能开启一个新事务,并在自己的 ...
随机推荐
- idea2020.1版本的maven项目报包不存在,找不到包错误
错误描述 idea创建maven项目,导入依赖都是成功,但是运行就会报找不到对应jar包的错误 解决办法: File -> Settings -> 搜索maven -> 展开mave ...
- git命令log与reflog的比较
感谢原文作者:杨鲜生 原文链接:https://blog.csdn.net/u013252047/article/details/80230781 用git命令,想看到自己的操作记录,则可以使用log ...
- JavaWeb编码浅解
感谢原文作者:少年无形 原文链接:https://blog.csdn.net/dl18215164175/article/details/72512131?depth_1-utm_source=dis ...
- Idea 如何不通过模板创建支持Maven的JavaWeb项目
手动与模板创建的区别,请自行体会. 1. 点击创建项目 2. 不勾选骨架 3.填写项目名称以及该Maven项目坐标(groupid.artifactid.version). 在仓库中,以坐标确定项目. ...
- C语言中的单引号和双引号的区别
首先肯定地说,二者是有区别的,不是说用谁都一样. 1.实质区别,代表的含义不同 'A'代表的是一个整数,而且这个整数对应的是编译器所采用的字符集中的字符序列对应的数值.所以'A'跟ASCII中的65意 ...
- DHCP原理与LINUX下的配置
DHCP原理与LINUX下的配置 目录 DHCP原理与LINUX下的配置 一.DHCP工作原理 1.DHCP概述 2.DHCP的优势 3.DHCP的分配方式 (1)自动分配 (2)手动分配 (3)动态 ...
- hgame-week3-web-wp
hgame第三周(web ak) 1.SecurityCenter 先看看hint(**vendor是第三方库和插件放置的文件夹,一般来源于composer的安装) 找到了使用的twig模板,应该是t ...
- node Cheerio 获取script脚本里的数据
const cheerio = require('cheerio'); const $ = cheerio.load(html); // your html//如果有多少script脚本标签使用循环来 ...
- 使用污点分析检查log4j问题
摘要:log4j问题的余波还在继续,为什么这个问题潜伏了这么长时间,大家一直没有发现?这里从静态分析的角度谈下log4j问题的发现. 本文分享自华为云社区<使用污点分析检查log4j问题> ...
- 手把手带你基于嵌入式Linux移植samba服务
摘要:Samba是在Linux和UNIX系统上实现SMB协议的一个免费软件,由服务器及客户端程序构成. 本文分享自华为云社区<嵌入式Linux下移植samba服务--<基于北斗和4G ca ...