Mybatis框架
入门演示
1、创建maven-java项目
2、加入依赖
<dependencies>
<!-- mybatis的依赖 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.6</version>
</dependency>
<!-- jdbc驱动包 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
</dependencies>
3、mybatis全局配置文件
一般,mybatis全局配置文件的名称为:sqlconfing.xml或者mybatis-config.xml
。格式为:.xml
文件,一般写在resources
下。内容(我们可以从mybatis官网上复制)
<?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>
<!-- jdbc环境 -->
<environments default="development">
<environment id="development">
<!-- 事务管理 : type="JDBC" jdbc管理 -->
<transactionManager type="JDBC"/>
<!-- 数据源配置:type="POOLED" 使用数据库连接池 -->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/test?useSSL=false"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<!-- 加载映射文件 -->
<mappers>
<mapper resource="UserMapper.xml"/>
</mappers>
</configuration>
4、Dao层的接口
在JavaWeb阶段,我们知道Dao层是对数据库进行操作的接口及其接口的实现类,而现在我们使用了Mybatis框架,对数据库的操作的包名就替换成mapper
,接口名替换成XxxMapper.java
。如图:
package com.lyc.mapper;
import com.lyc.model.User;
public interface UserMapper {
User findUserById(int id);
}
5、mybatis的映射文件
MyBatis 的真正强大在于它的映射语句,由于它的异常强大,映射器的 XML 文件就显得相对简单。如果拿它跟具有相同功能的 JDBC 代码进行对比,你会立即发现省掉了将近 95% 的代码。MyBatis 就是针对 SQL 构建的,并且比普通的方法做的更好。 为了更好的理解mybatis的映射文件,我们可以这样理解:在以前,我们写完Dao层接口,接下来我们就需要写Dao层的实现类,在实现类中写JDBC。而在mybatis框架中,是写完Mapper层接口后,需要写的是Mapper接口的xml映射文件,映射文件内写sql语句
。
映射文件的书写格式:
名称:模块名Mapper.xml。
格式:xml
位置:放在resources下,(也可以放在mapper包下)
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- 该映射文件是在resources下-->
<!--
mapper跟标签
namespace="该映射文件对应的接口文件的全限定名"
-->
<mapper namespace="com.lyc.mapper.UserMapper">
<!--
select 标签用于查询(后续还有其他标签)
id: 接口中的方法名
resultType: 结果类型,是查询返回的结果集要封装的那个类(这一步就是自动ORM)
parameterType: 接口中方法的参数类型
-->
<select id="findUserById" resultType="com.lyc.model.User" parameterType="int">
<!--
以前此处写的 where id = ?
现在此处写 where id = #{},当接口的参数是简单类型时,{}内名称任意,但是当接口的参数是复杂类型时就有限制,后续我们再说
此时,{}内的与方法参数名一致即可
-->
select * from user where id = #{id}
</select>
</mapper>
6、测试
在测试里,为了方便测试,我们使用单元测试,来提高效率
<!-- 单元测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
注意:
1、在方法上加上@Test注解
2、单元测试的方法,
一定是无返回值的(void)
每个基于 MyBatis 的应用都是以一个 SqlSessionFactory 的实例为核心的
。SqlSessionFactory 的实例可以通过 SqlSessionFactoryBuilder 获得。而 SqlSessionFactoryBuilder 则可以从 XML 配置文件或一个预先配置的 Configuration 实例来构建出 SqlSessionFactory 实例。
/*
1) 通过配置文件逻辑,获得文件流
2) 通过流获得SqlSessionFactory
3) 通过工厂获得SqlSession
4) 通过SqlSession获得接口的代理对象
5) 通过接口对象调用方法执行
6) 其实执行的是接口方法对应的xml中的标签内的sql语句
*/
public class TestMybatis {
/**
* 入门测试
*/
@Test
public void hello() throws IOException {
// 配置文件路径
String resource = "mybatis-config.xml";
// 通过配置文件,获得输入流
InputStream inputStream = Resources.getResourceAsStream(resource);
// 通过流获得SqlSession工厂
// SqlSession就是一次与SQL的交互
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 得到SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession( );
// 动态代理的模式
// 可以通过接口得到对应的映射文件,从而让映射文件执行
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
// 调用接口的方法,其实是执行映射文件中对应的sql语句
// 返回的User是mybatis的自动封装的
User user = mapper.findUserById(29);
System.out.println(user );
}
}
Mybatis之查询
查询是我们平时使用最多的语句,但同时写起来也是相对复杂的。接下来是对查询中接口方法的参数的讨论。
1、接口方法的参数是单个
参考入门案例,支持常见的简单的数据类型(8种基本类型,String,Date等)
2、接口方法的参数是多个
当接口中方法的参数列表有多个参数时,默认的方法已经不适用了,我们需要新的解决方案。
方案一:使用注释的方式【推荐】
UserMapper接口
public interface UserMapper {
// 注解中的参数是映射文件#{}内的值
User queryUser(@Param("name") String username,@Param("pwd") String password);
}
UserMapper.xml
<select id="queryUser" resultType="com.lyc.model.User">
select * from user where username = #{name} and password = #{pwd}
</select>
方案二:按照顺序写#{param1},#{param2}
public interface UserMapper {
// 注解中的参数是映射文件#{}内的值
User queryUser(String username,String password);
}
<select id="queryUser" resultType="com.lyc.model.User">
select * from user where username = #{param1} and password = #{param2}
</select>
为什么使用param1、param2?
当我们使用普通的方法写测试类,会报错。如下,我们根据错误信息,来修改我们的格式。
测试类:
@Test
public void query() throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = mapper.queryUser("lyc", "123456");
System.out.println(user);
}
3、接口方法的参数是对象类型
UserMapper接口
/**
* 对象作为参数查找
*/
User findUser(User user);
UserMapper.xml
<!-- 由于该方法的参数为对象,因此parameterType为实体类的全限定类名-->
<select id="findUser" resultType="com.lyc.model.User" parameterType="com.lyc.model.User">
<!-- 当参数类型是对象时,#{}内必须是对象的属性名-->
select * from user where username = #{username} and password = #{password}
</select>
测试类
//对象作为参数
@Test
public void findUser() throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = new User();
user.setUsername("lyc");
user.setPassword("123456");
User user1 = mapper.findUser(user);
System.out.println(user1);
}
4、接口方法的参数是Map
UserMapper接口
/**
* Map参数类型
*/
User findUserMap(Map<String,Object> params);
UserMapper.xml文件
<select id="findUserMap" resultType="com.lyc.model.User" parameterType="Map">
<!-- 当参数是Map时,#{}内写的是Map的key-->
select * from user where username = #{uname} and password = #{pword}
</select>
测试类
//Map做为参数
@Test
public void findUserMap() throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
HashMap<String, Object> hashMap = new HashMap<String, Object>();
hashMap.put("uname", "lyc");
hashMap.put("pword", "123456");
User userMap = mapper.findUserMap(hashMap);
System.out.println(userMap);
}
5、接口的参数是List
后续在动态SQL处再分析
6、接口方法的返回值是List集合
UserMapper接口
/**
* 返回值类型为List集合
*/
List<User> queryAll();
UserMapper.xml文件
<select id="queryAll" resultType="com.lyc.model.User">
select * from user
</select>
查询结果返回一个对象,还是List集合,resultType指定的是
封装的实体类类型
,而不是List类型。
测试类
//返回值类型为list
@Test
public void queryAll() throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> users = mapper.queryAll();
System.out.println(users);
}
Mybatis之删除
根据id删除
UserMapper接口
/**
* 删除指定用户
*/
boolean deleteUserById(int i);
UserMapper.xml文件
<delete id="deleteUserById" parameterType="int">
delete from user where id = #{id}
</delete>
测试类
//删除用户
@Test
public void delete() throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
boolean b = mapper.deleteUserById(24);
//需要将事务提交,否则数据无法正常变更
sqlSession.commit();
sqlSession.close();
System.out.println(b);
}
注意
mybatis在执行
增,删,改
的时候默认开启事务,但是没有自动提交, 如果在获得SqlSession时,指定了开启自动提交(SqlSession sqlSession = sqlSessionFactory.openSession(true)
),那么执行增删改时就会自动提交,否则我们需要手动提交。
Mybatis之更新
UserMapper接口
/**
* 修改用户
*/
int updataUserById(User user);
UserMapper.xml文件
<update id="updataUserById" parameterType="com.lyc.model.User">
<!-- #{}内写的是对象的属性名 -->
update user set username = #{username},password = #{password},birthday = #{birthday},phone = #{phone},address = #{address} where id = #{id}
</update>
测试类
//更新用户
@Test
public void add() throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
// 更新,如果对象某个属性为空,将会把直接置空
User user = new User( );
user.setId(29);
user.setUsername("圆圆");
user.setPassword("654321");
int i = mapper.updataUserById(user);
System.out.println(i );
// 记得提交
sqlSession.commit();
Mybatis之插入
UserMapper接口
/**
* 添加用户
*/
boolean addUser(User user);
UserMapper.xml文件
<insert id="addUser" parameterType="com.lyc.model.User">
insert into user(username,password,age,address,phone,birthday)
values (#{username},#{password},#{age},#{address},#{phone},#{birthday})
</insert>
测试类
//添加用户
@Test
public void add() throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = new User();
user.setUsername("萨达");
user.setPassword("11111");
user.setAge("23");
user.setAddress("洛阳");
user.setPhone("123456788");
user.setBirthday(new Date(System.currentTimeMillis()));
boolean b = mapper.addUser(user);
//需要将事务提交,否则数据无法正常变更
sqlSession.commit();
sqlSession.close();
System.out.println(b);
}
();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = new User();
user.setUsername("萨达");
user.setPassword("11111");
user.setAge("23");
user.setAddress("洛阳");
user.setPhone("123456788");
user.setBirthday(new Date(System.currentTimeMillis()));
boolean b = mapper.addUser(user);
//需要将事务提交,否则数据无法正常变更
sqlSession.commit();
sqlSession.close();
System.out.println(b);
}