概述:
Mybatis是什么?能干什么?MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。通俗讲就是封装了JDBC,把CRUD那些繁琐的步骤用一个xml来代替。
官方文档:https://mybatis.org/mybatis-3/zh/index.html
使用步骤:
- 1.首先将jar包放置在项目内,或使用maven导入依赖
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.2</version>
</dependency>
- 2.编写mabatis-config.xml,将该配置文件放置在resource目录下
<?xml version="1.0" encoding="UTF8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<!--mybatis核心配置文件-->
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/test?useSSL=true&useUnicode=true&characterEncoding=utf-8"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/edu/dao/UserMapper.xml"/>
</mappers>
</configuration>
- 3.编写mabatis工具类MabatisUtils
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();
}
}
public static SqlSession getSqlSession(){
return sqlSessionFactory.openSession();
}
}
- 4.接下来就开始编写实体类,Mapper,跟之前的dao,entity一样,只不过不用写实现类,让Mapper.xml代替
创建实体类
public class User {
private String uname;
private String pwd;
public String getUname() {
return uname;
}
public void setUname(String uname) {
this.uname = uname;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
public User(String uname, String pwd) {
this.uname = uname;
this.pwd = pwd;
}
public User() {
}
@Override
public String toString() {
return "User{" +
"uname='" + uname + '\'' +
", pwd='" + pwd + '\'' +
'}';
}
}
创建Mapper接口
public interface UserMapper {
List<User> getUserList();
}
- 5.开始配置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="com.edu.dao.UserMapper">
<select id="getUserList" resultType="com.edu.pojo.User">
select * from user
</select>
</mapper>
Mapper标签里参数namespace的值为要实现的接口
select标签就代表里边是查询语句,参数id代表实现的方法名,resultType代表返回的结果类型,路径要全,不能只写User
- 6.测试代码
public class UserMapper Test {
@Test
public void getUserList(){
//获取sqlSession对象
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
List<User> userList = UserMapper .getUserList();
for (User user : userList) {
System.out.println(user);
}
sqlSession.close();
}
}
踩坑总结:
- 1.maven的pom.xml配置文件
由于maven对规范要求比较严格,而Mybatis的Mapper文件又要放在java目录下,可能会导致这个资源不能被导出,从而找不到该资源。会报ExceptionInInitializerError,此时要在Build标签里加上
<build> <!--扫描到resources下的xml等资源文件--> <resources> <resource> <directory>src/main/java</directory> <includes> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>true</filtering> </resource> <resource> <directory>src/main/resources</directory> <includes> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>true</filtering> </resource> </resources> </build>
- 2.mabatis-config.xml中
每配置一个XXXMapper.xml都要在这里配置,不然会报BindingException。
更要注意路径层次关系是以斜线分割的,不要用点,不然会找不到这个资源,会报ExceptionInInitializerError。
推测,在xml配置文件中,如果是类路径用点,如Mapper文件中<mapper namespace="com.edu.dao.UserMapper">。如果是配置文件用斜线,如本文件中的 <mapper resource="com/edu/dao/UserMapper.xml"/>
作用域和生命周期
- SqlSessionFactoryBuilder
这个类可以被实例化、使用和丢弃,一旦创建了 SqlSessionFactory,就不再需要它了。 因此 SqlSessionFactoryBuilder 实例的最佳作用域是方法作用域(也就是局部方法变量)。 你可以重用 SqlSessionFactoryBuilder 来创建多个 SqlSessionFactory 实例,但最好还是不要一直保留着它,以保证所有的 XML 解析资源可以被释放给更重要的事情。
SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例。 使用 SqlSessionFactory 的最佳实践是在应用运行期间不要重复创建多次,多次重建 SqlSessionFactory 被视为一种代码“坏习惯”。因此 SqlSessionFactory 的最佳作用域是应用作用域。 有很多方法可以做到,最简单的就是使用单例模式或者静态单例模式。
每个线程都应该有它自己的 SqlSession 实例。SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域。 绝对不能将 SqlSession 实例的引用放在一个类的静态域,甚至一个类的实例变量也不行。 也绝不能将 SqlSession 实例的引用放在任何类型的托管作用域中,比如 Servlet 框架中的 HttpSession。 如果你现在正在使用一种 Web 框架,考虑将 SqlSession 放在一个和 HTTP 请求相似的作用域中。 换句话说,每次收到 HTTP 请求,就可以打开一个 SqlSession,返回一个响应后,就关闭它。 这个关闭操作很重要,为了确保每次都能执行关闭操作,你应该把这个关闭操作放到 finally 块中。
基本操作:
- 搞好了准备工作,增删改查就非常简单了,注意一下sql写法,参数传递。
- 除了查询,增删改要调用一下commit方法,保证数据能正确提交。
- 步骤就是--先写一个接口规范--接着配置xml,类似之前的实现---最后通过sqlsession调用就可以了
增:
UserMapper.java增加方法:
int inserUser(User user);
UserMapper.xml文件:
<insert id="inserUser" parameterType="com.edu.pojo.User"> insert into user(uname,pwd) values(#{uname},#{pwd}); </insert>
id 是接口中方法的名字,parameterType为参数传递的类型,#{.....}是传递的参数,uname必须和实体类中的字段对应。
测试调用代码:
@Test public void inserUser() { SqlSession sqlSession = MybatisUtils.getSqlSession(); UserMapper userMapper = sqlSession.getMapper(UserMapper.class); int i = userMapper.inserUser(new User("maliu", "135")); sqlSession.commit(); System.out.println(i); User user = userMapper.getUserByName("maliu"); System.out.println(user); sqlSession.close(); }
删:
UserMapper.xml文件:
<delete id="deleteUserByName" parameterType="String"> delete from user where uname = #{uname}; </delete>
这里的parameterType可以省略不写,如果参数为基本类型或String可以省略不写。
测试代码:
@Test public void deleteUserByName() { SqlSession sqlSession = MybatisUtils.getSqlSession(); UserMapper userMapper = sqlSession.getMapper(UserMapper.class); userMapper.deleteUserByName("maliu"); sqlSession.commit(); sqlSession.close(); }
改:
UserMapper.xml文件:
<update id="updateUserByName" parameterType="com.edu.pojo.User"> update user set pwd=#{pwd} where uname = #{uname}; </update>
测试代码:
@Test public void updateUserByName() { SqlSession sqlSession = MybatisUtils.getSqlSession(); UserMapper userMapper = sqlSession.getMapper(UserMapper.class); int i = userMapper.updateUserByName(new User("zhangsan", "321")); sqlSession.commit(); sqlSession.close(); }
通过map集合传递参数:
如果根据用户姓名,更改用户姓名怎么办?map集合随意规定键的名字。
接口方法:
int updateUserNameByName(Map<String,Object> map);
mapper.xml:
<update id="updateUserNameByName" parameterType="map"> update user set uname=#{newName} where uname = #{oldName}; </update>
根据key找到对应的value
测试代码:
@Test public void updateUserNameByName(){ SqlSession sqlSession = MybatisUtils.getSqlSession(); UserMapper userMapper = sqlSession.getMapper(UserMapper.class); Map<String, Object> map = new HashMap<String, Object>(); map.put("oldName","zhangsan"); map.put("newName","zhangliu"); int i = userMapper.updateUserNameByName(map); System.out.println(i); sqlSession.commit(); sqlSession.close(); }
模糊查询:
xml:
<select id="getLikeUserList" resultType="com.edu.pojo.User" parameterType="String"> select * from user where uname like "%"#{value}"%"; </select>
用双引号包裹%,单引号不管用
测试代码:
@Test public void getLikeUserList() { //获取sqlSession对象 SqlSession sqlSession = MybatisUtils.getSqlSession(); UserMapper userMapper = sqlSession.getMapper(UserMapper.class); List<User> userList = userMapper.getLikeUserList("zha"); for (User user : userList) { System.out.println(user); } sqlSession.close(); }
至此。。成功入门Mabatis
配置优化:
配置就是配置Mybatis-config.xml
configuration(配置)
- properties(属性)
- settings(设置)
- typeAliases(类型别名)
- typeHandlers(类型处理器)
- objectFactory(对象工厂)
- plugins(插件)
- environments(环境配置)
- databaseIdProvider(数据库厂商标识)
- mappers(映射器)
这些属性都必须按照顺序来写,可以没有,但出现必须按照顺序。
properties(属性)
<properties resource="db.properties"> <!--内部配置--> <property name="password" value="123456"/> </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>
- resource属性指向外部资源文件,从外部引入数据库配置,但是键名要和value中的属性对应
- 内部的property标签,也是对数据库的配置
- 如果两个同时配置,Mybatis查找顺序为,先查找内部配置,在查找外部配置,但是外部配置会覆盖内部属性,也就是同时配置时,内部属性不会生效。
typeAliases(类型别名)
类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置,意在降低冗余的全限定类名书写。
- typeAlias标签
<typeAliases> <typeAlias alias="User" type="edu.pojo.User"/> </typeAliases>
配置好之后Mapper.xml中全类名的写法,就变成了自定义的。
- typeAliases还有一个package标签
<package name="edu.pojo"/>
配置好后pojo包下的所有类都可以使用小写的类名来代替全类名,如果同时也有注解,则选择注解的别名
- 注解的方式
在JavaBean上注解,起别名
@Alias("User") public class User {....}
一些常见类型的别名(官方文档很详细)
基本类型前加下划线 ,如:int别名_int
包装类和集合,都是小写字母,如:Map别名map、Object别名object、Integer别名有integer和int
environments(环境配置)
该标签下可以配置多个environment(环境变量),根据default来选择
不过要记住:尽管可以配置多个环境,但每个 SqlSessionFactory 实例只能选择一种环境。
所以,如果你想连接两个数据库,就需要创建两个 SqlSessionFactory 实例。
mappers(映射器)
为mapper.xml添加映射,官方文档原话(定义 SQL 映射语句)
4种方式:
1.相对于类路径的资源引用
只定位这一个资源文件,每创建一个Mapper.xml就要定义一次。
<mapper resource="edu/dao/UserMapper.xml"/>
2.使用映射器接口实现类的完全限定类名
通过接口找到Mapper.xml。同样只能定位一个资源文件。
<mapper class="edu.dao.UserMapper"/>
3.将包内的映射器接口实现全部注册为映射器将包下的所有接口全部定位到。
<package name="edu.dao"/>
2和3方法:接口和配置文件必须同名才可以被定位到
4.使用完全限定资源定位符(URL)