仅方便之后复习
在此之前本地MySQL数据库已经建立了名为mybatis的数据库,且建立了tb_user表。
-- ----------------------------
-- Table structure for `tb_user`
-- ----------------------------
DROP TABLE IF EXISTS `tb_user`;
CREATE TABLE `tb_user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(32) NOT NULL COMMENT '用户名称',
`birthday` date DEFAULT NULL COMMENT '生日',
`sex` char(1) DEFAULT NULL COMMENT '性别',
`address` varchar(256) DEFAULT NULL COMMENT '地址',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=27 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `tb_user` VALUES ('1', '王五', null, '2', null);
INSERT INTO `tb_user` VALUES ('10', '张三', '2014-07-10', '1', '北京市');
INSERT INTO `tb_user` VALUES ('16', '张小明', null, '1', '江西南昌');
INSERT INTO `tb_user` VALUES ('22', '陈小明', null, '1', '江西赣州');
INSERT INTO `tb_user` VALUES ('24', '张三丰', null, '1', '江西樟树');
INSERT INTO `tb_user` VALUES ('25', '李小明', null, '1', '江西南昌');
INSERT INTO `tb_user` VALUES ('26', '王五', null, null, null);
MyBatis是一款优秀的持久层框架,它支持定制化SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。它对jdbc的操作数据库的过程进行封装,使开发者只需要关注 SQL 本身,而不需要花费精力去处理例如注册驱动、创建connection、创建statement、手动设置参数、结果集检索等jdbc繁杂的过程代码。
1.通过pom.xml导入jar包
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.25</version>
</dependency>
2.新建jdbc.properties,log4j.properties和mybatis-config.xml配置文件
#jdbc.properties
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis?useServerPrepStmts=true&cachePrepStmts=true&rewriteBatchedStatements=true
username=root
password=1234
# log4j.properties
# Global logging configuration,建议开发环境中要用debug
log4j.rootLogger= DEBUG, stdout
# Console output... ### 配置输出到控制台 ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
以下是mybatis-config.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>
<properties resource="jdbc.properties"></properties>
<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="mapper/UserMapper.xml"></mapper>
</mappers>
</configuration>
mybatis-config.xml是全局配置文件,MyBatis开发是基本上都是使用映射器进行开发。mybatis框架需要加载映射文件,将UserMapper.xml添加到mybatis-config.xml中。
3.通过xml定义SQL语句
新建UserMapper.xml
UserMapper.xml配置文件中定义映射器,映射器有:
- namespace 命名空间(需要保证唯一)
- id 该SQL语句的唯一表示(相当于函数名,需要保证唯一)
- parameterType 指定输入参数类型,mybatis输入对象中获取参数值拼接在sql中。
- resultType 指定输出结果类型,mybatis将sql查询结果的一行记录数据映射为resultType指定类型的对象。
#{}是占位符,相当于PreparedStatement里的?
${}是拼接符,相当于Statement里直接用“+”号,直接对输入参数进行拼接
定义了四个方法,分别实现增删改查
<?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.edu.jxnuss.dpc.mapper.UserMapper">
<!--通过Id查询User-->
<select id="findUserById" parameterType="java.lang.Integer" resultType="cn.edu.jxnuss.dpc.pojo.User">
select * from tb_user where id=#{id}
</select>
<!--通过姓名模糊查询-->
<select id="findUserByname" parameterType="java.lang.String" resultType="cn.edu.jxnuss.dpc.pojo.User">
select * from tb_user
where username like '%${value}%'
</select>
<!--添加User,并返回自增主键id值-->
<!-- #{}:如果传入的是pojo类型,那么#{}中的变量名称必须是pojo中对应的属性.属性.属性..... 如果要返回数据库自增主键:可以使用select LAST_INSERT_ID() -->
<!-- 执行 select LAST_INSERT_ID()数据库函数,返回自增的主键 keyProperty:将返回的主键放入传入参数的Id中保存.
order:当前函数相对于insert语句的执行顺序,在insert前执行是before,在insert后执行是AFTER resultType:id的类型,也就是keyproperties中属性的类型 -->
<insert id="insertUser" parameterType="cn.edu.jxnuss.dpc.pojo.User">
<selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
select
LAST_INSERT_ID()
</selectKey>
insert into tb_user (username,birthday,sex,address)
values(#{username},#{birthday},#{sex},#{address})
</insert>
<!--删除User-->
<delete id="deleteUserById" parameterType="int">
delete from tb_user where id=#{id}
</delete>
<!--修改User-->
<update id="updateUserById" parameterType="cn.edu.jxnuss.dpc.pojo.User">
update tb_user set username=#{username},sex=#{sex} where id=#{id}
</update>
</mapper>
创建User类作为领域模型
public class User {
private int id;
private String username;// 用户姓名
private String sex;// 性别
private Date birthday;// 生日
private String address;// 地址
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", sex='" + sex + '\'' +
", birthday=" + birthday +
", address='" + address + '\'' +
'}';
}
}
4.准备工作完成,在test里测试代码
通过Mybatis实现数据库增删改查
package cn.edu.jxnuss.dpc.mapper;
import cn.edu.jxnuss.dpc.pojo.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.Before;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.List;
/**
* @program: Mybatis20200301
* @description:
* @author: qingzhu
* @create: 2021-03-01 11:38
*/
public class UserTest {
//会话工厂
SqlSessionFactory sqlSessionFactory;
@Before
public void init() throws IOException {
//配置文件
String resource = "mybatis-config.xml";
//加载配置文件到输入流
InputStream inputStream = Resources.getResourceAsStream(resource);
//创建会话工厂
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
//通过Id搜索User
@Test
public void findUserById() {
//打开会话
SqlSession sqlSession = sqlSessionFactory.openSession();
//通过SqlSession内置的函数调用映射器里配置好的SQL语句,第一个参数指定是哪个映射器,(namespace.id),第二个参数是输入参数
User user = sqlSession.selectOne("cn.edu.jxnuss.dpc.mapper.UserMapper.findUserById",26);
System.out.println(user);
//关闭会话
sqlSession.close();
}
//通过姓名模糊查询
@Test
public void findUserByname() {
SqlSession sqlSession = sqlSessionFactory.openSession();
List<User> list = sqlSession.selectList("cn.edu.jxnuss.dpc.mapper.UserMapper.findUserByname", "王");
System.out.println(list);
sqlSession.close();
}
//添加User,并返回自增主键id值
@Test
public void insertUser() {
SqlSession sqlSession = sqlSessionFactory.openSession();
User user = new User();
user.setUsername("李八");
user.setBirthday(new Date());
user.setSex("男");
user.setAddress("北京昌平");
System.out.println(user.getId());
sqlSession.update("cn.edu.jxnuss.dpc.mapper.UserMapper.insertUser", user);
//如果执行添加、更新、删除需要调用SqlSession.commit()
sqlSession.commit();
System.out.println(user.getId());
sqlSession.close();
}
//删除User
@Test
public void deleteUserById() {
SqlSession sqlSession = sqlSessionFactory.openSession();
sqlSession.delete("cn.edu.jxnuss.dpc.mapper.UserMapper.deleteUserById", 25);
sqlSession.commit();
sqlSession.close();
}
//修改User
@Test
public void updateUserById() {
SqlSession sqlSession = sqlSessionFactory.openSession();
User user = new User();
user.setUsername("小芳");
user.setSex("女");
user.setId(16);
sqlSession.update("cn.edu.jxnuss.dpc.mapper.UserMapper.updateUserById", user);
sqlSession.commit();
sqlSession.close();
}
}
Mybatis解决jdbc编程的问题
1、数据库链接创建、释放频繁造成系统资源浪费从而影响系统性能,如果使用数据库链接池可解决此问题。
解决:在Mybatis_Config.xml中配置数据链接池,使用连接池管理数据库链接。
2、Sql语句写在代码中造成代码不易维护,实际应用sql变化的可能较大,sql变动需要改变java代码。
解决:将Sql语句配置在XXXXmapper.xml文件中与java代码分离。
3、向sql语句传参数麻烦,因为sql语句的where条件不一定,可能多也可能少,占位符需要和参数一一对应。
解决:Mybatis自动将java对象映射至sql语句,通过statement中的parameterType定义输入参数的类型。
4、对结果集解析麻烦,sql变化导致解析代码变化,且解析前需要遍历,如果能将数据库记录封装成pojo对象解析比较方便。
解决:Mybatis自动将sql执行结果映射至java对象,通过statement中的resultType定义输出结果的类型。
附:
注解方式定义sql语句
仅需要在接口方法的地方用注解的方式写sql语句,结果映射,并在mybatis-config.xml文件中添加映射器,调用和xml方式的一样。
package cn.edu.jxnuss.dpc.mapper;
import cn.edu.jxnuss.dpc.pojo.User;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;
public interface UserMapper {
@Select("select * from tb_user where id=#{id}")
@Results(
id="findUserResult", //给resultMap唯一标识
value={
//id=true是主键,column是返回结果集的列名,property是pojo类的属性名
@Result(id=true, column = "id", property = "id"),
@Result(column = "user_id", property = "userId")
}
)
public User findUserById(@Param("id") int id);
}
<?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>
<properties resource="jdbc.properties"></properties>
<typeAliases>
<!-- 单个别名定义 -->
<!-- <typeAlias alias="user" type="cn.edu.jxnuss.dpc.pojo.User"/>-->
<!-- 批量别名定义,扫描整个包下的类,别名为类名(首字母大写或小写都可以)-->
<package name="cn.edu.jxnuss.dpc.pojo"/>
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<!-- <mapper resource="mapper/UserMapper.xml"></mapper>-->
<!-- <mapper resource="mapper/OrderMapper.xml"></mapper>-->
<mapper class="cn.edu.jxnuss.dpc.mapper.UserMapper"></mapper>
<!--用class方式导入-->
</mappers>
</configuration>
测试代码
package cn.edu.jxnuss.dpc.mapper;
import cn.edu.jxnuss.dpc.pojo.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.Before;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import static org.junit.Assert.*;
public class UserMapperTest {
//会话工厂
SqlSessionFactory sqlSessionFactory;
@Before
public void init() throws IOException {
//配置文件
String resource = "mybatis-config.xml";
//加载配置文件到输入流
InputStream inputStream = Resources.getResourceAsStream(resource);
//创建会话工厂
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
@Test
public void findUserById() {
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = userMapper.findUserById(10);
System.out.println(user);
}
}