1、mybatis的介绍
2、分析jdbc的问题
3、mybatis框架原理
4、mybatis入门程序
5、主键策略
6、小结
7、mybatis开发dao的方式--原始dao开发方式
8、mybatis开发dao的方式--Mapper代理的开发方式
9、全局配置文件
10、映射文件--输入参数
11、映射文件--输出结果
12、动态sql
13、mybatis与hibernate的区别及各自应用场景
1、mybatis的介绍 <--返回目录
* mybatis就是一个封装了jdbc的【持久层框架】,它和hibernate都属于ORM(Object Relational Mapping对象关系映射)框架,
但是具体来说,hibernate是一个完全的orm框架,而mybatis是一个不完全的orm框架
* Mybatis让程序员只关注sql本身,而不需要去关注连接的创建、statement的创建等操作。
* Mybatis会将输入参数、输出结果进行映射。
2、分析jdbc的问题 <--返回目录
原生态的jdbc代码
public static void main(String[] args) { Connection connection = null; PreparedStatement preparedStatement = null; ResultSet resultSet = null; try { //1、加载数据库驱动 Class.forName("com.mysql.jdbc.Driver"); //2、通过驱动管理类获取数据库连接 connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8", "root", "root"); //3、定义sql语句 ?表示占位符 String sql = "select * from user where username = ?"; //4、获取预处理statement preparedStatement = connection.prepareStatement(sql); //5、给sql语句中的?赋值;设置参数,第一个参数为sql语句中参数的序号(从1开始),第二个参数为设置的参数值 preparedStatement.setString(1, "王五"); //6、向数据库发出sql执行查询,查询出结果集 resultSet = preparedStatement.executeQuery(); //7、遍历结果集 while(resultSet.next()){ System.out.println(resultSet.getString("id")+" "+resultSet.getString("username")); } } catch (Exception e) { e.printStackTrace(); }finally{ //8、释放资源 if(resultSet!=null){ try { resultSet.close(); } catch (SQLException e) { e.printStackTrace(); } } if(preparedStatement!=null){ try { preparedStatement.close(); } catch (SQLException e) { e.printStackTrace(); } } if(connection!=null){ try { connection.close(); } catch (SQLException e) { e.printStackTrace(); } } } }
问题总结
1)在创建连接时,存在硬编码
配置文件(全局配置文件)
2)在执行statement时存在硬编码
配置文件(映射文件)
3)频繁的开启和关闭数据库连接,会造成数据库性能下降。
数据库连接池(全局配置文件)
3、mybatis框架原理 <--返回目录
4、mybatis入门程序 <--返回目录
选中 config文件夹, 右键-> Build Path -> Use as Source Folder
需求:对订单商品案例中的用户表进行增删改查操作
1) 根据用户ID查询用户信息--加载load
2) 根据用户名称模糊查询用户列表--列表展示list,带条件的分页查询
3) 添加用户
4) 删除用户
5) 修改用户
环境准备
- Jdk:1.8
- IDE:eclipse
- Mybatis:3.2.7
- 数据库:MySQL 5.X
下载mybatis: mybaits的代码由github.com管理,下载地址:https://github.com/mybatis/mybatis-3/releases
sql 脚本
create database db_mybatis_01 default character set utf8; use db_mybatis_01; CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `username` varchar(32) NOT NULL COMMENT '用户名称', `birthday` date DEFAULT NULL COMMENT '生日', `sex` char(1) DEFAULT NULL COMMENT '性别', `address` varchar(256) DEFAULT NULL COMMENT '地址', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=27 DEFAULT CHARSET=utf8; insert into `user`(`id`,`username`,`birthday`,`sex`,`address`) values (1,'王五',NULL,'2',NULL), (2,'张三','2014-07-10','1','北京市'), (3,'张小明',NULL,'1','河南郑州'), (4,'陈小明',NULL,'1','河南郑州'), (5,'张三丰',NULL,'1','河南郑州'), (6,'陈小明',NULL,'1','河南郑州'), (7,'王五',NULL,NULL,NULL);
导入jar包
- 核心jar:mybatis-3.2.7.jar
- 依赖jar:lib目录下,9个
- mysql 驱动:mysql-connector-java-5.1.40-bin.jar
创建全局配置文件
<?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="db.username" value="123" /> --> <properties resource="db.properties"> </properties> <!-- <settings></settings> --> <!-- 自定义别名 --> <typeAliases> <!-- 单个别名定义 --> <!-- <typeAlias type="com.oy.mybatis.po.User" alias="user"/> --> <!-- 批量别名定义(推荐) --> <!-- package:指定包名称来为该包下的po类声明别名,默认的别名就是类名(首字母大小写都可) --> <!-- <package name="com.oy.mybatis.po" /> --> </typeAliases> <!-- 配置mybatis的环境信息,与spring整合后,该信息由spring来管理 --> <environments default="development"> <environment id="development"> <!-- 配置JDBC事务控制,由mybatis进行管理 --> <transactionManager type="JDBC"></transactionManager> <!-- 配置数据源,采用mybatis连接池 --> <dataSource type="POOLED"> <property name="driver" value="${db.driver}" /> <property name="url" value="${db.url}" /> <property name="username" value="${db.username}" /> <property name="password" value="${db.password}" /> </dataSource> </environment> </environments> <!-- 加载映射文件 --> <mappers> <mapper resource="User.xml" /> <!-- <mapper resource="mapper/UserMapper.xml" /> --> <!-- 批量加载映射文件 --> <!-- <package name="com.oy.mybatis.mapper" /> --> </mappers> </configuration>
数据库的配置文件 db.properties
db.driver=com.mysql.jdbc.Driver db.url=jdbc:mysql://localhost:3306/db_mybatis_01?useUnicode=true&characterEncoding=utf8 db.username=root db.password=
log4j.properties
# 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
或
log4j.rootLogger=info,appender1,appender2
log4j.appender.appender1=org.apache.log4j.ConsoleAppender
log4j.appender.appender2=org.apache.log4j.FileAppender
log4j.appender.appender2.File=d:/logFile.txt
log4j.appender.appender1.layout=org.apache.log4j.TTCCLayout
log4j.appender.appender2.layout=org.apache.log4j.TTCCLayout
User 实体类
package com.oy.domain; import java.sql.Date; public class User { private int id; private String username; // 用户名 private Date birthday; // 生日 private String sex; // 性别 private String address; // 地址 // getXxx和setXxx @Override public String toString() { return "User [id=" + id + ", username=" + username + ", birthday=" + birthday + ", sex=" + sex + ", address=" + address + "]"; } }
映射文件 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:命名空间,对statement的信息进行分类管理 --> <!-- 注意:在mapper代理时,它具有特殊及重要的作用 --> <mapper namespace="test"> <!-- 根据用户ID查询用户信息 --> <!-- select:表示一个MappedStatement对象 --> <!-- id:statement的唯一标示 --> <!-- #{}:表示一个占位符? --> <!-- #{id}:里面的id表示输入参数的参数名称,如果该参数是简单类型,那么#{}里面的参数名称可以任意 --> <!-- parameterType:输入参数的java类型 --> <!-- resultType:输出结果的所映射的java类型(单条结果所对应的java类型) --> <select id="findUserById" parameterType="int" resultType="com.oy.domain.User"> SELECT * FROM USER WHERE id =#{id} </select> <select id="findUsersByName" parameterType="java.lang.String" resultType="com.oy.domain.User"> SELECT * FROM USER WHERE username LIKE '%${value}%' </select> <!-- 添加用户 --> <!-- selectKey:查询主键,在标签内需要输入查询主键的sql --> <!-- order:指定查询主键的sql和insert语句的执行顺序,相当于insert语句来说(表示:什么时候获取主键id,是在insert语句之前,还是之后) --> <!-- LAST_INSERT_ID:该函数是mysql的函数,获取自增主键的ID,它必须配合insert语句一起使用 --> <insert id="insertUser" parameterType="com.oy.domain.User"> <selectKey keyProperty="id" resultType="int" order="AFTER"> SELECT LAST_INSERT_ID() </selectKey> INSERT INTO USER(username,birthday,sex,address) VALUES(#{username},#{birthday},#{sex},#{address}) </insert> <!-- 删除用户 --> <delete id="deleteUserById" parameterType="int"> delete from user where id = #{id} </delete> <!-- 修改用户 --> <update id="updateUserById" parameterType="int"> update user set username = '张小三' where id = #{id} </update> </mapper>
测试类
package com.oy.test; import java.io.InputStream; 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.jupiter.api.Test; import com.oy.domain.User; public class Test1 { /** * 按id查询用户 * @throws Exception */ @Test public void findUserByIdTest() throws Exception { //读取配置文件 //全局配置文件的路径 String resource = "SqlMapConfig.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); //创建SqlSessionFactory SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); //创建SqlSession SqlSession sqlSession = sqlSessionFactory.openSession(); //调用SqlSession的增删改查方法 //第一个参数:表示statement的唯一标示 User user = sqlSession.selectOne("test.findUserById", 1); System.out.println(user); //关闭资源 sqlSession.close(); } /** * 按username查询用户 * @throws Exception */ @Test public void findUsersByNameTest() throws Exception{ //读取配置文件 //全局配置文件的路径 String resource = "SqlMapConfig.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); //创建SqlSessionFactory SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); //创建SqlSession SqlSession sqlSession = sqlSessionFactory.openSession(); //调用SqlSession的增删改查方法 //第一个参数:表示statement的唯一标示 List<User> list = sqlSession.selectList("test.findUsersByName", "小明"); for(User user:list){ System.out.println(user); } //关闭资源 sqlSession.close(); } /** * 添加用户 * @throws Exception */ @Test public void insertUserTest() throws Exception{ //读取配置文件 //全局配置文件的路径 String resource = "SqlMapConfig.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); //创建SqlSessionFactory SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); //创建SqlSession SqlSession sqlSession = sqlSessionFactory.openSession(); User user = new User(); user.setUsername("东哥hm19"); user.setAddress("宝盛西里24号楼"); //调用SqlSession的增删改查方法 //第一个参数:表示statement的唯一标示 sqlSession.insert("test.insertUser", user); int id = user.getId(); //System.out.println(user.getId()); User user2 = sqlSession.selectOne("test.findUserById", id); System.out.println(user2); //提交事务 sqlSession.commit(); //关闭资源 sqlSession.close(); } /** * 删除用户 * @throws Exception */ @Test public void deleteUserByIdTest() throws Exception{ //读取配置文件 //全局配置文件的路径 String resource = "SqlMapConfig.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); //创建SqlSessionFactory SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); //创建SqlSession SqlSession sqlSession = sqlSessionFactory.openSession(); //调用SqlSession的增删改查方法 //第一个参数:表示statement的唯一标示 //先查询要删除的user,然后删除 User user = sqlSession.selectOne("test.findUserById", 28); System.out.println(user); sqlSession.delete("test.deleteUserById", 28); //提交事务 sqlSession.commit(); //关闭资源 sqlSession.close(); } /** * 按id修改用户 * @throws Exception */ @Test public void updateUserByIdTest() throws Exception{ //读取配置文件 //全局配置文件的路径 String resource = "SqlMapConfig.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); //创建SqlSessionFactory SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); //创建SqlSession SqlSession sqlSession = sqlSessionFactory.openSession(); //调用SqlSession的增删改查方法 //第一个参数:表示statement的唯一标示 User user = sqlSession.selectOne("test.findUserById", 10); System.out.println(user); sqlSession.update("test.updateUserById", 10); User user2 = sqlSession.selectOne("test.findUserById", 10); System.out.println(user2); //提交事务 sqlSession.commit(); //关闭资源 sqlSession.close(); } }
5、主键策略 <--返回目录
主键策略为自增时的执行顺序为:order="AFTER"
INSERT INTO `user`(`username`,`birthday`,`sex`,`address`) VALUES ('王五',NULL,'2',NULL); SELECT LAST_INSERT_ID(); //在insert语句执行完后,获取id。即获取上面记录的id
主键策略为:uuid
<!-- 主键策略为:UUID --> <insert id="insertUser2" parameterType="com.oy.domain.User"> <selectKey keyProperty="id" resultType="string" order="BEFORE"> SELECT UUID() </selectKey> INSERT INTO USER (id,username,birthday,sex,address) VALUES(#{id},#{username},#{birthday},#{sex},#{address}) </insert>
主键策略为uuid时的执行顺序为:order="BEFORE"
SELECT UUID(); INSERT INTO USER(id,username,birthday,sex,address) VALUES(#{id},#{username},#{birthday},#{sex},#{address});
主键返回值序列:序列也就是sequence,它是Oracle的主键生成策略
<!-- 主键之sequence --> <insert id="insertUser3" parameterType="com.oy.domain.User"> <selectKey keyProperty="id" resultType="int" order="BEFORE"> SELECT seq.nextval FROM dual </selectKey> INSERT INTO USER (id,username,birthday,sex,address) VALUES(#{id},#{username},#{birthday},#{sex},#{address}) </insert>
6、小结 <--返回目录
* #{}和${}
#{}表示占位符?,#{}接收简单类型的参数时,里面的名称可以任意
${}表示拼接符,${}接收简单类型的参数时,里面的名称必须是value
${}里面的值会原样输出,不加解析(如果该参数值是字符串,也不会添加引号)
${}存在sql注入的风险,但是有些场景下必须使用,比如排序后面会动态传入排序的列名
* parameterType和resultType
parameterType指定输入参数的java类型,parameterType只有一个,也就是说入参只有一个。
resultType指定输出结果的java类型(是单条记录的java类型)
* selectOne和selectList
selectOne查询单个对象
selectList查询集合对象
7、mybatis开发dao的方式--原始dao开发方式 <--返回目录
原始dao开发方式:开发dao接口和dao实现类,由ibatis遗留下来的风格
dao接口和实现类
public interface UserDao { public User findUserById(int id); public List<User> findUsersByName(String name); public void insertUser(User user); public void deleteUserById(int id); public void updateUserById(int id); } public class UserDaoImpl implements UserDao { private SqlSessionFactory sqlSessionFactory; public UserDaoImpl(SqlSessionFactory sqlSessionFactory) { this.sqlSessionFactory = sqlSessionFactory; } /** * 按id查询用户 */ @Override public User findUserById(int id) { // 创建SqlSession SqlSession sqlSession = sqlSessionFactory.openSession(); User user = sqlSession.selectOne("test.findUserById", id); // 关闭资源 sqlSession.close(); return user; } /** * 按username查询用户 */ @Override public List<User> findUsersByName(String name) { // 创建SqlSession SqlSession sqlSession = sqlSessionFactory.openSession(); List<User> userList = sqlSession.selectList("test.findUserByName", name); return userList; } /** * 添加用户 */ @Override public void insertUser(User user) { // 创建SqlSession SqlSession sqlSession = sqlSessionFactory.openSession(); sqlSession.insert("test.insertUser", user); } /** * 按id删除用户 */ @Override public void deleteUserById(int id) { SqlSession sqlSession = sqlSessionFactory.openSession(); sqlSession.update("test.deleteUserById", id); } /** * 按id修改用户 */ @Override public void updateUserById(int id) { SqlSession sqlSession = sqlSessionFactory.openSession(); sqlSession.update("test.updateUserById", id); } }
其他与上一项目一致。
测试类
package com.oy.test; import java.io.InputStream; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.junit.Before; import org.junit.Test; import com.oy.dao.UserDao; import com.oy.dao.UserDaoImpl; import com.oy.domain.User; public class Test1 { private SqlSessionFactory sqlSessionFactory; @Before public void setUp() throws Exception { // 读取配置文件 String resource = "SqlMapConfig.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); // 创建SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } @Test public void testFindUserById() throws Exception { // 创建UserDao UserDao dao = new UserDaoImpl(sqlSessionFactory);//注入sqlSessionFactory User user = dao.findUserById(1); System.out.println(user); } }
8、mybatis开发dao的方式--Mapper代理的开发方式 <--返回目录
Mapper代理使用的是jdk的代理策略。
Mapper代理的开发规范
1)mapper接口的全限定名要和mapper映射文件的namespace值一致。
2)mapper接口的方法名称要和mapper映射文件的statement的id一致。
3)mapper接口的方法参数类型要和mapper映射文件的statement的parameterType(输入参数类型)的值一致,
而且它的参数是一个。
4)mapper接口的方法返回值类型要和mapper映射文件的statement的resultType(返回结果类型)的值一致。
创建接口 com.oy.mapper.UserMapper
public interface UserMapper{ public User findUserById(int id) throws Exception; //int id为输入参数 User为输出结果 }
mapper映射文件:在config(源目录,也就是src)下创建mapper目录然后创建UserMapper.xml(这是mybatis的命名规范,当然,也不是必须是这个名称)
<mapper namespace="com.oy.mapper.UserMapper"> // namespace="com.oy.mapper.UserMapper"与接口全限定名称相同 <select id="findUserById" parameterType="int" resultType="com.oy.domain.User"> //id="findUserById"与接口方法名称相同 SELECT * FROM USER WHERE id = #{id} </select> </mapper>
SqlMapConfig.xml加载映射文件
<mappers> <mapper resource="mapper/UserMapper.xml" /> </mappers>
测试代码‘
private SqlSessionFactory sqlSessionFactory; @Before public void setUp() throws Exception { String resource = "SqlMapConfig.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } @Test public void testFindUserById() throws Exception { // 创建UserMapper对象 SqlSession sqlSession = sqlSessionFactory.openSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); User user = mapper.findUserById(1); System.out.println(user); sqlSession.close(); }
9、全局配置文件 <--返回目录
SqlMapConfig.xml的配置内容和顺序如下(顺序不能乱):
Properties(属性)
Settings(全局参数设置)
【typeAliases】(类型别名)SSM整合后依然会用到
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins(插件)
environments(环境信息集合)
environment(单个环境信息)
transactionManager(事物)
dataSource(数据源)
mappers(映射器)
property加载的顺序
1)先加载properties中property标签声明的属性 2)再加载properties标签引入的properties配置文件中的属性,如果同名,后面会覆盖前面的值 3)parameterType的值会和properties的属性值发生冲突,如果发现上面已经有同名的属性了,那后面会覆盖前面的值
mybatis支持的别名
别名 映射的类型 _byte byte _long long _short short _int int _integer int _double double _float float _boolean boolean string String java.lang.String byte Byte long Long short Short 【int Integer】 integer Integer double Double float Float boolean Boolean date Date decimal BigDecimal bigdecimal BigDecimal
自定义别名
<typeAliases> <typeAlias type="com.oy.domain.User" alias="user"/> <package:指定包名称来为该包下的po类声明别名,默认的别名就是类名(首字母大小写都可) <package name="com.oy.domain"/> </typeAliases>
在SqlMapConfig.xml文件中加载映射文件
<mapper resource="sqlmap/User.xml" /> 相对于类路径src <mapper url="file:///D:workspace_spingmvcmybatis_01configsqlmapUser.xml" /> 使用完全限定路径 <mapper class="cn.itcast.mapper.UserMapper"/>注意:此种方法要求mapper接口和mapper映射文件要名称相同,且放到同一个目录下; 【<package name="cn.itcast.mapper"/>注意:此种方法要求mapper接口和mapper映射文件要名称相同,且放到同一个目录下;】
<!-- 加载映射文件 --> <mappers> <mapper resource="User.xml" /> 相对类路径src <!-- <mapper resource="mapper/UserMapper.xml" /> --> <!-- 批量加载映射文件,推荐使用该种方式 --> <package name="com.oy.mapper" /> </mappers>
10、映射文件--输入参数 <--返回目录
parameterType="int等简单类型|pojo类型|包装pojo类型|Map类型"
parameterType="Map类型"
<!-- 传递hashmap综合查询用户信息 --> <select id="findUserByHashmap" parameterType="hashmap" resultType="user"> select * from user where id=#{id} or username like '%${username}%' //id和username是hashmap的key。 </select>
测试
Public void testFindUserByHashmap()throws Exception{ //获取session SqlSession session = sqlSessionFactory.openSession(); //获限mapper接口实例 UserMapper userMapper = session.getMapper(UserMapper.class); //构造查询条件Hashmap对象 HashMap<String, Object> map = new HashMap<String, Object>(); map.put("id", 1); map.put("username", "小明"); //传递Hashmap对象查询用户列表 List<User>list = userMapper.findUserByHashmap(map); //关闭session session.close(); }
异常测试:传递的map中的key和sql中解析的key不一致。测试结果没有报错,只是通过key获取值为空。
11、映射文件--输出结果 <--返回目录
resultType="int等简单类型|pojo类型"
resultType的使用要求:
- 使用resultType进行结果映射时,需要查询出的列名和映射的对象的属性名一致,才能映射成功。
- 如果查询的列名和对象的属性名全部不一致,那么映射的对象为空。
- 如果查询的列名和对象的属性名有一个一致,那么映射的对象不为空,但是只有映射正确那一个属性才有值。
- 如果查询的sql语句中的列名有别名,那么这个别名就代表列名,别名需要与映射的对象的属性名一致。所以,假如数据库中user表的列名为uid,但是领域对象User的属性为id,在查询时可以指定uid的别名为id
resultMap的使用要求:使用resultMap进行结果映射时,不需要查询的列名和映射的属性名必须一致。
但是需要声明一个resultMap,来对列名和属性名进行映射。
- 需求:对以下sql查询的结果集进行对象映射 Select id id_,username username_,sex sex_ from user where id = 1;
- 映射文件
<resultMap type="user" id="UserRstMap"> //注意type="user",mapper接口中findUserRstMap()方法返回值为User对象 <id column="id_" property="id"/> <result column="username_" property="username"/> <result column="sex_" property="sex"/> </resultMap> <select id="findUserRstMap" parameterType="int" resultMap="UserRstMap"> Select id id_,username username_,sex sex_ from user where id = #{id}; </select>
12、动态sql <--返回目录
在mybatis中,它提供了一些动态sql标签,可以让程序员更快得进行mybatis开发,这些动态sql可以提高sql的可重用性。
常用的动态sql标签:if标签、where标签、sql片段、foreach标签。
if标签/where标签
- 需求:综合查询时,查询条件由用户来输入,用户名称可以为空,需要满足这种情况下的sql编写。
- 映射文件
<select id="findUserList" parameterType="com.oy.po.UserQueryVO" resultType="user"> //注明:UserQueryVO是个包装pojo类, SELECT * FORM user //封装了private User user; <where> //<where>的作用:拼接条件,并去除多余的的AND <if test="user != null"> //判断当输入参数为空时,做不同处理 <if test="user.username != null and user.username != ''"> AND username LIKE '%${user.username}%' </if> <if test="user.sex != null and user.sex != ''"> AND sex=#{user.sex} </if> </if> </where> </select>
sql片段
- sql片段可以让代码有更高的可重用性
- sql片段需要先定义后使用
- 定义sql片段:
<!--定义sql片段 sql片段内,可以定义sql语句的任何部分 sql片段内,最好不要将where和select关键字声明在内 --> <sql id="whereClause"> <if test="user != null"> <if test="user.username != null and user.username != ''"> AND username LIKE '%${user.username}%' </if> <if test="user.sex != null and user.sex != ''"> AND sex=#{user.sex} </if> </if> </sql>
- 使用sql片段:
<select id="findUserList" parameterType="com.oy.po.UserQueryVO" resultType="user"> SELECT * FORM user <where> <!--引入sql片段--> <include refid="whereClause"/> </where> </select>
foreach标签
- 可以循环传入参数
- 需求:综合查询时,会根据用户ID集合进行查询 SELECT * FROM USER WHERE id IN (1,2,10)
- 修改包装pojo类
public class UserQueryVO{
private User user;
private List<Integer> idList;//商品id集合
}
- 映射文件
<select id="findUserList" parameterType="com.oy.po.UserQueryVO" resultType="user"> SELECT * FROM USER <where> <if test="idLIst != null"> AND id IN <foreach collection="idList" item="id" open="(" close=")" separator=","> #{id} </foreach> </if> </where> </select>
- 测试代码
List<Integet> idList = new ArrayList<Integer>(); idList.add(1); idList.add(2); idList.add(10); VO.setIdList(idList); List<User> list = mapper.findUsreList(VO);
- 最后发送的sql语句为:SELECT * FROM USER WHERE id IN (?,?,?)
13、mybatis与hibernate的区别及各自应用场景 <--返回目录
* Mybatis技术特点:
1)通过直接编写SQL语句,可以直接对SQL进行性能的优化;
2)学习门槛低,学习成本低。只要有SQL基础,就可以学习mybatis,而且很容易上手;
3)由于直接编写SQL语句,所以灵活多变,代码维护性更好。
4)不能支持数据库无关性,即数据库发生变更,要写多套代码进行支持,移植性不好。
* Hibernate技术特点:
1)标准的orm框架,程序员不需要编写SQL语句。
2)具有良好的数据库无关性,即数据库发生变化的话,代码无需再次编写。
3)学习门槛高,需要对数据关系模型有良好的基础,而且在设置ORM映射的时候,需要考虑好性能和对象模型的权衡。
4)程序员不能自主的去进行SQL性能优化。
* Mybatis应用场景:
需求多变的互联网项目,例如电商项目。
* Hibernate应用场景:
需求明确、业务固定的项目,例如OA项目、ERP项目等。
---