**
** 简单来说mybatis就是一个持久层框架,我们可以先复习一下持久层和框架两个概念。
框架是我们软件开发中的一套解决方案,不同的框架解决的是不同的问题。 使用框架的好处: 框架封装了很多的细节,使开发者可以使用极简的方式实现功能。大大提高开发效率。
三层架构: 表现层:是用于展示数据的 业务层:是处理业务需求 持久层:是和数据库交互的
我之前也写了了一些关于持久层的技术,像JDBC技术,Spring的JdbcTemplate,Apache的DBUtils,但上述都不是框架。 JDBC是规范,而JdbcTemplate与DBUtils是工具类。
**
** 第一步:创建maven工程并导入坐标 pom文件内容:
<?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>org.example</groupId> <artifactId>Mybatis_CRUD_Learn</artifactId> <version>1.0-SNAPSHOT</version> <dependencies> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.5</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.21</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.12</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> </dependencies> </project>第二步:创建实体类和dao的接口 实体类(这里我创建的是User):
package Gao.domain; import java.io.Serializable; import java.util.Date; public class User implements Serializable { private Integer userId; private String userName; private String userAddress; private String userSex; private Date userBirthday; public Integer getUserId() { return userId; } public void setUserId(Integer userId) { this.userId = userId; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getUserAddress() { return userAddress; } public void setUserAddress(String userAddress) { this.userAddress = userAddress; } public String getUserSex() { return userSex; } public void setUserSex(String userSex) { this.userSex = userSex; } public Date getUserBirthday() { return userBirthday; } public void setUserBirthday(Date userBirthday) { this.userBirthday = userBirthday; } @Override public String toString() { return "User{" + "userId=" + userId + ", userName='" + userName + '\'' + ", userAddress='" + userAddress + '\'' + ", userSex='" + userSex + '\'' + ", userBirthday=" + userBirthday + '}'; } }dao接口:
package Gao.Dao; import Gao.domain.QueryVo; import Gao.domain.User; import java.util.List; public interface UserDao { /** * 查询所有用户 * @return */ List<User> findAll(); /** * 保存用户 * @param user */ void saveUser(User user); /** * 更新用户 * @param user */ void updateUser(User user); /** * 根据Id删除用户 * @param userId */ void deleteUser(Integer userId); /** * 根据id查询用户信息 * @param userId * @return */ User findById(Integer userId); /** * 根据名称模糊查询用户信息 * @param username * @return */ List<User> findByName(String username); /** * 查询总用户数 * @return */ int findTotal(); /** * 根据queryVo中的条件查询用户 * @param vo * @return */ List<User> findUserByVo(QueryVo vo); /** * 根据传入的条件查询 * @param user 传入的user可能有用户名,可能有性别等等条件 * @return */ List<User> findUserByCondition(User user); /** * 根据Queryvo中提供的id集合,查询用户信息 * @param vo * @return */ List<User> findUserInIds(QueryVo vo); }第三步:创建Mybatis的主配置文件(SqlMapConifg.xml) SqlMapConifg.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 url="file:///Users/apple/IdeaProjects/Mybatis_CRUD_Learn/src/main/resources/jdbcConfig.properties"> </properties> <typeAliases> <package name="Gao.domain"></package> </typeAliases> <!--配置环境--> <environments default="mysql"> <!-- 配置mysql的环境--> <environment id="mysql"> <!-- 配置事务 --> <transactionManager type="JDBC"></transactionManager> <!--配置连接池--> <dataSource type="POOLED"> <property name="driver" value="${jdbc.driver}"></property> <property name="url" value="${jdbc.url}"></property> <property name="username" value="${jdbc.username}"></property> <property name="password" value="${jdbc.password}"></property> </dataSource> </environment> </environments> <!-- 配置映射文件的位置 --> <mappers> <package name="Gao.Dao"></package> </mappers> </configuration>对上面xml文件一些标签的解释:
properties标签: 可以在标签内部配置连接数据库的信息。也可以通过属性引用外部配置文件信息,包含resource属性和url属性 resource属性: 常用的用于指定配置文件的位置,是按照类路径的写法来写,并且必须存在于类路径下。 url属性: 是要求按照Url的写法来写地址
typeAliases标签: 使用typeAliases配置别名,它只能配置domain中类的别名。 在typeAliases标签下的typeAlias标签有type属性,指定的是实体类全限定类名。alias属性指定别名,当指定了别名就不再区分大小写。 在typeAliases标签下的package标签有name属性,用于指定要配置别名的包,当指定之后,该包下的实体类都会注册别名,并且类名就是别名,不再区分大小写。
第四步:创建映射配置文件(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="Gao.Dao.UserDao"> <!-- 配置 查询结果的列名和实体类的属性名的对应关系 --> <resultMap id="userMap" type="user"> <!-- 主键字段的对应 --> <id property="userId" column="id"></id> <!--非主键字段的对应--> <result property="userName" column="username"></result> <result property="userAddress" column="address"></result> <result property="userSex" column="sex"></result> <result property="userBirthday" column="birthday"></result> </resultMap> <!-- 查询所有 --> <select id="findAll" resultMap="userMap"> <!--select id as userId,username as userName,address as userAddress,sex as userSex,birthday as userBirthday from user;--> select * from user; </select> <!-- 保存用户 --> <insert id="saveUser" parameterType="user"> <!-- 配置插入操作后,获取插入数据的id --> <selectKey keyProperty="userId" keyColumn="id" resultType="int" order="AFTER"> select last_insert_id(); </selectKey> insert into user(username,address,sex,birthday)values(#{userName},#{userAddress},#{userSex},#{userBirthday}); </insert> <!-- 更新用户 --> <update id="updateUser" parameterType="user"> update user set username=#{userName},address=#{userAddress},sex=#{userSex},birthday=#{userBirthday} where id=#{userId} </update> <!-- 删除用户--> <delete id="deleteUser" parameterType="java.lang.Integer"> delete from user where id = #{uid} </delete> <!-- 根据id查询用户 --> <select id="findById" parameterType="INT" resultMap="userMap"> select * from user where id = #{uid} </select> <!-- 根据名称模糊查询 --> <select id="findByName" parameterType="string" resultMap="userMap"> select * from user where username like #{name} <!-- select * from user where username like '%${value}%'--> </select> <!-- 获取用户的总记录条数 --> <select id="findTotal" resultType="int"> select count(id) from user; </select> <!-- 根据queryVo的条件查询用户 --> <select id="findUserByVo" parameterType="Gao.domain.QueryVo" resultMap="userMap"> select * from user where username like #{user.userName} </select> <!-- 根据不确定的条件查询 --> <select id="findUserByCondition" resultMap="userMap"> select * from user <where> <if test="userName != null"> and username=#{userName} </if> <if test="userSex !=null"> and sex=#{userSex} </if> </where> </select> <!-- 根据Query中的id集合实现用户查询列表 --> <select id="findUserInIds" resultMap="userMap" parameterType="Gao.domain.QueryVo"> select * from user <where> <if test="ids != null and ids.size()>0"> <foreach collection="ids" open="and id in (" close=")" item="uid" separator=","> #{uid} </foreach> </if> </where> </select> </mapper>这个文件就是需要我们写sql语句的文件,现在解读一下这个文件:对于数据库数据的增删改查分别对应着,insert标签,delete标签,update标签,select标签
对于上面四个标签: id对应了UserDao接口的某一个抽象方法。 resultMap代表了查询结果的返回集Map(这个我后面会说)。 parameterType代表了插入的数据的数据类型。
对于resultMap标签,这个标签在某些情况下也是可以不加的,就是当数据库中数据(像我这里的user表)的属性名与Java中自定义的实体类(User类)是一样的。在这种情况下,我们不写resultMap标签写resultType标签,内容就是查询结果的数据类型。所以resultMap的作用就是把数据库数据的属性名与实体类的成员变量名对应起来。
对于mapper标签,namespace里面的内容指定了这个配置文件指向的接口的全类名,而mybatis正是通过这个全类名加上增删改查标签中id属性中的方法名找到的该方法。
大概说完一遍后看一下这些文件在idea中的样子 注意:mybatis的映射配置文件位置必须和dao接口的包结构相同。
最后我们看一下test的测试类(使用了junit测试对每个方法都进行测试):
public class MybatisTest { private InputStream in; private SqlSession sqlSession; private UserDao userDao; @Before//用于在测试方法执行之前执行 public void init()throws Exception{ //1.读取配置文件,生成字节输入流 in = Resources.getResourceAsStream("SqlMapConfig.xml"); //2.获取SqlSessionFactory SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in); //3.获取SqlSession对象 sqlSession = factory.openSession(); //sqlSession=factory.openSession(true); //4.获取dao的代理对象 userDao = sqlSession.getMapper(UserDao.class); } @After//用于在测试方法执行之后执行 public void destroy()throws Exception{ //提交事务 sqlSession.commit(); //6.释放资源 sqlSession.close(); in.close(); } /** * 测试查询所有 */ @Test public void testFindAll(){ //5.执行查询所有方法 List<User> users = userDao.findAll(); for(User user : users){ System.out.println(user); } } /** * 测试保存操作 */ @Test public void testSave(){ User user = new User(); user.setUserName("modify User property"); user.setUserAddress("北京市顺义区"); user.setUserSex("男"); user.setUserBirthday(new Date()); System.out.println("保存操作之前:"+user); //5.执行保存方法 userDao.saveUser(user); System.out.println("保存操作之后:"+user); } /** * 测试更新操作 */ @Test public void testUpdate(){ User user = new User(); user.setUserId(50); user.setUserName("mybastis update user"); user.setUserAddress("北京市顺义区"); user.setUserSex("女"); user.setUserBirthday(new Date()); //5.执行保存方法 userDao.updateUser(user); } /** * 测试删除操作 */ @Test public void testDelete(){ //5.执行删除方法 userDao.deleteUser(43); } /** * 测试删除操作 */ @Test public void testFindOne(){ //5.执行查询一个方法 User user = userDao.findById(50); System.out.println(user); } /** * 测试模糊查询操作 */ @Test public void testFindByName(){ //5.执行查询一个方法 List<User> users = userDao.findByName("%王%"); // List<User> users = userDao.findByName("王"); for(User user : users){ System.out.println(user); } } /** * 测试查询总记录条数 */ @Test public void testFindTotal(){ //5.执行查询一个方法 int count = userDao.findTotal(); System.out.println(count); } /** * 测试使用QueryVo作为查询条件 */ @Test public void testFindByVo(){ QueryVo vo = new QueryVo(); User user = new User(); user.setUserName("%王%"); vo.setUser(user); //5.执行查询一个方法 List<User> users = userDao.findUserByVo(vo); for(User u : users){ System.out.println(u); } } /** *测试查询所有 */ @Test public void testFindByCondition(){ User user=new User(); user.setUserSex("女"); List<User> userList = userDao.findUserByCondition(user); for (User u: userList) { System.out.println(u); } } /** *测试按照id查询集合 */ @Test public void testFindUserInIds(){ QueryVo vo = new QueryVo(); List<Integer> list=new ArrayList<Integer>(); list.add(41); list.add(42); list.add(46); vo.setIds(list); List<User> users = userDao.findUserInIds(vo); for (User user:users) { System.out.println(user); } } }这次写了比较多也比较杂,其实一个简单的mybatis框架使用还是非常简单的,我这里只是实现的方法比较多,并且在配置文件中写了一些一些情况下不必要写的标签。
