MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。
半自动的ORM(Object/ Relational Mapping,即对象关系映射)框架。ORM框架常用有两个:Hibernate和MyBatis框架。
2.ORM的介绍ORM(对象关系映射):以对象的方式操作数据库
比如定义一个对象和数据库表字段一致,那么就可以直接操作这个对象,就可以自动生成SQL语句. 如:userDao.insert(user对象) ,无需书写SQL语句就可以实现数据的插入
ORM的核心映射机制
数据表 <-对应-> java对象
数据表字段 <-对应-> java对象中的属性
1)全自动映射
当用户执行代码userDao.insert(user对象),映射框架解析成insert into 表名(字段1,字段2,字段3...) values(属性值1,属性值2,属性值3.....) ------------------------------------------ 用户查询操作:ListuserList = userDao.selectList(user对象); select * from 表名 where xxxx=xxxx and xxx= xxx 结果集自动的封装成对象
自动实现对象的封装
自动生成SQL语句
2)半自动ORM的mybatis
可以实现对象的自动封装,但是不能自动生成SQL语句.
3.mybatis的入门代码编辑(Maven项目下) 总体的项目结构[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XDR0Aujp-1659013934685)(D:Typorabindocumentimg1658917077363.png)]
1.导入jar包2.数据库表和实体对象mysql mysql-connector-java 8.0.16 org.mybatis mybatis 3.5.6 log4j log4j 1.2.17 junit junit 4.12 test
必须保证数据表和对象一一映射,表中字段和对象属性一一映射
3.编写xxxMapper接口(和Dao接口一类,只是命名格式不同,用来定义操作数据库的方法)
4.编写xxxMapper对应的映射文件xxxMapper.xml该xml文件只是替代了实现类,在该xml中书写SQL
5.核心配置文件mybatis-config.xml---------------------------------------------------------------------------------- SQL语句
6.单元测试
步骤:
1.读取配置文件
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
2.通过SqlSessionFactoryBuilder 创建SqlSessionFactory
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(resource);
3.通过SqlSessionFactory获得SqlSession
SqlSession sqlSession=sqlSessionFactory.openSession();
4.获取Mapper接口
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
5.调用mapper接口中的方法
ListuserList = userMapper.getAllUser(); 或者使用[了解] List list = sqlSession.selectList("com.atguigu.mybatis.mapper.UserMapper.getAllUser"); getAllUser()是mapper接口中的方法,mybatis会根据映射关系,执行映射文件中的id为getAllUser的sql标签
@Test
public void findCount() throws IOException {
InputStream resource = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(resource);
SqlSession sqlSession=sqlSessionFactory.openSession();
UserMapper mapper=sqlSession.getMapper(UserMapper.class);
int count = mapper.findCount();
System.out.println(count);
}
userMapper.xxx调用的是接口中的方法,mybatis根据映射关系,执行映射文件中id为xxx的sql标签.
注意:在接收返回数据时,如果根据主键查询必返回一个对象,用对象接收.如果不确定,则使用list<实体对象>进行接收
7.Sqlsession的简化操作通过@Before标签 简化sqlSession的赋值操作
private SqlSession sqlSession;
@Before
public void init() throws IOException {
//读取mybatis-config.xml核心配置文件
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
//创建mybatis中操作数据库的会话对象SqlSession
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
sqlSession = sqlSessionFactory.openSession();
}
@Test
public void findCount() throws IOException {
UserMapper mapper=sqlSession.getMapper(UserMapper.class);
int count = mapper.findCount();
System.out.println(count);
}
4.mybatis常见错误及解决办法
报错说明1:
org.apache.ibatis.binding.BindingException: Type interface com.jt.mapper.UserMapper is not known to the MapperRegistry.
解决方案1:
1.检查namespace命名是否与接口一致
2. 检查Mybatis核心配置文件是否加载映射文件.
报错说明2:
org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.jt.mapper.UserMapper.findAll
解决方案2:
检查xml映射文件中的ID是否与接口方法一致.
报错说明3:
The error may exist in mybatis/mappers/UserMapper2.xml
解决方案3:
检查mybatis核心文件加载mapper映射文件的路径是否正确.
在pom.xml中引入jar包,在resources下放置log4j.xml
需求:在使用mybatis时,执行时不会打印SQL语句,为了检验sql语句的执行正确性,使用log4j用来在执行时打印SQL
位置:在resources下
日志级别
日志级别从左到右打印的内容越来越详细
FATAL(致命) > ERROR(错误) > WARN(警告) > INFO(信息) > DEBUG(调试)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dkwod1Fq-1659013934695)(D:Typorabindocumentimg1658922186039.png)]
#key=value jdbc.driver=com.mysql.cj.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/atweb?serverTimezone=UTC&rewriteBatchedStatements=true&characterEncoding=utf-8 jdbc.username=root jdbc.password=root
serverTimezone=UTC 时区:标准时区
rewriteBatchedStatements=true 批处理,提高批量处理SQL语句的执行效率
characterEncoding=utf-8 编码格式utf-8
7.mybatis核心配置文件mybatis-config.xml
mybatis-config.xml中,所有的配置都是在标签内,这些标签在使用时,要遵循相应的顺序
properties,settings,typeAliases,
typeHandlers,objectFactory,
objectWrapperFactory,reflectorFactory,plugins,
environments,databaseIdProvider,mappers.
从上到下的顺序
8.mybatis中typeAliases(别名)的使用需求:在xxxMapper.xml中,resultType=“返回值类型”,书写的太复杂,可以使用别名定义.
此处的User就是一个别名,代表com.atguigu.mybatis.pojo.User
通过下面的别名定义实现
1|2|4 在mybatis-config.xml中配置
3在实体类上
-----------------------------------
1)通过标签定义
2)简化alias
3)注解写法
@Alias("User")
public class User implements Serializable {...}
4)定义别名
9.映射文件中的元素
映射文件是 MyBatis框架中十分重要的文件,在映射文件中,元素是映射文件的根元素,其他元素都是它的子元素
1、< select >用于映射查询语句,它用于从数据库中读取出数据,并组装数据给业务开发人员。
上述语句中的唯一标识为findUserById,它接收一个 Integer类型的参数,并返回一个User类型的对象。
2、 < insert >元素< update > < delete >用于映射插入语句,在执行完元素中定义的SQL语句后,会返回一个表示插入记录数的整数。
3、 < sql >元素insert into t_user(username,jobs,phone) values(#{username},#{jobs},#{phone})
元素的作用就是定义可重用的SQL代码片段,然后在其他语句中引用这一代码片段。
定义重复SQL:
< sql id=“user_column”>
id,name,age,sex
< /sql>
引入标签:
< include refid=“user_column”/>
10.参数传递 #{}和${}的用法和区别id,name,age,sex
#号它是有预编译的效果(相当于 PraperStatement ),参数使用?进行占位,并且默认为参数添加引号
$号是直接将字符串进行拼接,没有预编译的效果,使用时需要手动添加引号
原则: 能用#号 不要使用$符,除非以字段名称为参数时使用.
1.单值参数传递mybatis单值数据传递时和参数的名称无关. 通过参数下标的方式获取的.
建议: 虽然和名称无关,但是一般的参数 见名知意.
2.多值参数传递 1)通过数组进行取值Mybatis进行多值参数传递时,内部使用数组的结构,所以需要通过下标的方式取值.
例如: Available parameters are [arg0, arg1, param1, param2]
弊端: 用户传递的数据是有参数名称的, 如果大量使用下标的方式,则会导致sql业务理解不方便
2)Map集合说明: 如果用户需要进行多值参数传递,则可以使用map集合进行封装.
编辑测试类:
@Test
public void test04(){
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
int age = 3030;
String sex = "男";
Map map = new HashMap<>();
map.put("age",age);
map.put("sex",sex);
List list = mapper.findUserByMap(map);
list.forEach(System.out::println);
}
xml映射文件
3)注解封装
说明: 使用@Param注解封装参数
注解封装在底层还是运用了map集合进行的处理
- 编辑测试类
@Test
public void test05(){
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
int age = 2851;
String sex= "女";
List list = mapper.findUserByAnno(age,sex);
list.forEach(System.out::println);
}
- 编辑接口
List findUserByAnno(@Param("age") int age,@Param("sex") String sex);
- 编辑映射文件
4)实体对象封装
需求: 根据实体对象中的数据查询数据.
- 编辑测试类
@Test
public void test06(){
User user = new User();
user.setName("铁扇公主");
user.setAge(1273);
user.setSex("女");
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List list = mapper.findUser(user);
list.forEach(System.out::println);
}
- 编辑Mapper接口
ListfindUser(User user);
- 编辑Mapper.xml映射文件
重要知识理解:
Mybatis中的参数其实只能允许单值传递(数据可以被封装为单值)
在使用mybatis进行数据库的增删改查时,凡是数据发生改变[如增删改]的都需要加上sqlSession.commit();sqlSession.close()用于事务的提交.
11.转义字符
select * from demo_user where age >=#{starAge} and age <= #{endAge}
------------------------------------------
select * from demo_user where age >=? and age <= ?
lombok的注解说明:
@Accessors(chain = true)
@Accessors 注解用来配置lombok如何产生和显示get和set的方法,@Accessors(chain = true)加上参数以后就可以开启链式编程.
传统set方法赋值(臃肿、占空间)
Person person = new Person();
person.setName("wang");
person.setSex("男");
person.setEmail("123@qq.com");
person.setDate(new Date());
person.setAddr("山东");
加上@Accessors(chain = true)
Person person = new Person();
person.setName("wang").setSex("男").setEmail("123@qq.com").setDate(new Date()).setAddr("山东");
11.ResultMap
当表中的字段与POJO中的属性不能完全匹配时, 则需要使用resultMap映射.
ResultMap解决在数据库中的字段名和实体类中属性名不一致,无法自动映射的问题(数据库:user_id 属性:userId)
案例描述
1)实体类:
@Data
@Accessors(chain = true)
@AllArgsConstructor
@NoArgsConstructor
public class Users implements Serializable {
private Integer id;
private String tName;
private Integer tAge;
private String sex;
}
2)UsersMapper接口
public interface UserMappers {
List selectUser();
}
3)UsersMapper.xml
4)mybatis-config.xml
在properties标签下生效,要依照执行顺序
........................................
5)测试类
@Test
public void selectUser() throws IOException {
InputStream rs = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(rs);
SqlSession sqlSession=sqlSessionFactory.openSession();
UserMappers mapper=sqlSession.getMapper(UserMappers.class);
List userList=mapper.selectUser();
System.out.println(userList);
}



