Mybatis(一)
零、目录
- Mybatis介绍
- Mybatis入门案例
- 增删改查练习
- 映射文件中取值问题
- Mybatis中单值传递和多值传递问题
- sql语句的复用
- 别名标签
- 动态更新
- 动态查询
- 动态插入
- 批量删除
一、Mybatis介绍
- Mybatis是一款优秀的数据持久层框架
- Mybatis内部也是JDBC原理
- 回顾JDBC缺点:
- 需要频繁的开关数据库连接
- 查询的结果需要手动进行封装
- JDBC中内有缓存机制
- SQL语句写在java代码中
- mybatis优点:
- 内置数据库连接池
- 会自动进行结果集封装
- 自带缓存机制
- SQL语句写在配置文件中
- mybatis工作流程 :
二、 Mybatis入门案例
- 导入约束文件
- 如果你的电脑有网就不用导入了 , 在使用时会自动下载
- 如果你的机器没网 , 需要手动导入mybatis-3-mapper.dtd文件和mybatis-3-config.dtd文件
- 注意导入时 , 需要约束文件在不含中文的路径下 , keyType选择URI , key填写如:http://mybatis.org/dtd/mybatis-3-mapper.dtd 。
- 导入响应的jar包
添加配置文件
日志文件log4j.properties , 不需要改动直接复制即可
log4j.rootLogger=DEBUG, Console #Console log4j.appender.Console=org.apache.log4j.ConsoleAppender log4j.appender.Console.layout=org.apache.log4j.PatternLayout log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n log4j.logger.java.sql.ResultSet=INFO log4j.logger.org.apache=INFO log4j.logger.java.sql.Connection=DEBUG log4j.logger.java.sql.Statement=DEBUG log4j.logger.java.sql.PreparedStatement=DEBUG
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> <!-- 为实体类配置别名 --> <typeAliases> <typeAlias type="com.tj.pojo.User" alias="User"/> </typeAliases> <!-- 配置数据源 --> <environments default="mysql"><!-- 设置默认使用的数据库配置 , 可以根据具体情境随意切换 --> <environment id="mysql"> <!-- 配置事务管理 --> <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> <environment id="oracle"> <transactionManager type="JDBC" /> <dataSource type="POOLED"> <property name="driver" value="oracle.jdbc.driver.OracleDriver" /> <property name="url" value="jdbc:oracle:thin:@127.0.0.1:1521:XE" /> <property name="username" value="ht1602" /> <property name="password" value="htdb" /> </dataSource> </environment> </environments> <!-- 映射文件 --> <mappers> <!-- 注意配置的映射文件的路径 , 而不是全类名 --> <mapper resource="com/tj/pojo/UserMapper.xml" /> </mappers> </configuration>
实体类对应的映射文件(该文件一般由逆向工程通过数据库配置自动生成实体类和对应的映射文件 , 不需要手动写)
<?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="UserMapper"> <sql id="basefind"> select * from user</sql> <select id="findAll" resultType="com.tj.pojo.User" > select * from user; </select> <insert id="insert" parameterType="com.tj.pojo.User"> insert into user(name , age) values( #{name} , #{age}); </insert> <delete id="delete"> delete from user where id=#{id}; </delete> <update id="updaet"> update user set name=#{name} , age = #{age} where id=#{id}; </update> <!-- 根据名字查询 用户 --> <select id="findByName" resultType="User"> <include refid="basefind"/>where name = #{name}; </select> </mapper>
测试代码:
private SqlSession session ; @Before public void init() throws IOException{ //获取一个数据流 InputStream in = Resources.getResourceAsStream("sqlMapConfig.xml"); //创建一个工厂 SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in); //创建一个会话 session = factory.openSession(true);//true表示自动提交 , 默认为false , 需要手动提交 } @Test public void testFindAll() throws IOException{ //执行sql语句 List<User> users = session.selectList("UserMapper.findAll"); System.out.println(users.get(0)); }
三、增删改查练习
以下案例测试之前先创建会话
private SqlSession session ; @Before public void init() throws IOException{ //获取一个数据流 InputStream in = Resources.getResourceAsStream("sqlMapConfig.xml"); //创建一个工厂 SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in); //创建一个会话 session = factory.openSession(true);//true表示自动提交 , 默认为false , 需要手动提交 }
增
映射文件中添加:
<insert id="insert" > insert into user(name , age) values( #{name} , #{age}); </insert>
测试:
@Test public void insertUser() { User user = new User(); user.setName("李四"); user.setAge(20); //執行sql語句 session.insert("UserMapper.insert", user); //提交增删改时都需要commit , 可以在opensession时添加参数为true设置文 自动提交 session.commit(); }
删
映射文件中添加:
<delete id="delete"> delete from user where id=#{id}; </delete>
测试:
@Test public void delete() throws IOException{ //执行session session.delete("UserMapper.delete",3); }
改
映射文件中添加:
<update id="update"> update user set name=#{name} , age = #{age} where id=#{id}; </update>
测试:
@Test public void updateUser(){ //修改之前先获取到原数据 User user = new User(); user.setId(1); user.setName("张三"); user.setAge(19); //对数据进行修改 user.setName("王五"); //执行数据库更新操作 session.update("UserMapper.update", user); }
查
映射文件中添加:
<select id="findAll" resultType="com.tj.pojo.User" > select * from user; </select>
测试:
@Test public void testFindAll() throws IOException{ //执行sql语句 List<User> users = session.selectList("UserMapper.findAll"); System.out.println(users.get(0)); }
四、映射文件中的取值符号
- #{变量名称} : 会在与sql语句拼接时自动加上引号, 并且有预编译的效果 , 可以防止sql注入攻击
- ${变量名称} : 在于sql语句拼接时不会添加引号 , 直接拼接在sql语句中
- 使用两种取值方式的选择:
- 绝大多数情况下使用#{} , 在传入的值为表的字段(如: order by 编号时必须使用 {} , 否则会失效)或者是sql语句的一部分时(如: order by id 升序|降序),必须使用 {} , 否则会生效
- 能使用#{}绝不使用{} , 不能使用#{}时才使用{} .
五、Mybatis映射文件的多值传递和单值传递
Mybatis中提供的增删改查方法只支持传递一个参数代表传入的值
当需要传递多个 值时, 可以将值放入map中 ;
Mapper文件中:
<select id="finfAllByOrderDesc" resultType="User"> select * from user order by ${type} ${paixu}; </select>
测试:
//多值传递 查询所有用户并按照年龄 降序排列 @Test public void findAllOrderByAgeDesc(){ Map<String , String > map = new HashMap<String ,String >(); map.put("type", "age"); map.put("paixu", "desc"); List<User> users = session.selectList("UserMapper.finfAllByOrderDesc" , map); for(User user : users){ System.out.println(user); } }
当传递一个值的时候 ,映射文件中取值时可以以任意变量名取值 。
Mapper文件中:
<select id="findByName" resultType="User"> <include refid="basefind"/>where name = #{xxxxxx}; </select>
测试:
//单值传递 @Test public void findByName(){ User user = session.selectOne("UserMapper.findByName", "王五"); System.out.println(user); }
六、 sql语句的复用
- 声明一个基本的sql语句 , 以便在后续的使用时直接调用
声明:
<sql id="basefind"> select * from user</sql>
调用:
<select id="finfAllByOrderDesc" resultType="User"> <include refid="basefind"/>order by ${type} ${paixu}; </select>
七、别名标签
- 在映射文件中写resultType或者是paramType时需要写的是全类名 , 一般xxx.xxx.xxx.xxx.xxx.类名 都会很长 , 很容易写错 , 可以指定类别名以简化书写
在核心配置文件中配置别名
<!-- 配置别名 --> <typeAliases> <typeAlias type="com.tj.pojo.User" alias="User"/> </typeAliases>
使用
<select id="finfAllByOrderDesc" resultType="User"> <include refid="basefind"/>order by ${type} ${paixu}; </select>
八、 动态更新
- 当进行数据库修改的时候 ,有时只需要修改表中的某几个字段 , 其他字段保持不变 , 这是就需要用到动态更新 , 不然会出现其他值为null的问题 。
映射文件中sql语句的修改
<!-- 动态 更新 --> <select id="dynamicUpdate"> update user <set> <if test="name != null">name = #{name} , </if> <if test="age != null">age = #{age} , </if> </set> where id=#{id} </select>
- 注意: 字段后的“,” , 如果age为空 , set标签会自动把name属性后的“,”去掉
九、 动态查询
- 查询需要多个条件 , 但是不一定每一个条件都用的上 , 在数据封装时就会出现null值的情况 , 如果被sql指定势必会影响到sql 的查询结果 , 这是就需要用到动态查询 , 不然会出现满足条件为null的判断。
映射文件中sql语句的修改
<!-- 动态查询 --> <select id="dyniaicselect"> <include refid="basefind"/> <where> <if test="name != null">name = #{name} </if> <if test="age != null"> and age = #{age} </if> <if test="id != id"> and id = #{id}</if> </where> </select>
- 注意: and加在字段前 , 当name字段为null时 , where标签会自动去掉age前的and 。
十、 动态插入
映射文件中sql语句的修改:
<!-- 动态插入--> <insert id="dyniamicInsert"> insert into user <trim prefix="(" suffix=")" suffixOverrides=","><!-- 设置前缀后缀 , 并且设置将拼接后最后的逗号去掉 --> <if test="name != null">name </if> <if test="age != null"> age </if> </trim> values <trim prefix="(" suffix=")" suffixOverrides=","><!-- 设置前缀后缀 , 并且设置将拼接后最后的逗号去掉 --> <if test="name != null">name = #{name} , </if> <if test="age != null"> age = #{age} </if> </trim> </insert>
十一、批量删除
数组中存放要删除元素的id
<!-- 动态删除 --> <delete id="dynamicdelete"> delete form user where id in <foreach collection="array" item="id" open="(" close=")"<!-- 参数类型是数组 设置前后缀为() , 并且元素之间用“,”拼接 --> separator=","> #{id} </foreach> </delete>
列表中存放要删除的元素
<!-- 动态删除 --> <delete id="dynamicdelete"> delete form user where id in <foreach collection="list" item="user" open="(" close=")" separator=","> #{user.id} </foreach> </delete>