MyBatis的简单使用
2种开发方式
映射文件开发
1.配置主配置文件
2.与数据库关联的实体类
3.映射接口
4.dao接口映射文件
注解开发
1.配置主配置文件
2.与数据库关联的实体类
3.映射接口
4.接口中用注解编写sql动态语句
1.导入maven依赖项目 /pom.xml
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency
其他依赖框架
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.30</version>
</dependency>
2.配置主配置文件 /resources/sqlMapConfig.xml
配置连接数据库的参数,url账户密码等
约束头文件
<?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>
<!--default 表示默认使用哪一个运行环境配置-->
<environments default="mysql">
<!--id="mysql" 表示mysql的运行环境配置-->
<environment id="mysql">
<!--事务管理器配置:基于JDBC的事务控制-->
<transactionManager type="JDBC"></transactionManager>
<!--连接池配置(UNPOOLED/POOLED/JNDI)-->
<!--type="POOLED" 表示使用mybatis自带的连接池-->
<dataSource type="pooled">
<property name="driver" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://URL地址:端口号/数据库名?characterEncoding=utf8"></property>
<property name="username" value="root"></property>
<property name="password" value="root"></property>
</dataSource>
</environment>
</environments>
</configuration>
3.准备实体类
public class User {
private int id;
private String username;
private Date birthday;
private String sex;
private String address;// 省略get set
}
4.准备接口
调用接口会自动调用接口映射文件里的sql语句
/* 数据访问接口*/
public interface IUserDao {
/* 查询查询*/
List<User> findAll();
}
5.dao接口映射文件 resources/IUserDao.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">
<!--namespace 名称空间,表示当前的xml是哪一个接口的映射-->
<mapper namespace="com.itheima.dao.IUserDao">
<!--id 对应的是IUserDao接口的方法名称-->
<!--resultType 方法的返回值类型,如果方法返回的是集合,只要指定集合中元素的类型-->
<!--如何封装数据?mybatis会自动封装数据,要求:查询列名称要与对象的属性名称一致。-->
<select id="findAll" resultType="com.itheima.entity.User">
select * from user
</select>
</mapper>
6.在主配置文件(#2)添加加载接口映射文件(IUserDao.xml)
<configuration>
...
</configuration>
<!--加载接口映射文件 , 可以添加多个-->
<mappers>
<mapper resource="resources/IuserDao.xml"></mapper>
</mappers>
用包扫描的方式
<mappers>
<package name="com.osc.entity"/>
</mappers>
7.运行测试
@Test
public void testApp() throws Exception {
// 1. 获取文件流(获取resources文件下的这个文件)
InputStream in = Resources.getResourceAsStream("sqlMapConfig.xml");
// 2. 创建工厂的构建器
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
// 3. 创建SqlSession的工厂
SqlSessionFactory factory = builder.build(in);
// 3. 创建SqlSession
SqlSession session = factory.openSession();
// 4. 创建接口的代理对象
IUserDao userDao = session.getMapper(IUserDao.class);
// 查看是否是代理对象?
System.out.println(userDao.getClass());
// 5. 调用方法
List<User> list = userDao.findAll();
System.out.println(list);
// 6. 关闭,释放资源
session.close();
in.close();
}
# 扩展资料
映射文件中的 #{ } 和 ${ } 占位符
#{}
一般用于赋值,如where id = #{id} and name = #{name}
${}
用于字符串拼接
findById(String colname , int id);
<select id="findById" parameterType="integer">
<!-- 参数为简单类型,只有一个参数,占位符可以随便写 -->
select * from user where id=#{id123} order by ${colname} desc
</select>
参数为复杂类型(实体类)
findById(String tablename,User user);
<select id="findById" parameterType="com.osc.entity.User" resultType="com.osc.entity.User">
<!-- 必须与实体类的成员名对应 -->
insert into ${tablename} (username,birthday,sex,address)values(#{username},#{birthday},#{sex},#{address})
</select>
<![CDATA[批量转译的内容]]>
在映射文件中不能直接使用 < , > => , <=
<select id="findid">
<![CDATA[
select * from user where id > 3
]]>
</select>
关键字 | 说明 |
---|---|
namespace | 对应接口的类路径 |
id | 对应接口的方法 |
parameterType | 对应方法的形参 |
resultType | 对应方法的返回值 |
resultMap | 当表的列与对象属性不一致才使用 |
ResultMap
public class User{
String username;
Date birthday;
String sex;
String address;
}
<!--指定列与对象属性的映射关系-->
<resultMap id="usmId" type="com.osc.entity.User">
<!--id用来指定主键列与对象属性的映射-->
<id property="id" column="id_"/>
<!--property type中的对象属性;column 查询数据库列的名称-->
<!-- 这里列名的下划线是sql语句加了别名而已,列名以查询结果列 -->
<result property="username" column="username_"/>
<result property="birthday" column="birthday_"/>
<result property="sex" column="sex_"/>
<result property="address" column="address_"/>
</resultMap>
<select id="findAll" resultMap="usmId">
select id as id_, username as username_, birthday as birthday_, sex as sex_, address as address_ from user
</select>
引入/resources/的.properties文件*
在sqlMapConfig.xml主配置文件中加入<properties>
属性,根据属性名${xxx}
取文件里的对应的值
<configuration>
<properties resource="jdbc.properties" ></properties>
<environments default="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>
</configuration>
jdbc.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.username=root
jdbc.password=root
jdbc.url=jdbc:mysql://URL地址:端口号/数据库名?characterEncoding=utf8
映射文件标签
标签名 | 作用 |
---|---|
<if> | 条件生成部分sql语句 |
<where> | where部分的sql语句 |
<set> | 1) 在进行update更新的时候相当于set关键字。 2) 根据传入的参数情况,智能的去掉最后一个多余的逗号 |
<foreach> | 遍历参数 |
<include 和<sql> | 简化编写sql语句的片段 |
selectKey | 操作后返回主键id值 |
if标签
<select id="findByCondition" parameterType="user" resultType="user">
select * from user where 1=1
<!-- 判断,如过id等于0则不会生成标签内语句 -->
<if test="id != 0">
and id=#{id}
</if>
<if test="username != null">
and username=#{username}
</if>
</select>
事例生成结果: select * from user where 1=1 and id=#{id} and username=#{username}
where标签
相当于sql中的where条件语句,if语句里的sql语句全部加上and
<select id="findByCondition" parameterType="user" resultType="user">
select * from user
<where>
<if test="id != 0">
and id=#{id}
</if>
<if test="username != null">
and username=#{username}
</if>
</where>
</select>
事例生成结果: select * from user where id=#{id} and username=#{username}
set标签
<update id="dynamicUpdateUser" parameterType="user">
update user
<set>
<if test="username != null and username !=''">
username=#{username},
</if>
<if test="sex != null and sex !=''">
sex=#{sex},
</if>
</set>
<where>
id=#{id}
</where>
</update>
事例生成结果: update user set username=#{username},sex=#{sex} where id=#{id}
foreach标签
collection : 集合
open : 在前面添加的语句
separator : 每次循环结束后拼接的字符
close : 在后面添加的语句
item : 集合中的子元素名字
<select id="findByCondition2" parameterType="queryvo" resultType="user">
SELECT * FROM USER WHERE 1=1
<if test="ids != null and ids.size()>0">
<foreach collection="ids"
open="and id IN ("
separator=","
close=")"
item="id">
#{id}
</foreach>
</if>
</select>
事例生成结果: select * from user where 1=1 and id in (1,2,3,4,5,6,7)
include和sql标签
<sql id="selectUser">
SELECT * FROM USER WHERE 1=1
</sql>
<select id="findid">
<!--引用SQL片段; refid 属性的值就是sql标签定义的id值-->
<include refid="selectUser"></include>
and id=2
</select>
事例生成结果: SELECT * FROM USER WHERE 1=1 and id=2
selectKey标签
keyColumn 对应表的主键列
keyProperty 对应User对象的唯一标记(OID)
resultType 主键类型
order 查询获取主键的时间
AFTER 表示在执行insert之后,再查询获取主键值
应用: 支持主键自增长的数据库,如:Mysql、sqlserver
BEFORE 表示在执行insert之前,先获取主键值
应用: oracle数据库,要先获取序列值,再把它作为主键
如: select seq_user.nextval from dual;
<insert id="save2" parameterType="com.itheima.entity.User">
<selectKey keyColumn="id" keyProperty="id" resultType="int" order="AFTER">
SELECT LAST_INSERT_ID();
</selectKey>
insert into user(username,birthday,sex,address)
values(#{username},#{birthday},#{sex},#{address})
</insert>
注解方式开发
不需要创建接口映射文件
session直接调用即可
支持混合开发
/* 数据访问接口*/
public interface IUserDao {
/* 注解查询*/
@Select("select * from user")
List<User> findAll();
}
当只有一个形参时,#{id}变量名可以随意
@Select("select * from user where id=#{id}")
User findUserById(int id);
比如
@Select("select * from user where id=#{xxx}")
User findUserById(int id);
形参列表超过一个的时候不能直接写
这是错误写法
@Select("SELECT * FROM USER LIMIT #{index},#{count}")
List<User> findByPage(int index,int count);
应该在每个参数前都加注解 @Param(新变量名)
@Select("SELECT * FROM USER LIMIT #{index},#{count}")
List<User> findByPage3(@Param("index") int index, @Param("count") int count);
或者用arg0,arg1…变量代替(不推荐)
@Select("SELECT * FROM USER LIMIT #{arg0},#{arg1}")
List<User> findByPage2(int index,int count);
当形参时一个实体类时,sql语句必去与实体类的成员变量名一致
public class User{
String username;
Date birthday;
String sex;
String address;
}
@Insert("insert into user(username,birthday,sex,address)values(#{username},#{birthday},#{sex},#{address})")
void save(User user);