MyBatis笔记(一)
一、MyBatis是什么?
MyBatis是一个优秀的基于Java的持久层框架,它内部封装了JDBC,使开发者只需要关注SQL语句本身,而不需要花费精力去处理加载驱动、创建连接、创建Statement等繁杂的过程。
二、JDBC有哪些缺点?
JDBC程序示例:
public static void main(String[] args) {
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
try {
//加载数据库驱动
Class.forName("com.mysql.jdbc.Driver");
//通过驱动管理类获取数据库链接
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8", "root", "root");
//定义 sql 语句 ?表示占位符
String sql = "select * from user where username = ?";
//获取预处理 statement
preparedStatement = connection.prepareStatement(sql);
//设置参数,第一个参数为 sql 语句中参数的序号(从 1 开始),第二个参数为设置的参数值
preparedStatement.setString(1, "王五");
//向数据库发出 sql 执行查询,查询出结果集
resultSet = preparedStatement.executeQuery();
//遍历查询结果集
while(resultSet.next()){
System.out.println(resultSet.getString("id")+"
"+resultSet.getString("username"));
}
} catch (Exception e) {
e.printStackTrace();
}finally{
//释放资源
if(resultSet!=null){
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(preparedStatement!=null){
try {
preparedStatement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(connection!=null){
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
JDBC存在的问题:
- 数据库连接创建、释放频繁造成系统资源浪费从而影响系统性能,如果使用数据库连接池可解决此问题。
- SQL语句在代码中硬编码,造成代码不易维护,实际应用SQL变化的可能较大,SQL变动需要改变Java代码。
- 使用PreparedStatement向占有位符号传参数存在硬编码,因为SQL语句的where条件不一定,可能多也可能少,修改SQL还要修改代码,系统不易维护。
- 对结果集解析存在硬编码(查询列名),SQL变化导致解析代码变化,系统不易维护,如果能将数据库记录封装成pojo对象解析比较方便。
三、MyBatis环境搭建步骤
- 创建Maven工程
GroupId: com.itheima
ArtifactId: mybatis01
- 导入依赖坐标
pom.xml
<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.46</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.16</version>
</dependency>
</dependencies>
- 编写实体类
com/itheima/domain/User.java
package com.itheima.domain;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
@Data
public class User implements Serializable {
private Integer id;
private String username;
private Date birthday;
private String sex;
private String address;
}
- 编写持久层接口
com/itheima/dao/UserDao.java
package com.itheima.dao;
import com.itheima.domain.QueryVo;
import com.itheima.domain.User;
import java.util.List;
public interface UserDao {
/**
* 查询所有用户
* @return
*/
List<User> findAll();
/**
* 根据id查询用户
* @param id
* @return
*/
User findById(Integer id);
/**
* 保存用户
* @param user
* @return
*/
int saveUser(User user);
/**
* 更新用户
* @param user
* @return
*/
int updateUser(User user);
/**
* 删除用户
* @param id
* @return
*/
int deleteUser(Integer id);
/**
* 根据用户名模糊查询
* @param username
* @return
*/
List<User> findByName(String username);
/**
* 查询用户数量
* @return
*/
Integer findCount();
/**
* 根据QueryVo中的条件查询用户
* @param vo
* @return
*/
List<User> findByVo(QueryVo vo);
}
- 编写MyBatis配置文件
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>
<typeAliases>
<package name="com.itheima.domain"/>
</typeAliases>
<environments default="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/ee50"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<mappers>
<package name="com.itheima.dao"/>
</mappers>
</configuration>
- 编写映射配置文件
com/itheima/dao/UserDao.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.itheima.dao.UserDao">
<select id="findAll" resultType="User">
select * from user
</select>
<select id="findById" resultType="User" parameterType="int">
select * from user where id = #{id}
</select>
<insert id="saveUser" parameterType="User">
<selectKey keyColumn="id" keyProperty="id" resultType="int">
select last_insert_id();
</selectKey>
insert into user(username, birthday, sex, address)
values(#{username}, #{birthday}, #{sex}, #{address})
</insert>
<update id="updateUser" parameterType="User">
update user set username=#{username}, birthday=#{birthday}, sex=#{sex},
address=#{address} where id=#{id}
</update>
<delete id="deleteUser" parameterType="int">
delete from user where id=#{id}
</delete>
<select id="findByName" parameterType="string" resultType="User">
select * from user where username like #{username}
</select>
<select id="findCount" resultType="int">
select count(*) from user
</select>
<select id="findByVo" resultType="User" parameterType="QueryVo">
select * from user where username like #{user.username}
</select>
</mapper>
- 编写测试类
com/itheima/test/MyBatisTests.java
package com.itheima.test;
import com.itheima.dao.UserDao;
import com.itheima.domain.QueryVo;
import com.itheima.domain.User;
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 org.junit.After;
import org.junit.Before;
import org.junit.Test;
import javax.annotation.Resource;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.List;
public class MyBatisTests {
private InputStream in ;
private SqlSessionFactory factory;
private SqlSession session;
private UserDao userDao;
// 一些共有操作
@Before
public void init() throws IOException{
in = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
factory = builder.build(in);
session = factory.openSession();
userDao = session.getMapper(UserDao.class);
}
@After
public void destroy() throws Exception {
session.commit();
session.close();
in.close();
}
@Test
public void testSelectAll() {
List<User> users = userDao.findAll();
for (User user : users) {
System.out.println(user);
}
}
@Test
public void testSelectById() {
User user = userDao.findById(1);
System.out.println(user);
}
@Test
public void testSaveUser() {
User user = new User();
user.setUsername("xxx");
user.setBirthday(new Date());
user.setSex("男");
user.setAddress("china");
int i = userDao.saveUser(user);
System.out.println(i);
System.out.println(user.getId());
}
@Test
public void testUpdateUser() {
User user = userDao.findById(2);
user.setAddress("JiangSu");
int i = userDao.updateUser(user);
System.out.println(i);
}
@Test
public void testDeleteUser() {
int i = userDao.deleteUser(4);
System.out.println(i);
}
@Test
public void testFindByName() {
List<User> userList = userDao.findByName("%g%");
for (User user : userList) {
System.out.println(user);
}
}
@Test
public void testFindCount() {
int i = userDao.findCount();
System.out.println(i);
}
@Test
public void testFindByVo() {
QueryVo vo = new QueryVo();
User user = new User();
user.setUsername("%w%");
vo.setUser(user);
List<User> userList = userDao.findByVo(vo);
for (User resUser : userList) {
System.out.println(resUser);
}
}
}
四、补充说明
UserDao.java和UserDao.xml两个文件分别在java包和resources包下,其路径必须保持一致且名字相同。UserDao.xml中的mapper的几个属性:namespace为对应的持久层接口UserDao.java的全限定类名,id为UserDao.java中相应的方法名,<selectkey>用于新增User后自动返回id属性值。UserDao.xml中的resultType和parameterType:若是基本类型和String类型,可以直接写类名;若是实体类,如User,则需要写全限定类名。可以在SqlMapConfig.xml中注册别名:
<typeAliases>
<package name="com.itheima.domain"/>
</typeAliases>
注册过后,该包下的实体类都可以用别名,及类名,首字母不区分大小写。
4. 需要在SqlMapConfig.xml中配置映射器(mappers),一种比较方便的方法是设置整个包:
<mappers>
<package name="com.itheima.dao"/>
</mappers>
要求mapper接口和mapper映射文件包路径一致且名字相同。
5. MyBatis也可以不编写mapper映射文件,可以将SQL语句写在mapper接口中相应方法的上面,例如:
/**
* 查询所有用户
* @return
*/
@Select("select * from user")
List<User> findAll();
这种方式少些一个XML文件,看着比较简洁。但是一般工程不采用该方式,个人猜想是因为SQL和Java方法之间产生了耦合,修改维护不方便。

浙公网安备 33010602011771号