简介
什么是mybatis:mybatis是一款优秀的持久层框架,支持定制化SQL、存储过程以及高级映射,避免了几乎所有的JDBC代码和手动设置参数以及获取结果集。Mybatis可以使用简单的XML或者注解来配置和映射原生类型、接口和Java的POJO为数据库中的记录。
mybatis开始
先去mybatis官网点了这里
第一步:引入maven
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>x.x.x</version>
</dependency>
第二步:Building SqlSessionFactory from XML(搭建SqlSessionFactory环境):
<?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>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="org/mybatis/example/BlogMapper.xml"/>
</mappers>
</configuration>
编写的工具类:
官网中要求必须在类中引入:
String resource = “org/mybatis/example/mybatis-config.xml”;
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory =
new SqlSessionFactoryBuilder().build(inputStream);
这是通过Builder获得SqlSessionFactory的方式。
工具类:
package com.mao.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;
//sqlSessionFactory --> sqlSession
public class MybatisUtil {
private static SqlSessionFactory sqlSessionFactory;
static {
try {
String resource = "mybatis.config.xml";
InputStream inputStream = null;
inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory =
new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
//既然有了SqlsessionFactory,顾名思义,我们可以从中得到SqlSession实例.
//SqlSession包含了面向数据库执行SQL命令所需要的方法
public static SqlSession getSqlSession(){
return sqlSessionFactory.openSession();
}
}
写一个实体类映射数据库中的表:
package com.mao.pojo;
import lombok.Data;
@Data
public class User {
private int id;
private String username;
private String password;
}
有了实体类就可以去定义一个数据访问层接口:
package com.mao.dao;
import com.mao.pojo.User;
public interface UserDao {
User getUser(Integer id);
}
其具体的实体类并不用写,而是通过指定的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">
<mapper namespace="com.mao.dao.UserDao">
<select id="getUser" resultType="com.mao.pojo.User">
select * from user where id = #{id}
</select>
</mapper>
注意:这里要指定mapper的命名空间,即是所对应的接口,select标签中的id对应指定的方法名,resultType就是返回值。
注意:当sqlSession用完的时候应当关闭,否则会造成内存的浪费。
CRUD
1.namespace
namespace中的包名要和Dao/Mapper中的接口的包名一致。
UserDao接口
package com.mao.dao;
import com.mao.pojo.User;
import java.util.List;
public interface UserDao {
/**
* 通过id返回User
* @param id
* @return
*/
User getUserById(Integer id);
/**
* 返回所有User
* @return
*/
List<User> getUserList();
/**
* 添加用户
* @param user
* @return
*/
int addUser(User user);
/**
* 更新用户
* @param user
* @return
*/
int updateUser(User user);
/**
* 删除指定用户
* @param id
* @return
*/
int deleteUser(int id);
}
UserMapper.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.mao.dao.UserDao">
<select id="getUserById" resultType="com.mao.pojo.User">
select * from user where id = #{id}
</select>
<select id="getUserList" resultType="com.mao.pojo.User">
select * from study.user
</select>
<insert id="addUser" parameterType="com.mao.pojo.User">
insert into study.user(id,username,password) values (#{id},#{username},#{password})
</insert>
<update id="updateUser" parameterType="com.mao.pojo.User">
update study.user set username=#{username},password=#{password} where id=#{id}
</update>
<delete id="deleteUser">
delete from study.user where id=#{id}
</delete>
</mapper>
Junit测试
package com.mao.dao;
import com.mao.pojo.User;
import com.mao.utils.MybatisUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import java.util.List;
import static org.junit.Assert.*;
public class UserDaoTest {
@Test
public void getUserById() {
SqlSession sqlSession = MybatisUtil.getSqlSession();
try {
UserDao userDao = sqlSession.getMapper(UserDao.class);
User user = userDao.getUserById(1);
System.out.println(user);
}catch (Exception e){
e.printStackTrace();
}finally {
sqlSession.close();
}
}
@Test
public void getUserList() {
SqlSession sqlSession = MybatisUtil.getSqlSession();
try {
UserDao userDao = sqlSession.getMapper(UserDao.class);
List<User> userList = userDao.getUserList();
System.out.println(userList);
} catch (Exception e) {
e.printStackTrace();
} finally {
sqlSession.close();
}
}
@Test
public void addUser() {
SqlSession sqlSession = MybatisUtil.getSqlSession();
try {
User user = new User();
user.setId(4);
user.setUsername("张天伟");
user.setPassword("123456");
UserDao userDao = sqlSession.getMapper(UserDao.class);
int i = userDao.addUser(user);
System.out.println(i);
//这一步很关键,增删改等DML是需要提交事务的
sqlSession.commit();
} catch (Exception e) {
e.printStackTrace();
} finally {
sqlSession.close();
}
}
@Test
public void updateUser() {
SqlSession sqlSession = MybatisUtil.getSqlSession();
try {
User user = new User();
user.setId(4);
user.setUsername("张地瓜");
user.setPassword("438");
UserDao userDao = sqlSession.getMapper(UserDao.class);
int i = userDao.updateUser(user);
sqlSession.commit();
System.out.println(i);
} catch (Exception e) {
e.printStackTrace();
} finally {
sqlSession.close();
}
}
@Test
public void deleteUser(){
SqlSession sqlSession = MybatisUtil.getSqlSession();
try {
UserDao mapper = sqlSession.getMapper(UserDao.class);
int i = mapper.deleteUser(3);
sqlSession.commit();
System.out.println(i);
} catch (Exception e) {
e.printStackTrace();
} finally {
sqlSession.close();
}
}
}
注意
注意,要知道mysql是支持事务的,所以增删改等DML语句需要在操作完成时提交一下事务,否则会因为事务的ACID特性导致操作未显示。
万能的Map
在mybatis中使用Map的时候只需要再接口中使用Map,而在xxMapper.xml中parameterType指定为map,就可以像一个对象一样去使用它了。注:
1.使用Map中的参数,直接在sql中取其key即可【parameterType=map】
2.使用对象中的属性,直接在sql中取其属性即可【parameterType=Object】
只有一个基本类型的时候直接取该基本类型即可,多个的话就要用到map,
或者用注解,用上述的getUserById来演示一下:
Dao层接口代码:
/**
* 用Map来演示
* @param map
* @return
*/
int getUserById2(Map<String,Object> map);
xxMapper.xml:
<select id="getUserById2" parameterType="map">
select * from user where id = #{id}
</select>
junit:
@Test
public void getUserById2() {
SqlSession sqlSession = MybatisUtil.getSqlSession();
try {
UserDao userDao = sqlSession.getMapper(UserDao.class);
HashMap<String, Object> map = new HashMap<String, Object>();
map.put("id",1);
User user = userDao.getUserById(1);
System.out.println(user);
}catch (Exception e){
e.printStackTrace();
}finally {
sqlSession.close();
}
}
输出结果:
注意
这里有两个注意点:
1.一般公司里如果用xml配置方式的话普遍推荐使用map,因为那时候将会遇到有很多属性的类,用map显然在灵活性上比对象更好操作
2.mybatis中是以方法名为id的,所以同一个Mapper是不支持重载的,这也是为什么我在上面中要将方法的名字改为getUserById2
Mybatis的配置优化
- configuration(配置)
- properties(属性):这些属性都是可外部配置且可动态替换的,既可以在典型的 Java 属性文件中配置,亦可通过 properties 元素的子元素来传递。相当于可以读取配置文件的值,还可以在其中设置值,如果存在和外部文件相同的值,优先取外部的值
- settings(设置):对一些属性进行配置
- typeAliases(类型别名):设置别名,可以减少包名的输入,增加开发效率。可以给包起别名,也可以给类取别名:下面是给类取别人
<typeAliases>
<typeAlias alias="Author" type="domain.blog.Author"/>
<typeAlias alias="Blog" type="domain.blog.Blog"/>
<typeAlias alias="Comment" type="domain.blog.Comment"/>
<typeAlias alias="Post" type="domain.blog.Post"/>
<typeAlias alias="Section" type="domain.blog.Section"/>
<typeAlias alias="Tag" type="domain.blog.Tag"/>
</typeAliases>
给包取别名:
<typeAliases>
<package name="domain.blog"/>
</typeAliases>
每一个在包 domain.blog 中的 Java Bean,在没有注解的情况下,会使用 Bean 的首字母小写的非限定类名来作为它的别名。 比如 domain.blog.Author 的别名为 author;若有注解,则别名为其注解值。
注意:如果实体类比较少推荐用第一种,如果比较多用第二种。第一种可以在配置中取别名,第二种不行,不过可以用注解来取别名。
@Alias("author")
public class Author {
...
}
如果同一个类注解和配置中都有,优先取注解。
- typeHandlers(类型处理器):无需太了解
- objectFactory(对象工厂):无需太了解
- plugins(插件):无需太了解
- environments(环境配置)
- environment(环境变量)
- transactionManager(事务管理器):分位jdbc和manager,服务于ejb,如果用spring完全不用配置。
- dataSource(数据源):连接数据库所用,POOLED和UNPOOLED,有池和无池,如果是POOLED就在用完之后不会销毁,而是放回POOLED。
- databaseIdProvider(数据库厂商标识)
- mappers(映射器):注册绑定我们配置的mapper.xml文件
resultMap的引用
我们在开发中可能会遇到这样的一种情况,就是数据库中的表字段和对应实体类的属性名不一致,这时候查询就会发现该属性本来应该有值却没有,比如我把上面那对象中的User对象的password改为psd,再做一次查询得到:
这时候就要用到,resultMap了,该属性就是可以实现把数据库中的列名和属性名做一个映射的效果。
代码:
<mapper namespace="com.mao.dao.UserDao">
<resultMap id="userMap" type="user">
<result column="password" property="psd"></result>
</resultMap>
<select id="getUserById" resultType="user" resultMap="userMap">
select * from user where id = #{id}
</select>
</mapper>
实现效果: