什么是Mybatis
MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Ordinary Java Object,普通的 Java对象)映射成数据库中的记录。
配置Mybatis在Maven中的依赖
首先新建一个Maven工程项目,在pom.xml文件中加入依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cn.junko</groupId>
<artifactId>eesy_mybatis</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<!---->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
</dependency>
</dependencies>
</project>
在实际使用中,只要导入mybatis和mysql坐标就能够正常使用了,log4j与junit分别是日志与单元测试。
环境搭建
Java程序操作是基于实体类的,而在操作数据库的时候,是基于Dao的,于是我们需要新建
实体类User
main/java/cn/junko/domain
注意:这里的属性名与我之前建好的User表的名字是一致的
package cn.junko.domain;
import java.util.Date;
public class User implements Serializable{
private Integer id;
private String username;
private String sex;
private String address;
private Date birthday;
/* 这里生成各种setter和getter方法,以及toString */
}
接口UserDao
main/java/cn/junko/dao
package cn.junko.Dao;
import cn.junko.domain.User;
import java.util.List;
public interface UserDao {
/**
* 查询所有User表所有
* @return
*/
List<User> findAll();
}
接下来配置Mybatis的配置文件
在项目resources目录下新建一个xml文件,命名没有规范,自己能辨识出来就行 resources/SqlMapConfig.xml
<?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="mysql">
<!--配置mysql环境-->
<environment id="mysql">
<!--配置事务类型-->
<transactionManager type="JDBC"></transactionManager>
<!--配置连接池-->
<dataSource type="POOLED">
<!--连接数据库的四个基本信息-->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/eesy"/>
<property name="username" value="root"/>
<property name="password" value="12345678"/>
</dataSource>
</environment>
</environments>
<!--指定映射配置文件的位置,每个dao独立的配置文件-->
<mappers>
<mapper resource="cn.junko.dao.UserDao.xml"></mapper>
</mappers>
</configuration>
因为我们目前只需要操作User表,因此在resources再新建一个针对UserDao的xml配置文件 需要注意的是,这个xml文件的路径需要对应主配置文件mappers下的路径 resources/cn/junko/dao/UserDao
<?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="cn.junko.dao.UserDao">
<select id="findAll">
select * from user;
</select>
</mapper>
id对应的是Dao接口的方法名findAll
,mapper标签的namespace则为Dao接口的全限定类名
入门案例,尝试完成一个查询
环境配置完成,接下来可以去test里面测试一下是否可以实现
public class MyBatisTest {
public static void main(String[] args) throws Exception {
//1.读取配置文件
InputStream in= Resources.getResourceAsStream("SqlMapConfig.xml");
//2.创建SqlSessionFactory工厂
SqlSessionFactoryBuilder builder=new SqlSessionFactoryBuilder();
SqlSessionFactory factory=builder.build(in);
//3.使用工厂生产SqlSession对象
SqlSession session=factory.openSession();
//4.使用SqlSession创建Dao接口的代理对象(动态代理)
UserDao userDao=session.getMapper(UserDao.class);
//5.使用代理对象执行方法
List<User> users = userDao.findAll();
for (User user : users) {
System.out.println(user);
}
//6.释放资源
session.close();
in.close();
}
结果正常查询出来,控制台显示表中数据
CRUD
经过刚才的配置和简单测试,我们现在可以试着进行一些简单的CRUD操作
为了测试方便,我们进行单元测试的方法,把一些重复的操作抽离出来
private InputStream in;
private SqlSession sqlSession;
private UserDao userDao;
@Before
public void init() throws Exception{
in=Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory factory=new SqlSessionFactoryBuilder().build(in);
sqlSession=factory.openSession();
userDao =sqlSession.getMapper(UserDao.class);
}
@After
public void destroy() throws Exception{
sqlSession.close();
in.close();
}
同样,先从UserDao里面添加方法,在UserDao.xml里面加入对应的标签,最后在测试类里面运行
Mybatis的事务默认是开启的,需要我们手动去提交事务sqlSession.commit();
或者sqlSession=factory.openSession(true);
parameterType:参数的类型。
<insert id="saveUser" parameterType="cn.junko.domain.User">
insert into user(username,address,sex,birthday) values (#{username},#{address},#{sex},#{birthday});
</insert>
<update id="updateUser" parameterType="cn.junko.domain.User">
update user set username=#{username},address=#{address},sex=#{sex} where id=#{id};
</update>
<delete id="deleteUser" parameterType="java.lang.Integer">
delete from user where id = #{id};
</delete>
测试类
@Test
public void testSave(){
User user=new User();
user.setUsername("junko");
user.setSex("男");
user.setAddress("深圳");
user.setBirthday(new Date());
userDao.saveUser(user);
//提交事务
sqlSession.commit();
}
@Test
public void testUpdate(){
User user=new User();
user.setId(52);
user.setUsername("fuwafuwa");
user.setSex("女");
user.setAddress("云南");
user.setBirthday(new Date());
userDao.updateUser(user);
//提交事务
sqlSession.commit();
}
@Test
public void testDelete(){
userDao.deleteUser(52);
sqlSession.commit();
}
一个小细节,在执行完插入操作后,由于表中数据的ID是自增长,我们能否获取到插入数据的ID值?这就需要在insert标签中添加一个操作,这样在执行完插入语句之后,在控制台打印对象,会显示ID值
<insert id="saveUser" parameterType="cn.junko.domain.User">
<selectKey keyProperty="id" keyColumn="id" resultType="int" order="AFTER">
select last_insert_id();
</selectKey>
insert into user(username,address,sex,birthday) values (#{username},#{address},#{sex},#{birthday});
</insert>
- keyProperty=”id” 对应实体类
- keyColumn=”id” 对应数据库表的列名
- resultType=”int” 结果集对应返回int
- order=”AFTER” 在执行插入操作之后
当实体类的属性名和数据库的列名不一致的解决方法
1、修改xml中的sql语句,使用起别名的方式与实体类的名字对应 select id as uid ······
2、使用resultMap
<resultMap id="userMap" type="cn.junko.domain.User">
<!--主键字段对应-->
<id property="userId" column="id"></id>
<!--非主键字段对应-->
<result property="userName" column="username"></result>
<result property="userSex" column="sex"></result>
</resultMap>
标签引用的地方需要作出修改,不再使用resultType
resulMap="userMap"