MyBatis入门的详细应用实例
目录
- MyBatis
- 第一章:代理Dao方式的CRUD操作
- 1. 代理Dao方式的增删改查
- 第二章:MyBatis参数详解
- 1. parameterType
- 2. resultType
- 第三章:SqlMapConfig.xml配置文件
- 1. 定义properties标签的方式管理数据库的信息
- 2. 类型别名定义
MyBatis
第一章:代理Dao方式的CRUD操作
1. 代理Dao方式的增删改查
-
创建项目
-
UserMapper接口代码
findAll
方法用于获取所有用户的信息,将以List<User>
形式返回。findById
是根据用户的唯一标识(userId)查找用户信息,返回单个User
对象。insert
方法接收一个User
对象作为参数,将其存储到数据库中。update
方法用于更新用户信息,接收一个User
对象,通过对象的属性值更新数据库中对应记录。delete
方法依据用户 ID 删除相应记录,接收一个Integer
类型的用户 ID。findByName
可根据用户名进行查找,以字符串形式接收用户名,结果以List<User>
形式返回,适用于模糊查询或精确查询。findByCount
方法计算用户的总数,结果以Integer
类型返回。package cn.tx.mapper; import java.util.List; import cn.tx.domain.User; public interface UserMapper { public List<User> findAll(); public User findById(Integer userId); public void insert(User user); public void update(User user); public void delete(Integer userId); public List<User> findByName(String username); public Integer findByCount(); }
-
UserMapper.xml的配置文件代码
元素的 namespace 属性绑定到对应的 UserMapper 接口,确保 XML 中的操作与接口方法关联。
元素中的 findAll 操作,使用 select * from user 语句查询所有用户,结果将映射为 com.qcbyjy.domain.User 类型的对象。
findById 的 select 操作通过 #{id} 占位符接收 findById 方法传入的用户 ID,查询结果映射为 com.qcbyjy.domain.User 类型,参数为 int 类型。
insert 操作除了插入数据的 SQL 语句外,使用 元素在插入操作后执行,通过 select last_insert_id() 获取新插入记录的主键值,keyProperty 指明将主键值存储在 User 对象的 id 属性中,order=“AFTER” 表示在插入之后执行,resultType 为 Integer。
update 操作使用 #{} 占位符接收 update 方法传入的 User 对象的属性,更新用户表中相应记录。
delete 操作使用 #{id} 接收 delete 方法传入的用户 ID,删除相应记录。
findByName 操作的 select 语句使用 like ‘%${value}%’ 进行模糊查询,其中 ${value} 接收 findByName 方法传入的用户名,存在 SQL 注入风险,不推荐使用。
findByCount 操作通过 select count(*) from user 统计用户表中的记录数,结果为 int 类型。
<?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.qcbyjy.mapper.UserMapper"> <select id="findAll" resultType="com.qcbyjy.domain.User"> select * from user </select> <!-- 通过id查询 SQL语句使用#{占位符的名称,名称可以任意},仅限于基本数据类型和String类型 --> <select id="findById" resultType="com.qcbyjy.domain.User" parameterType="int"> select * from user where id = #{id}; </select> <!--保存操作--> <insert id="insert" parameterType="com.qcbyjy.domain.User"> /* keyProperty表示要返回的属性名称 order取值AFTER表示插入数据后的行为 resultType表示返回值的类型 */ <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer"> select last_insert_id(); </selectKey> insert into user (username,birthday,sex,address) values (#{username},#{birthday},#{sex},#{address}) </insert> <!-- 修改 --> <update id="update" parameterType="com.qcbyjy.domain.User"> update user set username = #{username},birthday = #{birthday},sex = #{sex},address=#{address} where id = #{id} </update> <!-- 删除 --> <delete id="delete" parameterType="Integer"> delete from user where id = #{id} </delete> <!-- 模糊查询 --> <select id="findByName" resultType="com.qcbyjy.domain.User" parameterType="string"> <!-- 第一种方式的SQL语句 select * from user where username like #{username} --> <!-- 第二章SQL语句的编写 强调:'%${value}%'不能修改,固定写法(不推荐使用) --> select * from user where username like '%${value}%' </select> <!-- 具体函数的查询 --> <select id="findByCount" resultType="int"> select count(*) from user </select> </mapper>
-
UserTest的代码
- 在
init
方法中,首先使用Resources.getResourceAsStream("SqlMapConfig.xml")
从类路径加载配置文件,然后使用SqlSessionFactoryBuilder
创建SqlSessionFactory
,进而创建SqlSession
,最终通过session.getMapper(UserMapper.class)
获取UserMapper
的代理对象。 - 在
@Before
注解的init
方法中进行资源的初始化,在@After
注解的destory
方法中关闭输入流和SqlSession
,确保资源的正确管理。 testFindAll
测试方法调用mapper.findAll()
方法查询所有用户,将结果存储在List<User>
中并遍历打印。testFindById
测试方法调用mapper.findById(41)
查找 ID 为 41 的用户并打印。testInsert
测试方法创建一个新的User
对象,设置属性,调用mapper.insert(user)
插入用户,使用session.commit()
提交事务,并打印新插入用户的id
。testUpdate
测试方法先查找用户,修改用户信息,调用mapper.update(user)
更新用户信息,再提交事务。testDelete
测试方法调用mapper.delete(48)
删除 ID 为 48 的用户,提交事务。testFindByName
测试方法有两种方式,第一种传入%王%
进行模糊查询,第二种只传入王
,根据配置自动添加通配符进行模糊查询,都将结果存储在List<User>
中并遍历打印。testFindByCount
测试方法调用mapper.findByCount()
获取用户数量并打印。
package cn.tx.test; import java.io.IOException; import java.io.InputStream; import java.util.Date; import java.util.List; 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 cn.tx.domain.User; import cn.tx.mapper.UserMapper; public class UserTest { private InputStream in; private SqlSession session; private UserMapper mapper; @Before public void init() throws Exception { // 加载配置文件 in = Resources.getResourceAsStream("SqlMapConfig.xml"); // 创建工厂对象 SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in); // 创建Session对象 session = factory.openSession(); // 获取到代理对象 mapper = session.getMapper(UserMapper.class); } @After public void destory() throws IOException { in.close(); session.close(); } /** * 测试查询所有的方法 * @throws Exception */ @Test public void testFindAll() throws Exception { List<User> list = mapper.findAll(); // 遍历 for (User user : list) { System.out.println(user); } in.close(); } @Test public void testFindById() throws Exception { User user = mapper.findById(41); System.out.println(user); in.close(); } @Test public void testInsert() throws Exception { User user = new User(); user.setUsername("美美"); user.setBirthday(new Date()); user.setSex("男"); user.setAddress("顺义"); mapper.insert(user); session.commit(); System.out.println(user.getId()); } @Test public void testUpdate() throws Exception { User user = mapper.findById(41); user.setUsername("小凤"); mapper.update(user); session.commit(); } @Test public void testDelete() throws Exception { mapper.delete(48); session.commit(); } // 第一种 @Test public void testFindByName() throws Exception { List<User> list = mapper.findByName("%王%"); for (User user : list) { System.out.println(user); } } // 第二种 @Test public void testFindByName() throws Exception { List<User> list = mapper.findByName("王"); for (User user : list) { System.out.println(user); } } @Test public void testFindByCount() throws Exception { Integer count = mapper.findByCount(); System.out.println("总记录数:"+count); } }
- 在
-
模糊查询符号使用的区别
通过#{}可以实现preparedStatement向占位符中设置值,自动进行java类型和jdbc类型转换,#{}可以有效防止sql注入。 #{}可以接收简单类型值或pojo属性值。 如果parameterType传输单个简单类型值,#{}括号中可以是value或其它名称。 通过$可以将传入的内容拼接在中且不进行类型转换,${}可以将parameterType 传入的内容拼接在sql中且不进行jdbc类型转换, ${}可以接收简单类型值或pojo属性值,如果parameterType传输单个简单类型值,${}括号中只能是value。
第二章:MyBatis参数详解
1. parameterType
-
简单数据类型
int double类型 String类型 long
简单的写法:java.lang.Integer --> int integer Int Integer 都可以,框架提供简写的方式。
-
POJO(JavaBean实体类)对象类型,默认是不能简写,可以配置。
User对象
-
POJO包装对象类型
包含更多的实体类
package cn.tx.domain; import java.io.Serializable; /** * * * * * */ public class QueryVo implements Serializable { // 自己属性 private String name; // user属性 private User user; // role属性 private Role role; public String getName() { return name; } public void setName(String name) { this.name = name; } public User getUser() { return user; } public void setUser(User user) { this.user = user; } public Role getRole() { return role; } public void setRole(Role role) { this.role = role; } } // 测试包装类查询 public List<User> findByVo(QueryVo vo); <!--包装类测试查询--> <select id="findByVo" parameterType="com.qcbyjy.domain.QueryVo" resultType="com.qcbyjy.domain.User"> select * from user where username = #{user.username} </select>
2. resultType
-
返回简单数据类型
int double long String
-
返回POJO数据类型
返回User对象类型
-
resultMap结果类型
resultType可以指定pojo将查询结果映射为pojo,但需要pojo的属性名和sql查询的列名一致方可映射成功。 如果sql查询字段名和pojo的属性名不一致,可以通过resultMap将字段名和属性名作一个对应关系 ,resultMap实质上还需要将查询结果映射到pojo对象中。 resultMap可以实现将查询结果映射为复杂类型的pojo,比如在查询结果映射对象中包括pojo和list实现一对一查询和一对多查询。
<!--演示resultMap配置--> <select id="findUsers" resultMap="userMap"> select id _id,username _username,birthday _birthday,sex _sex,address _address from user </select> <!-- 配置resultMap,用来进行数据封装 id="唯一的名称,用来被引用的" type="进行封装数据的类型" --> <resultMap id="userMap" type="com.qcbyjy.domain.User"> <!-- property="JavaBean中的属性" column="表中的字段" --> <result property="id" column="_id"/> <result property="username" column="_username" /> <result property="birthday" column="_birthday" /> <result property="sex" column="_sex" /> <result property="address" column="_address" /> </resultMap>
第三章:SqlMapConfig.xml配置文件
1. 定义properties标签的方式管理数据库的信息
-
把数据库的信息定义property标签中的方式,在
properties
元素内直接定义jdbc
相关属性,如jdbc.driver
、jdbc.url
等,这些属性在dataSource
元素中通过${}
占位符使用,实现了配置信息的集中管理。<?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> <property name="jdbc.driver" value="com.mysql.jdbc.Driver"/> <property name="jdbc.url" value="jdbc:mysql:///mybatis_db"/> <property name="jdbc.username" value="root"/> <property name="jdbc.password" value="root"/> </properties> <!-- 配置环境们 --> <environments default="mysql"> <!-- 配置具体的环境 --> <environment id="mysql"> <!-- 配置事务管理类型 --> <transactionManager type="JDBC"/> <!-- 配置是否需要使用连接池,POOLED使用,UNPOOLED不使用 --> <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="mappers/UserMapper.xml"/> </mappers> </configuration>
-
在项目中定义jdbc.properties属性文件,存储数据库相关的信息,统一管理,在
SqlMapConfig.xml
中通过<properties resource="jdbc.properties"></properties>
引入,使配置信息更易于维护。-
jdbc.properties属性文件
jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql:///mybatis_db jdbc.username=root jdbc.password=root
-
SqlMapConfig.xml的配置文件
在 environments 元素中设置事务管理类型和数据源类型,数据源类型可选择使用连接池(POOLED)或不使用(UNPOOLED)。
元素加载映射文件,将 UserMapper.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>读取外部的配置文件 resource="文件的相对路径写法"。例如:jdbc.properties 或者 cn/tx/xxx/jdbc.properties --> <properties resource="jdbc.properties"></properties> <!-- 配置环境们 --> <environments default="mysql"> <!-- 配置具体的环境 --> <environment id="mysql"> <!-- 配置事务管理类型 --> <transactionManager type="JDBC"/> <!-- 配置是否需要使用连接池,POOLED使用,UNPOOLED不使用 --> <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="mappers/UserMapper.xml"/> </mappers> </configuration>
2. 类型别名定义
-
MyBatis自已有类型别名的注册类,咱们编写int或者integer通过注册可以找到java.lang.Integer
-
咱们自己也可以进行别名的注册
-
SqlMapConfig.xml的配置文件
<!-- 定义别名 --> <typeAliases> <!-- 把com.qcbyjy.domain.User使用user别名来显示,别名user User USER都可以,默认是忽略大写的 <typeAlias type="com.qcbyjy.domain.User" alias="user"/> --> <!-- 针对com.qcbyjy.domain包下的所有的类,都可以使用当前的类名做为别名 --> <package name="com.qcbyjy.domain"/> </typeAliases>
-
UserMapper.xml的配置文件使用别名
<!-- resultType="com.qcbyjy.domain.User" 原来是全路径 resultType="user" 现在使用的是别名的方式 --> <select id="findAll" resultType="user"> select * from user </select>
-
-