一个简单的MyBatis项目(应用)
Posted 沐昱
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一个简单的MyBatis项目(应用)相关的知识,希望对你有一定的参考价值。
### 1. MYBATIS简介
MYBATIS是持久层框架,大大的简化了持久层开发。
当使用MYBATIS框架时,开发人员不必再编写繁琐的JDBC代码,只需要定义好每个功能对应的抽象方法与需要执行的SQL语句即可!
相关文献资料地址:http://www.mybatis.org/mybatis-3/zh/getting-started.html
一、准备工作
1、配置MyBatis开发环境:https://www.cnblogs.com/package-java/p/10316536.html
2、创建数据库:
2-1. 创建新的数据库`tedu_ums`;
CREATE DATABASE tedu_ums;
2-2. 在新数据库中创建数据表`t_user`,表中至少包含id, username, password, age, phone, email这6个属性;
USE tedu_ums;
CREATE TABLE t_user (
id INT AUTO_INCREMENT,
username VARCHAR(20) UNIQUE NOT NULL,
password VARCHAR(20) NOT NULL,
age INT,
phone VARCHAR(20),
email VARCHAR(50),
PRIMARY KEY(id)
) DEFAULT CHARSET=utf8;
2-3. 添加不少于10条数据;
INSERT INTO t_user
(username, password, age, phone, email)
VALUES
(\'root\', \'1234\', 18, \'13800138001\', \'root@tedu.cn\'),
(\'admin\', \'4567\', 19, \'13800138002\', \'admin@tedu.cn\'),
(\'jack\', \'1234\', 20, \'13800138003\', \'jack@tedu.cn\'),
(\'tom\', \'1234\', 22, \'13800138010\', \'tom@tedu.cn\'),
(\'jerry\', \'1234\', 25, \'13800138011\', \'jerry@tedu.cn\'),
(\'rose\', \'1234\', 21, \'13800138004\', \'rose@tedu.cn\'),
(\'mike\', \'1234\', 22, \'13800138005\', \'mike@tedu.cn\'),
(\'lily\', \'1234\', 23, \'13800138006\', \'lily@tedu.cn\'),
(\'lucy\', \'1234\', 24, \'13800138007\', \'lucy@tedu.cn\'),
(\'mary\', \'1234\', 25, \'13800138008\', \'mary@tedu.cn\'),
(\'alex\', \'1234\', 26, \'13800138009\', \'alex@tedu.cn\');
二、创建实体类
每张数据表都应该有1个对应的实体类,所以,创建`cn.tedu.mybatis.entity.User`类,属性的数量与类型请参考数据表的设计:
package cn.tedu.mybatis.entity; import java.io.Serializable; public class User implements Serializable { private static final long serialVersionUID = 1L; private Integer id; private String username; private String password; private Integer age; private String phone; private String email; private Integer isDelete; public Integer getIsDelete() { return isDelete; } public void setIsDelete(Integer isDelete) { this.isDelete = isDelete; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } @Override public String toString() { return "User [id=" + id + ", username=" + username + ", password=" + password + ", age=" + age + ", phone=" + phone + ", email=" + email + ", isDelete=" + isDelete + "]"; } }
三、创建接口,声明抽象方法
创建`cn.tedu.mybatis.mapper.UserMapper`接口,并在接口中声明“插入用户数据”的抽象方法:
package cn.tedu.mybatis.mapper; import java.util.ArrayList; import java.util.List; import cn.tedu.mybatis.entity.User; import cn.tedu.mybatis.vo.UserVO; public interface UserMapper { Integer addnew(User user);//增加数据 User findById(Integer id);//根据id查找用户数据 User findByUsername(String username);//根据用户名username查找用户数据 List<User> findAll(); Integer getCount(); ArrayList<String> finddelect(); List<UserVO> findAll2(); }
关于抽象方法,在MyBatis中,执行的操作如果是增、删、改,返回值均使用`Integer`,表示受影响的行数;方法的名称可以自定义,只要不违反Java的命名规则即可,另外,不允许在接口中使用重载机制;参数也可以自定义,如果执行的是增加操作,参数应该是与数据表对应的实体类的类型。
四、配置接口所在的包
在MyBatis中,通过`MapperScannerConfigurer`类扫描持久层接口的,所以,应该在`spring-dao.xml`文件中进行配置:
<!-- MapperScannerConfigurer --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <!-- 配置接口文件所在的包 --> <property name="basePackage" value="cn.tedu.mybatis.mapper" /> </bean>
五、在XML中配置接口方法对应的SQL语句
在`src/main/resources`下创建名为`mappers`文件夹,mappers文件夹下创建UserMapper.xml文件:
其实,这些XML文件的名称并不重要,可以自由命名,通常,推荐使用与接口文件相同的名称,便于管理。
然后,编写`UserMapper.xml`文件中的内容,首先,根节点必须是`<mapper>`,且根节点的`namespace`表示对应的接口文件,然后,添加子节点,以对应接口中的抽象方法:
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//ibatis.apache.org//DTD Mapper 3.0//EN" "http://ibatis.apache.org/dtd/ibatis-3-mapper.dtd"> <!-- 根节点必须是mapper --> <!-- namespace:对应的接口文件 --> <mapper namespace="cn.tedu.mybatis.mapper.UserMapper"> <!-- 根据执行的操作类型选取节点 --> <!-- id:对应的抽象方法的方法名 --> <!-- 值:使用#{}框住参数User类型中的属性名 --> <!-- 增加数据 --> <insert id="addnew"> INSERT INTO t_user ( username, password, age, phone, email ) VALUES ( #{username}, #{password}, #{age}, #{phone}, #{email} ) </insert> <!-- 根据id查询数据 --> <select id="findById" resultType="cn.tedu.mybatis.entity.User"> SELECT id, age, password, username, phone, email FROM t_user WHERE id=#{id} </select> <!-- 根据用户名查询数据 --> <select id="findByUsername" resultType="cn.tedu.mybatis.entity.User"> SELECT id, age, password, username, phone, email FROM t_user WHERE username=#{username} </select> <!-- 查询所有数据 --> <select id="findAll" resultType="cn.tedu.mybatis.entity.User"> SELECT id, age, password, username, phone, email FROM t_user </select> <select id="getCount" resultType="java.lang.Integer"> SELECT COUNT(id) FROM t_user </select> <!-- 删除数据 --> <delete id="deleteByIds"> DELETE FROM t_user WHERE id IN ( <foreach collection="array" item="id" separator=","> #{id} </foreach> ) </delete> </mapper>
执行查询时,`<select>`节点中必须配置`resultType`属性(或者是`resultMap`属性)。
以上方法执行时,如果查询到匹配的数据,则返回有效的User对象,如果没有匹配的数据,则返回null。
<select id="findByUid" resultType="cn.tedu.store.entity.User"> SELECT username, phone, email, gender, password, salt, is_delete AS isDelete //如果这边给字段名取别名,那别名是cn.tedu.store.entity.User中的属性名,不然数据写不进去 FROM t_user WHERE uid=#{uid} </select>
六、配置XML文件的位置与数据源
MyBatis通过`SqlSessionFactoryBean`获取数据源,并且扫描配置了SQL语句的XML文件,最终由MyBatis框架来执行SQL语句,所以,需要在`spring-dao.xml`中配置`SqlSessionFactoryBean`:
<!-- SqlSessionFactoryBean --> <bean class="org.mybatis.spring.SqlSessionFactoryBean"> <!-- 数据源,值为以上配置BasicDataSource节点的bean-id --> <property name="dataSource" ref="dataSource" /> <!-- XML文件在哪里 --> <property name="mapperLocations" value="classpath:mappers/*.xml" /> </bean>
七、单元测试
package cn.tedu.mybatis.mapper; import java.util.List; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.springframework.context.support.AbstractApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import cn.tedu.mybatis.entity.User; public class UserMapperTestCase { AbstractApplicationContext ac; UserMapper mapper; @Before public void doBefore() { ac = new ClassPathXmlApplicationContext("spring-dao.xml"); mapper = ac.getBean("userMapper", UserMapper.class); } @After public void doAfter() { ac.close(); } @Test public void addnew() { User user = new User(); user.setUsername("fancq"); user.setPassword("666"); Integer rows = mapper.addnew(user); System.out.println("rows=" + rows); } @Test public void findById() { Integer id = 80; User user = mapper.findById(id); System.out.println(user); } @Test public void findByUsername() { String username = "jack"; User user = mapper.findByUsername(username); System.out.println(user); } @Test public void findAll() { List<User> users = mapper.findAll(); for (User user : users) { System.out.println(user); } } @Test public void getCount() { Integer count = mapper.getCount(); System.out.println("count=" + count); } }
八、抽象方法中多个参数的问题
在使用MyBatis时,接口中的抽象方法只允许有1个参数,如果有多个参数,例如:
Integer updatePassword(
Integer id, String password);
在最终运行时,Java源代码会被编译成.class文件,就会丢失参数名称,所以,运行时会提示“找不到某参数”的错误:
Caused by: org.apache.ibatis.binding.BindingException: Parameter \'password\' not found. Available parameters are [arg1, arg0, param1, param2]
解决方案就是“封装”,例如将以上2个参数id、password封装到1个User对象中,或将这2个参数封装到1个Map对象中……但是,无论哪种做法,都存在调用方法不便利的问题,MyBatis提供的解决方案就是添加注解:
Integer updatePassword(
@Param("id") Integer id,
@Param("password") String password);
通过`@Param`注解,当执行时,MyBatis会将多个参数封装为1个Map对象来执行,就不需要开发人员自行封装!
也可以小结为:当抽象方法的参数超过1个时,必须添加`@Param`注解,并且,在XML配置中,使用`#{}`表示的变量的名称其实是`@Param`注解中的值!
以上是关于一个简单的MyBatis项目(应用)的主要内容,如果未能解决你的问题,请参考以下文章
Spring Boot + MyBatis + Thymeleaf实现简单留言板应用
Spring Boot + MyBatis + Thymeleaf实现简单留言板应用