MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
思路流程:搭建环境–>导入Mybatis—>编写代码—>测试
CREATE DATABASE `mybatis`;
USE `mybatis`;
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` int(20) NOT NULL,
`name` varchar(30) DEFAULT NULL,
`pwd` varchar(30) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
insert into `user`(`id`,`name`,`pwd`) values (1,'lxl','123456'),(2,'张三','abcdef'),(3,'李四','987654');
我们搭建完成数据库后在程序中首先就要导入mysql jar包、mybatis jar包以及junit jar包(直接使用maven导入较为方便)
org.mybatis
mybatis
3.5.2
mysql
mysql-connector-java
5.1.47
junit
junit
3.8.1
test
public class User {
private int id;
private String name;
private String pwd;
//set get方法以及构造方法
}
package com.lxl.mapper;
import com.lxl.pojo.User;
import java.util.List;
public interface UserMapper {
List selectUser();
}
namespace参数为USerMapper对应的接口,select id对应的是其方法名(selectUSer),resultType为返回类型,这里需要注意一下其中返回信息为List但在这里我们仍写User。
XML配置文件中包含了对 MyBatis 系统的核心设置,包括获取数据库连接实例的数据源(DataSource)以及决定事务作用域和控制方式的事务管理器(TransactionManager)。在resource文件夹下新建mybatis-config.xml文件(名字为官方建议),其中包括连接数据库的一些配置。需要注意的是mysql版本对应的url连接方法有些许不同。然后在标签中注册userMapper.xml文件。
此工具类的目的是使用sqlSessionFactory返回一个sqlSession对象,我们操作数据库是通过sqlSession对象进行操作的。其代码为写死的代码,一般无需改动。每个基于 MyBatis 的应用都是以一个 SqlSessionFactory 的实例为核心的。SqlSessionFactory 的实例可以通过 SqlSessionFactoryBuilder 获得。而 SqlSessionFactoryBuilder 则可以从 XML 配置文件或一个预先配置的 Configuration 实例来构建出 SqlSessionFactory 实例。
package com.lxl.utils;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;
public class MybatisUtils {
private static SqlSessionFactory sqlSessionFactory;
static {
try {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
//获取SqlSession连接
public static SqlSession getSession(){
return sqlSessionFactory.openSession();
}
}
现在我们一般使用代码块中的方法一进行操作。
package com.lxl.mapper;
import com.lxl.pojo.User;
import com.lxl.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import java.util.List;
public class UserMapperTest {
@Test
public void selectUser() {
SqlSession session = MybatisUtils.getSession();
//方法一:
UserMapper mapper = session.getMapper(UserMapper.class);
List users = mapper.selectUser();
//方法二:
//List users = session.selectList("com.kuang.mapper.UserMapper.selectUser");
for (User user: users){
System.out.println(user);
}
session.close();
}
}
我们的userMapper.xml文件是写在了mapper包下,不在resources文件夹下,所以maven并不会将其进行编译到target对应的目录下,我们需要对pom.xml进行一些配置,让其能加载到target目录下。
src/main/java
**/*.properties
**/*.xml
false
src/main/resources
**/*.properties
**/*.xml
false
CRUD是指在做计算处理时的增加(Create)、读取查询(Retrieve)、更新(Update)和删除(Delete)几个单词的首字母简写。主要被用在描述软件系统中DataBase或者持久层的基本操作功能。
select语句有很多属性可以详细配置每一条SQL语句
1.SQL语句返回值类型。【完整的类名或者别名】
2.传入SQL语句的参数类型 。【万能的Map,可以多尝试使用】
3.命名空间中唯一的标识符。【namespace】
4.接口中的方法名与映射文件中的SQL语句ID 一一对应
在第二部分的入门项目中我们已经学到了如何使用MyBatis对mysql进行操作,与其类似,我们现在来学习一下额外的内容。
public interface UserMapper {
//查询全部用户
List selectUser();
//根据id查询用户
User selectUserById(int id);
}
@Test
public void tsetSelectUserById() {
SqlSession session = MybatisUtils.getSession(); //获取SqlSession连接
UserMapper mapper = session.getMapper(UserMapper.class);
User user = mapper.selectUserById(1);
System.out.println(user);
session.close();
}
与使用id查询用户类似,只不过是现在参数有两个,有两种方法进行查询。
//通过密码和名字查询用户
User selectUserByNP(@Param("username") String username,@Param("pwd") String pwd);
User selectUserByNP2(Map map);
Map map = new HashMap();
map.put("username","小明");
map.put("pwd","123456");
User user = mapper.selectUserByNP2(map);
如果参数过多,我们可以考虑直接使用Map实现,如果参数比较少,直接传递参数即可
注意点:
所有的增删改操作都需要提交事务!
接口所有的普通参数,尽量都写上@Param参数,尤其是多个参数时,必须写上!
有时候根据业务的需求,可以考虑使用map传递参数!
为了规范操作,在SQL的配置文件中,我们尽量将Parameter参数和resultType都写上!
**问题:**mapper映射文件中select语句是相当于select id,name,pwd from user where id = #{id}
,mybatis会根据这些查询的列名(会将列名转化为小写,数据库不区分大小写),去对应的实体类中查找相应列名的set方法设值,如果对应属性值与数据库中的属性不一致,找不到对应的set方法 , 对应返回值就为null。
我们一般采用手动映射的方式在 select 标签中的resultMap中填写我们定义的map。如上述代码所示。当然也可以使用自动映射,直接写resultType=“map”,但只是简单地将所有的列映射到 HashMap 的键上,而HashMap 不是一个很好的模型。
在学习mybatis等持久层框架的时候,会经常对数据进行增删改查操作,使用最多的是对数据库进行查询操作,如果查询大量数据的时候,我们往往使用分页进行查询,也就是每次处理小部分数据,这样对数据库压力就在可控范围内。
#语法
SELECT * FROM table LIMIT stratIndex,pageSize
主要实现其中的startIndex以及pageSize等参数通过函数传过来就行了
SELECT * FROM table LIMIT 5,10; // 检索记录行 6-15
#为了检索从某一个偏移量到记录集的结束所有的记录行,可以指定第二个参数为 -1:
SELECT * FROM table LIMIT 95,-1; // 检索记录行 96-last.
#如果只给定一个参数,它表示返回最大的记录行数目:
SELECT * FROM table LIMIT 5; //检索前 5 个记录行
#换句话说,LIMIT n 等价于 LIMIT 0,n。
我们除了使用Limit在SQL层面实现分页,也可以使用RowBounds在Java代码层面实现分页,当然此种方式作为了解即可。我们来看下如何实现的!
主要是在测试类等Java代码层面对其实现分页。
@Test
public void testUserByRowBounds() {
SqlSession session = MybatisUtils.getSession();
int currentPage = 2; //第几页
int pageSize = 2; //每页显示几个
RowBounds rowBounds = new RowBounds((currentPage-1)*pageSize,pageSize);
//通过session.**方法进行传递rowBounds,[此种方式现在已经不推荐使用了]
List users = session.selectList("com.kuang.mapper.UserMapper.getUserByRowBounds", null, rowBounds);
for (User user: users){
System.out.println(user);
}
session.close();
}
使用Mybatis是基于接口,配置文件的源代码执行过程。因此,我们必须选择日志工具来作为我们开发,调节程序的工具。具体使用现先不写在这里,后续可能会更新。
mybatis最初配置信息是基于 XML ,映射语句(SQL)也是定义在 XML 中的。而到MyBatis 3提供了新的基于注解的配置。不幸的是,Java 注解的的表达力和灵活性十分有限。最强大的 MyBatis 映射并不能用注解来构建。利用注解开发就不需要mapper.xml映射文件了。使用注解和配置文件协同开发,才是MyBatis的最佳实践!
//查询全部用户
@Select("select id,name,pwd password from user")
public List getAllUser();
@Test
public void testGetAllUser() {
SqlSession session = MybatisUtils.getSession();
//本质上利用了jvm的动态代理机制
UserMapper mapper = session.getMapper(UserMapper.class);
List users = mapper.getAllUser();
for (User user : users){
System.out.println(user);
}
session.close();
}
其他的步骤也都类似。而注解的本质是利用了jvm的动态代理机制
多个学生对应一个老师,如果对于学生这边,就是一个多对一的现象,即从学生这边关联一个老师!
现在我们要查询学生表信息,但学生表里存放的只有对应老师的id而不是对应的老师这个对象。
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');
public class Student {
private int id;
private String name;
//多个学生可以是同一个老师,即多对一
private Teacher teacher;
}
public class Teacher {
private int id;
private String name;
}
public interface StudentMapper {
//获取所有学生及对应老师的信息
public List getStudents();//对应两个获取学生表的方法
public List getStudents2();
}
我们实现查询的方法一般有两个,分别是子查询和按照结果查询。
association对应这复杂属性映射
一般来说按照结果查询更加方便一点。
@Test
public void testGetStudents(){
SqlSession session = MybatisUtils.getSession();
StudentMapper mapper = session.getMapper(StudentMapper.class);
List students = mapper.getStudents();
for (Student student : students){
System.out.println(
"学生名:"+ student.getName()
+"\t老师:"+student.getTeacher().getName());
}
session.close();
}
@Test
public void testGetStudents2(){
SqlSession session = MybatisUtils.getSession();
StudentMapper mapper = session.getMapper(StudentMapper.class);
List students = mapper.getStudents2();
for (Student student : students){
System.out.println(
"学生名:"+ student.getName()
+"\t老师:"+student.getTeacher().getName());
}
session.close();
}
一个老师拥有多个学生,如果对于老师这边,就是一个一对多的现象,即从一个老师下面拥有一群学生(集合)!
若我们查询老师信息,同时想要获得所查询老师信息下的学生信息,这需要用到一对多的查询。与多对一类似,我们仍有两种方法查询,分别是按结果嵌套处理以及按查询嵌套处理。
public class Student {
private int id;
private String name;
private int tid;
}
public class Teacher {
private int id;
private String name;
//一个老师多个学生
private List students;
}
//获取指定老师,及老师下的所有学生
public Teacher getTeacher(int id);
@Test
public void testGetTeacher(){
SqlSession session = MybatisUtils.getSession();
TeacherMapper mapper = session.getMapper(TeacherMapper.class);
Teacher teacher = mapper.getTeacher(1);
System.out.println(teacher.getName());
System.out.println(teacher.getStudents());
}
对应接口对应的Mapper配置文件
总结:
1、关联-association
2、集合-collection
3、所以association是用于一对一和多对一,而collection是用于一对多的关系
4、JavaType和ofType都是用来指定对象类型的
其中JavaType是用来指定pojo中属性的类型
ofType指定的是映射到list集合属性中pojo的类型。
本博客是学习Spring的笔记记录,学习参考狂神说SSM框架系列:狂神说SSM框架系列