一、环境搭建
【下载mybatis】
mybaits的代码由github.com管理,下载地址:https://github.com/mybatis/mybatis-3/releases
下载完后的目录结构:
【创建Java工程】
【加入jar包】
加入mybatis核心包、依赖包、数据驱动包。
- 核心包:
- 依赖包:
- 数据驱动包:
【加入配置文件】
如下图创建资源文件夹config,加入log4j.properties和SqlMapConfig.xml配置文件
在config下创建log4j.properties:(mybatis默认使用log4j作为输出日志信息)
# Global logging configuration 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
在config下创建SqlMapConfig.xml:(SqlMapConfig.xml是mybatis核心配置文件,配置文件内容为数据源、事务管理)
<?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> <!-- 和spring整合后 environments配置将废除 --> <environments default="development"> <environment id="development"> <!-- 使用jdbc事务管理 --> <transactionManager type="JDBC" /> <!-- 数据库连接池 --> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8" /> <property name="username" value="root" /> <property name="password" value="root" /> </dataSource> </environment> </environments> </configuration>
效果如下:
【创建POJO】
pojo类作为mybatis进行sql映射使用,po类通常与数据库表对应,
数据库user表如下图:
User.java如下:
Public class User { private int id; private String username;// 用户姓名 private String sex;// 性别 private Date birthday;// 生日 private String address;// 地址 get/set…… }
【在config下的sqlmap目录下创建sql映射文件User.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:命名空间,用于隔离sql,还有一个很重要的作用,后面会讲 --> <mapper namespace="test"> </mapper>
【加载Mapper.xml映射文件】
将User.xml添加在SqlMapConfig.xml,如下:
二、实现根据id查询用户
使用的sql:SELECT * FROM `user` WHERE id = 1
【映射文件】
在user.xml中添加select标签,编写sql:(解决mybatis在xml映射文件里面写sql时候没有提示的问题)
<?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:命名空间,用于隔离sql,还有一个很重要的作用,后面会讲 --> <mapper namespace="test"> <!-- id:statement的id 或者叫做sql的id--> <!-- parameterType:声明输入参数的类型 --> <!-- resultType:声明输出结果的类型,应该填写pojo的全路径 --> <!-- #{}:输入参数的占位符,相当于jdbc的? --> <select id="queryUserById" parameterType="int" resultType="cn.itcast.mybatis.pojo.User"> SELECT * FROM `user` WHERE id = #{id} </select> </mapper>
【测试程序】
1. 创建SqlSessionFactoryBuilder对象
2. 加载SqlMapConfig.xml配置文件
3. 创建SqlSessionFactory对象
4. 创建SqlSession对象
5. 执行SqlSession对象执行查询,获取结果User
6. 打印结果
7. 释放资源
public class MybatisTest { private SqlSessionFactory sqlSessionFactory = null; @Before public void init() throws Exception{ // 1. 创建SqlSessionFactoryBuilder对象 SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder(); // 2. 加载SqlMapConfig.xml配置文件 InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml"); // 3. 创建SqlSessionFactory对象 sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream); } @Test public void testQueryById() throws Exception { // 4. 创建SqlSession对象 SqlSession sqlSession = sqlSessionFactory.openSession(); // 5. 执行SqlSession对象执行查询,获取结果User // 第一个参数是User.xml的statement的id,第二个参数是执行sql需要的参数; User user = sqlSession.selectOne("queryUserById", 1); // 6. 打印结果 System.out.println(user); // 7. 释放资源 sqlSession.close(); } }
三、实现根据用户名模糊查询用户
查询sql:SELECT * FROM `user` WHERE username LIKE '%王%'
3.1 使用#{}
映射文件——在User.xml配置文件中添加如下内容:
<!-- 如果返回多个结果,mybatis会自动把返回的结果放在list容器中 --> <!-- resultType的配置和返回一个结果的配置一样 --> <select id="queryUserByUsername1" parameterType="string" resultType="cn.itcast.mybatis.pojo.User"> SELECT * FROM `user` WHERE username LIKE #{username} </select>
测试程序:
@Test public void testQueryUserByUsername1() throws Exception { // 4. 创建SqlSession对象 SqlSession sqlSession = sqlSessionFactory.openSession(); // 5. 执行SqlSession对象执行查询,获取结果User // 查询多条数据使用selectList方法 List<Object> list = sqlSession.selectList("queryUserByUsername1", "%王%"); // 6. 打印结果 for (Object user : list) { System.out.println(user); } // 7. 释放资源 sqlSession.close(); }
3.2 使用${}
映射文件:
<!-- 如果传入的参数是简单数据类型,${}里面必须写value --> <select id="queryUserByUsername2" parameterType="string" resultType="cn.itcast.mybatis.pojo.User"> SELECT * FROM `user` WHERE username LIKE '%${value}%' </select>
测试程序:
@Test public void testQueryUserByUsername2() throws Exception { // 4. 创建SqlSession对象 SqlSession sqlSession = sqlSessionFactory.openSession(); // 5. 执行SqlSession对象执行查询,获取结果User // 查询多条数据使用selectList方法 List<Object> list = sqlSession.selectList("queryUserByUsername2", "王"); // 6. 打印结果 for (Object user : list) { System.out.println(user); } // 7. 释放资源 sqlSession.close(); }
四、实现添加用户
使用的sql:INSERT INTO `user` (username,birthday,sex,address) VALUES('黄忠','2016-07-26','1','三国')
【映射文件】
在User.xml配置文件中添加如下内容:
<!-- 保存用户 --> <insert id="saveUser" parameterType="cn.itcast.mybatis.pojo.User"> INSERT INTO `user` (username,birthday,sex,address) VALUES (#{username},#{birthday},#{sex},#{address}) </insert>
【测试程序】
@Test public void testsaveUser() throws Exception { // 创建SqlSession对象 SqlSession sqlSession = sqlSessionFactory.openSession(); // 执行SqlSession对象执行保存 // 创建要保存的对象 User user = new User(); user.setUsername("张飞"); user.setSex("男"); user.setBirthday(new Date()); user.setAddress("蜀国"); sqlSession.insert("saveUser", user); System.out.println(user); // 需要进行事务提交 sqlSession.commit(); //释放资源 sqlSession.close(); }
五、根据id修改用户
使用的sql:UPDATE `user` SET username = '赵云' WHERE id = 26
【映射文件】
<!-- 更新用户 --> <update id="updateUserById" parameterType="cn.itcast.mybatis.pojo.User"> UPDATE `user` SET username = #{username} WHERE id = #{id} </update>
【测试程序】
@Test public void testUpdateUserById() { // 4. 创建SqlSession对象 SqlSession sqlSession = sqlSessionFactory.openSession(); // 5. 执行SqlSession对象执行更新 // 创建需要更新的User User user = new User(); user.setId(26); user.setUsername("关羽"); user.setSex("1"); user.setBirthday(new Date()); user.setAddress("蜀国"); sqlSession.update("updateUserById", user); // 需要进行事务提交 sqlSession.commit(); // 7. 释放资源 sqlSession.close(); }
六、根据用户id删除用户
使用的sql:DELETE FROM `user` WHERE id = 47
【映射文件】
<!-- 删除用户 --> <delete id="deleteUserById" parameterType="int"> delete from user where id=#{id} </delete>
【测试程序】
@Test public void testDeleteUserById() { // 4. 创建SqlSession对象 SqlSession sqlSession = sqlSessionFactory.openSession(); // 5. 执行SqlSession对象执行删除 sqlSession.delete("deleteUserById", 48); // 需要进行事务提交 sqlSession.commit(); // 7. 释放资源 sqlSession.close(); }
七、问题总结
7.1 #{}和${}
#{}表示一个占位符号,通过#{}可以实现preparedStatement向占位符中设置值,自动进行java类型和jdbc类型转换。#{}可以有效防止sql注入。 #{}可以接收简单类型值或pojo属性值。 如果parameterType传输单个简单类型值,#{}括号中可以是value或其它名称。
${}表示拼接sql串,通过${}可以将parameterType 传入的内容拼接在sql中且不进行jdbc类型转换, ${}可以接收简单类型值或pojo属性值,如果parameterType传输单个简单类型值,${}括号中只能是value。
7.2 parameterType和resultType
parameterType:指定输入参数类型,mybatis通过ognl从输入对象中获取参数值拼接在sql中。
resultType:指定输出结果类型,mybatis将sql查询结果的一行记录数据映射为resultType指定类型的对象。如果有多条数据,则分别进行映射,并把对象放到容器List中
7.3 selectOne和selectList
selectOne查询一条记录,如果使用selectOne查询多条记录则抛出异常:
selectList可以查询一条或多条记录。
7.4 mysql自增主键返回
查询id的sql:SELECT LAST_INSERT_ID()
通过修改User.xml映射文件,可以将mysql自增主键返回:
如下添加selectKey 标签
<!-- 保存用户 --> <insert id="saveUser" parameterType="cn.itcast.mybatis.pojo.User"> <!-- selectKey 标签实现主键返回 --> <!-- keyColumn:主键对应表中的哪一列 --> <!-- keyProperty:主键对应的pojo中的哪一个属性 --> <!-- order:设置在执行insert语句之前执行查询id的sql,还是在执行insert语句之后执行查询id的sql; 如果主键的类型为Integer,属于自增长,自增长的方式是:当对数据库进行保存时,先把数据保存下来,然后再生成id塞进去, 这是MySQL生成主键的过程(先保存数据,再生成id);如果主键的类型为varchar类型,或者为uuid的主键,那就是BEFORE, 即先用uuid生成一个ID,然后把数据取来一起保存到数据库中; 如果用的是Oracle,此处为BEFORE,如果用的是MySQL,且主键类型是Integer,此处为AFTER --> <!-- resultType:设置返回的id的类型 --> <selectKey keyColumn="id" keyProperty="id" order="AFTER" resultType="int"> SELECT LAST_INSERT_ID() </selectKey> INSERT INTO `user` (username,birthday,sex,address) VALUES (#{username},#{birthday},#{sex},#{address}) </insert>
LAST_INSERT_ID():是mysql的函数,返回auto_increment自增列新记录id值。
效果如下:
返回的id为48,能够正确的返回id了。
7.5 Mysql使用 uuid实现主键
需要增加通过select uuid()得到uuid值
<!-- 保存用户 --> <insert id="saveUser" parameterType="cn.itcast.mybatis.pojo.User"> <!-- selectKey 标签实现主键返回 --> <!-- keyColumn:主键对应的表中的哪一列 --> <!-- keyProperty:主键对应的pojo中的哪一个属性 --> <!-- order:设置在执行insert语句前执行查询id的sql,孩纸在执行insert语句之后执行查询id的sql --> <!-- resultType:设置返回的id的类型 --> <selectKey keyColumn="id" keyProperty="id" order="BEFORE" resultType="string"> SELECT LAST_INSERT_ID() </selectKey> INSERT INTO `user` (username,birthday,sex,address) VALUES (#{username},#{birthday},#{sex},#{address}) </insert>