说明:本文由大量的源代码,及截图,建议读者,操作一遍。ide:IDEA。文末有笔记及视频分享
Mybatis
数据表的sql下载 密码: xjjw
1 Public static void main(String[] args) { 2 3 Connection connection = null; 4 5 PreparedStatement preparedStatement = null; 6 7 ResultSet resultSet = null; 8 9 10 11 try { 12 13 //加载数据库驱动 14 15 Class.forName("com.mysql.jdbc.Driver"); 16 17 18 19 //通过驱动管理类获取数据库链接 20 21 connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8", "root", "mysql"); 22 23 //定义sql语句 ?表示占位符 24 25 String sql = "select * from user where username = ?"; 26 27 //获取预处理statement 28 29 preparedStatement = connection.prepareStatement(sql); 30 31 //设置参数,第一个参数为sql语句中参数的序号(从1开始),第二个参数为设置的参数值 32 33 preparedStatement.setString(1, "王五"); 34 35 //向数据库发出sql执行查询,查询出结果集 36 37 resultSet = preparedStatement.executeQuery(); 38 39 //遍历查询结果集 40 41 while(resultSet.next()){ 42 43 System.out.println(resultSet.getString("id")+" "+resultSet.getString("username")); 44 45 } 46 47 } catch (Exception e) { 48 49 e.printStackTrace(); 50 51 }finally{ 52 53 //释放资源 54 55 if(resultSet!=null){ 56 57 try { 58 59 resultSet.close(); 60 61 } catch (SQLException e) { 62 63 // TODO Auto-generated catch block 64 65 e.printStackTrace(); 66 67 } 68 69 } 70 71 if(preparedStatement!=null){ 72 73 try { 74 75 preparedStatement.close(); 76 77 } catch (SQLException e) { 78 79 // TODO Auto-generated catch block 80 81 e.printStackTrace(); 82 83 } 84 85 } 86 87 if(connection!=null){ 88 89 try { 90 91 connection.close(); 92 93 } catch (SQLException e) { 94 95 // TODO Auto-generated catch block 96 97 e.printStackTrace(); 98 99 } 100 101 } 102 103 104 105 } 106 107 108 109 }
上面代码有如下几个问题:
jar包结构
过程中需要数据库的连接,junit的调试,注意要将jar包build path!
log4j.properties
1 # Global logging configuration 2 3 # 开发环境下,日志级别要设置成DEBUG或者ERROR 4 5 log4j.rootLogger=DEBUG, stdout 6 7 # Console output... 8 9 log4j.appender.stdout=org.apache.log4j.ConsoleAppender 10 11 log4j.appender.stdout.layout=org.apache.log4j.PatternLayout 12 13 log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
SqlMapConfig.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> <!-- 和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="" /> </dataSource> </environment> </environments> <!--加载映射文件--> <mappers> <mapper resource="sqlmap/User.xml"/> </mappers> </configuration>
User.xml
1 <?xml version="1.0" encoding="UTF-8" ?> 2 3 <!DOCTYPE mapper 4 5 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 6 7 "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 8 9 <!-- 10 11 命名空间,作用为,对sql进行分类化管理,理解sql隔离, 12 13 注意:使用mapper代理方法开发,namespace有特殊作用 14 15 --> 16 17 <mapper namespace="test"> 18 19 <!--在映射文件中配置sql--> 20 21 <!-- 22 23 findUserById 24 25 通过select执行数据库查询 26 27 id:标识映射文件的sql 28 29 将sql语句封装到mappedStatement对象中,所以将id称为Statement的id 30 31 #{}:表示一个占位符 32 33 parameterType:指定输入参数的类型 34 35 #{id}:其中的id表示接收输入的参数,参数的名称就是id,如果输入参数类型为简单类型,那么#{}中的参数可以任意,可以是value或其他 36 37 resultType:指定sql输出结果的所映射的Java对象类型,select指定的resultType表示将单条记录映射成的Java对象 38 39 --> 40 41 <select id="findUserById" parameterType="int" resultType="com.nuc.mybatis.po.User"> 42 43 select * from user where id=#{VALUE } 44 45 </select> 46 47 48 49 50 51 52 53 54 55 <!-- 56 57 findUserByName 58 59 ${}:表示拼接字符串,将接收到的sql不加任何修饰拼接在sql语句里 60 61 使用${}拼接sql,可能会引起sql注入,一般不建议使用 62 63 ${value}:接收参数的内容,如果传入的的是简单类型,${}中只能使用value 64 65 --> 66 67 <select id="findUserByName" parameterType="java.lang.String" resultType="com.nuc.mybatis.po.User"> 68 69 select * from user WHERE username LIKE ‘%${value}%‘ 70 71 </select> 72 73 74 75 76 77 78 79 80 81 <!-- 82 83 添加用户 84 85 parameterType:指定参数类型为pojo类型 86 87 #{}中指定pojo的属性名,接收到的pojo对象的属性值,mybatis通过OGNL获取对象的值 88 89 SELECT LAST_INSERT_ID():得到刚刚insert进去的记录的主键值,只适用于主键自增 90 91 非主键自的则需要使用uuid()来实现,表的id类型也得设置为tring(详见下面的注释) 92 93 keyProperty:将查询到的主键值设置到SparameterType指定的对象的哪个属性 94 95 order:SELECT LAST_INSERT_ID()执行顺序,相当于insert语句来说它的实现顺序 96 97 98 99 --> 100 101 <insert id="insertUser" parameterType="com.nuc.mybatis.po.User"> 102 103 <!--uuid()--> 104 105 <!-- 106 107 <selectKey keyProperty="id" order="AFTER" resultType="java.lang.String"> 108 109 SELECT uuid() 110 111 </selectKey> 112 113 insert into user (id,username,birthday,sex,address) value(#{id},#{username},#{birthday},#{sex},#{address}) 114 115 --> 116 117 <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer"> 118 119 SELECT LAST_INSERT_ID() 120 121 </selectKey> 122 123 insert into user (username,birthday,sex,address) value(#{username},#{birthday},#{sex},#{address}) 124 125 </insert> 126 127 128 129 130 131 <delete id="deleteUser" parameterType="java.lang.Integer"> 132 133 delete from user where id=#{id} 134 135 </delete> 136 137 138 139 <update id="updateUser" parameterType="com.nuc.mybatis.po.User"> 140 141 UPDATE user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address} where id=#{id} 142 143 </update> 144 145 </mapper>
User.java
1 package com.nuc.mybatis.po; 2 3 4 5 import java.util.Date; 6 7 8 9 public class User { 10 11 //用户po 12 13 //属性名和数据库字段名对应 14 15 private int id; 16 17 private String username;// 用户姓名 18 19 private String sex;// 性别 20 21 private Date birthday;// 生日 22 23 private String address;// 地址 24 25 26 27 public int getId() { 28 29 return id; 30 31 } 32 33 34 35 public void setId(int id) { 36 37 this.id = id; 38 39 } 40 41 42 43 public String getUsername() { 44 45 return username; 46 47 } 48 49 50 51 public void setUsername(String username) { 52 53 this.username = username; 54 55 } 56 57 58 59 public String getSex() { 60 61 return sex; 62 63 } 64 65 66 67 public void setSex(String sex) { 68 69 this.sex = sex; 70 71 } 72 73 74 75 public Date getBirthday() { 76 77 return birthday; 78 79 } 80 81 82 83 public void setBirthday(Date birthday) { 84 85 this.birthday = birthday; 86 87 } 88 89 90 91 public String getAddress() { 92 93 return address; 94 95 } 96 97 98 99 public void setAddress(String address) { 100 101 this.address = address; 102 103 } 104 105 }
MybatisFirst.java
1 package com.nuc.mybatis.first; 2 3 4 5 import com.nuc.mybatis.po.User; 6 7 import org.apache.ibatis.io.Resources; 8 9 import org.apache.ibatis.session.SqlSession; 10 11 import org.apache.ibatis.session.SqlSessionFactory; 12 13 import org.apache.ibatis.session.SqlSessionFactoryBuilder; 14 15 import org.junit.Test; 16 17 18 19 import java.io.IOException; 20 21 import java.io.InputStream; 22 23 import java.util.Date; 24 25 import java.util.List; 26 27 28 29 public class MybatisFirst { 30 31 //根据id查询用户信息,得到一条记录 32 33 @Test 34 35 public void findUserByIdTest() throws IOException { 36 37 //mybatis配置文件 38 39 String resource = "SqlMapConfig.xml"; 40 41 InputStream inputStream = Resources.getResourceAsStream(resource); 42 43 //创建会话工厂 44 45 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); 46 47 //通过工厂得到SqlSession 48 49 SqlSession sqlSession = sqlSessionFactory.openSession(); 50 51 //通过SqlSession操作数据库 52 53 //第一个参数:映射文件中的statement的id,等于namespace+"."+statement的id 54 55 //第二个参数:指定和映射文件中所匹配的所有parameterType的类型 56 57 //sqlSession.selectOne()的结果是映射文件中所匹配的resultType类型的对象 58 59 User user = sqlSession.selectOne("test.findUserById",1); 60 61 System.out.println(user); 62 63 //释放资源 64 65 sqlSession.close(); 66 67 } 68 69 //根据用户名称查询用户列表 70 71 @Test 72 73 public void findUserByName() throws IOException { 74 75 //mybatis配置文件 76 77 String resource = "SqlMapConfig.xml"; 78 79 InputStream inputStream = Resources.getResourceAsStream(resource); 80 81 //创建会话工厂 82 83 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); 84 85 //通过工厂得到SqlSession 86 87 SqlSession sqlSession = sqlSessionFactory.openSession(); 88 89 List<User> list= sqlSession.selectList("test.findUserByName","小明"); 90 91 System.out.println(list); 92 93 sqlSession.close(); 94 95 } 96 97 /* 98 99 小结: 100 101 selectOne和selectList: 102 103 104 105 selectOne表示查询出一条记录进行映射。如果使用selectOne可以实现使用selectList也可以实现(list中只有一个对象)。 106 107 selectList表示查询出一个列表(多条记录)进行映射。如果使用selectList查询多条记录,不能使用selectOne。 108 109 如果使用selectOne报错: 110 111 org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned by selectOne(), but found: 4 112 113 114 115 */ 116 117 @Test 118 119 public void insertUserTest() throws IOException { 120 121 //mybatis配置文件 122 123 String resource = "SqlMapConfig.xml"; 124 125 InputStream inputStream = Resources.getResourceAsStream(resource); 126 127 //创建会话工厂 128 129 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); 130 131 //通过工厂得到SqlSession 132 133 SqlSession sqlSession = sqlSessionFactory.openSession(); 134 135 User user = new User(); 136 137 user.setUsername("宋江涛"); 138 139 user.setBirthday(new Date()); 140 141 user.setSex("男"); 142 143 user.setAddress("山西"); 144 145 //list中的user和映射文件User.xml中的resultType的类型一直 146 147 sqlSession.insert("test.insertUser",user); 148 149 //提交事务 150 151 sqlSession.commit(); 152 153 //获取主键 154 155 System.out.println(user.getId()); 156 157 sqlSession.close(); 158 159 } 160 161 //删除用户 162 163 @Test 164 165 public void deleteUserTest() throws IOException { 166 167 //mybatis配置文件 168 169 String resource = "SqlMapConfig.xml"; 170 171 InputStream inputStream = Resources.getResourceAsStream(resource); 172 173 //创建会话工厂 174 175 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); 176 177 //通过工厂得到SqlSession 178 179 SqlSession sqlSession = sqlSessionFactory.openSession(); 180 181 182 183 //list中的user和映射文件User.xml中的resultType的类型一直 184 185 sqlSession.delete("test.deleteUser",30); 186 187 //提交事务 188 189 sqlSession.commit(); 190 191 sqlSession.close(); 192 193 } 194 195 196 197 //更新用户 198 199 @Test 200 201 public void updateUserTest() throws IOException { 202 203 //mybatis配置文件 204 205 String resource = "SqlMapConfig.xml"; 206 207 InputStream inputStream = Resources.getResourceAsStream(resource); 208 209 //创建会话工厂 210 211 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); 212 213 //通过工厂得到SqlSession 214 215 SqlSession sqlSession = sqlSessionFactory.openSession(); 216 217 User user = new User(); 218 219 user.setId(27); 220 221 user.setUsername("宋江涛new2"); 222 223 user.setBirthday(new Date()); 224 225 user.setSex("男"); 226 227 user.setAddress("山西太原new"); 228 229 //list中的user和映射文件User.xml中的resultType的类型一直 230 231 sqlSession.update("test.updateUser",user); 232 233 //提交事务 234 235 sqlSession.commit(); 236 237 sqlSession.close(); 238 239 } 240 241 }
数据库的设计图
部分测试结果
jdbc的测试程序,前面已经沾过。
重点内容在代码的注释中均已说明
mybatis和hibernate本质区别和应用场景
hibernate:
应用场景:
mybatis:
专注是sql本身,需要程序员自己编写sql语句,sql修改、优化比较方便。mybatis是一个不完全 的ORM框架,虽然程序员自己写sql,mybatis 也可以实现映射(输入映射、输出映射)。
应用场景:
4、Mybatis开发dao的方法
具体目录结构:
结构中的相关mapper请先忽略
UserDao.java
1 package com.nuc.mybatis.dao; 2 3 4 5 import com.nuc.mybatis.po.User; 6 7 8 9 public interface UserDao { 10 11 //dao原始开发 12 13 //根据id查询用户信息 14 15 public User findUserById(int id) throws Exception; 16 17 //添加用户 18 19 public void insertUser(User user) throws Exception; 20 21 //删除用户 22 23 public void deleteUser(int id) throws Exception; 24 25 }
UserDaoImpl.java
1 package com.nuc.mybatis.dao; 2 3 4 5 import com.nuc.mybatis.po.User; 6 7 import org.apache.ibatis.session.SqlSessionFactory; 8 9 import org.apache.ibatis.session.SqlSession; 10 11 12 13 public class UserDaoImpl implements UserDao { 14 15 //原生态的dao 16 17 //需要向dao实现类里注入SqlSessionFactory 18 19 //通过构造方法 20 21 private SqlSessionFactory sqlSessionFactory; 22 23 24 25 public UserDaoImpl(SqlSessionFactory sqlSessionFactory){ 26 27 this.sqlSessionFactory=sqlSessionFactory; 28 29 } 30 31 @Override 32 33 public User findUserById(int id) throws Exception { 34 35 SqlSession sqlSession = sqlSessionFactory.openSession(); 36 37 User user = sqlSession.selectOne("test.findUserById",id); 38 39 sqlSession.close(); 40 41 return user; 42 43 } 44 45 46 47 @Override 48 49 public void insertUser(User user) throws Exception { 50 51 SqlSession sqlSession = sqlSessionFactory.openSession(); 52 53 sqlSession.insert("test.insertUser",user); 54 55 sqlSession.commit(); 56 57 sqlSession.close(); 58 59 60 61 } 62 63 64 65 @Override 66 67 public void deleteUser(int id) throws Exception { 68 69 SqlSession sqlSession = sqlSessionFactory.openSession(); 70 71 sqlSession.insert("test.deleteUser",id); 72 73 sqlSession.commit(); 74 75 sqlSession.close(); 76 77 } 78 79 }
UserDaoImplTest.java
1 package com.nuc.mybatis.test; 2 3 4 5 import com.nuc.mybatis.mapper.UserMapper; 6 7 import com.nuc.mybatis.po.User; 8 9 import org.apache.ibatis.io.Resources; 10 11 import org.apache.ibatis.session.SqlSession; 12 13 import org.apache.ibatis.session.SqlSessionFactory; 14 15 import org.apache.ibatis.session.SqlSessionFactoryBuilder; 16 17 import org.junit.Before; 18 19 import org.junit.Test; 20 21 22 23 import java.io.InputStream; 24 25 import java.util.List; 26 27 28 29 public class UserMapperTest { 30 31 //原始dao的测试 32 33 private SqlSessionFactory sqlSessionFactory; 34 35 @Before 36 37 public void setUp() throws Exception{ 38 39 String resource = "SqlMapConfig.xml"; 40 41 InputStream inputStream = Resources.getResourceAsStream(resource); 42 43 //创建会话工厂 44 45 sqlSessionFactory = new 46 47 SqlSessionFactoryBuilder().build(inputStream); 48 49 } 50 51 @Test 52 53 public void testFindUserById() throws Exception{ 54 55 SqlSession sqlSession = sqlSessionFactory.openSession(); 56 57 //创建UserMapper的对象,mybatis自动调用 58 59 UserMapper userMapper = sqlSession.getMapper(UserMapper.class); 60 61 User user = userMapper.findUserById(1); 62 63 System.out.println(user); 64 65 66 67 } 68 69 @Test 70 71 public void testFindUserByName() throws Exception{ 72 73 SqlSession sqlSession = sqlSessionFactory.openSession(); 74 75 //创建UserMapper的对象,mybatis自动调用 76 77 UserMapper userMapper = sqlSession.getMapper(UserMapper.class); 78 79 List<User> list= userMapper.findUserByName("宋江涛"); 80 81 System.out.println(list); 82 83 } 84 85 //其他的测试,可以照猫画虎 86 87 }
测试结果:
根据上面的结构图创建相应文件,源码如下:
UserMapper.java
1 package com.nuc.mybatis.mapper; 2 3 4 5 import com.nuc.mybatis.po.User; 6 7 8 9 import java.util.List; 10 11 12 13 public interface UserMapper { 14 15 //mapper代理开发和dao开发对比 16 17 // mapper接口,相当于dao接口,mybatis可以自动生成mapper接口实现类的代理对象 18 19 //根据id查询用户信息 20 21 public User findUserById(int id) throws Exception; 22 23 //根据用户名查询用户列表 24 25 public List<User>findUserByName(String name) throws Exception; 26 27 //添加用户 28 29 public void insertUser(User user) throws Exception; 30 31 //删除用户 32 33 public void deleteUser(int id) throws Exception; 34 35 }
UserMapper.xml
1 <?xml version="1.0" encoding="UTF-8" ?> 2 3 <!DOCTYPE mapper 4 5 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 6 7 "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 8 9 <mapper namespace="com.nuc.mybatis.mapper.UserMapper"> 10 11 <select id="findUserById" parameterType="int" resultType="com.nuc.mybatis.po.User"> 12 13 select * from user where id=#{VALUE } 14 15 </select> 16 17 <select id="findUserByName" parameterType="java.lang.String" resultType="com.nuc.mybatis.po.User"> 18 19 select * from user WHERE username LIKE ‘%${value}%‘ 20 21 </select> 22 23 24 25 <insert id="insertUser" parameterType="com.nuc.mybatis.po.User"> 26 27 28 29 <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer"> 30 31 SELECT LAST_INSERT_ID() 32 33 </selectKey> 34 35 insert into user (username,birthday,sex,address) value(#{username},#{birthday},#{sex},#{address}) 36 37 </insert> 38 39 40 41 42 43 <delete id="deleteUser" parameterType="java.lang.Integer"> 44 45 delete from user where id=#{id} 46 47 </delete> 48 49 50 51 <update id="updateUser" parameterType="com.nuc.mybatis.po.User"> 52 53 UPDATE user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address} where id=#{id} 54 55 </update> 56 57 </mapper>
在测试之前需要在SqlMapConfig.xml中加载mapper.xml这个映射文件
UserMapperTest.java
1 package com.nuc.mybatis.test; 2 3 4 5 import com.nuc.mybatis.mapper.UserMapper; 6 7 import com.nuc.mybatis.po.User; 8 9 import org.apache.ibatis.io.Resources; 10 11 import org.apache.ibatis.session.SqlSession; 12 13 import org.apache.ibatis.session.SqlSessionFactory; 14 15 import org.apache.ibatis.session.SqlSessionFactoryBuilder; 16 17 import org.junit.Before; 18 19 import org.junit.Test; 20 21 22 23 import java.io.InputStream; 24 25 import java.util.List; 26 27 28 29 public class UserMapperTest { 30 31 //原始mapper的测试 32 33 private SqlSessionFactory sqlSessionFactory; 34 35 @Before 36 37 public void setUp() throws Exception{ 38 39 String resource = "SqlMapConfig.xml"; 40 41 InputStream inputStream = Resources.getResourceAsStream(resource); 42 43 //创建会话工厂 44 45 sqlSessionFactory = new 46 47 SqlSessionFactoryBuilder().build(inputStream); 48 49 } 50 51 @Test 52 53 public void testFindUserById() throws Exception{ 54 55 SqlSession sqlSession = sqlSessionFactory.openSession(); 56 57 //创建UserMapper的对象,mybatis自动调用 58 59 UserMapper userMapper = sqlSession.getMapper(UserMapper.class); 60 61 User user = userMapper.findUserById(1); 62 63 System.out.println(user); 64 65 66 67 } 68 69 @Test 70 71 public void testFindUserByName() throws Exception{ 72 73 //返回列表测试 74 75 SqlSession sqlSession = sqlSessionFactory.openSession(); 76 77 //创建UserMapper的对象,mybatis自动调用 78 79 UserMapper userMapper = sqlSession.getMapper(UserMapper.class); 80 81 List<User> list= userMapper.findUserByName("宋江涛"); 82 83 System.out.println(list); 84 85 } 86 87 }
部分测试结果:
总结:
1 User user = sqlSession.selectOne("test.findUserById", id); 2 sqlSession.insert("test.insertUser", user); 3 。。。。
建议:
这样在其他地方就可以使用,例如:
UserCustom.java
1 package com.nuc.mybatis.po; 2 3 4 5 public class UserCustom extends User { 6 7 //可扩展用户信息 8 9 }
UserQueryVo.java
1 package com.nuc.mybatis.po; 2 3 4 5 public class UserQueryVo { 6 7 //这里包装所需的查询条件 8 9 10 11 //用户查询条件 12 13 private UserCustom userCustom; 14 15 16 17 public UserCustom getUserCustom() { 18 19 return userCustom; 20 21 } 22 23 24 25 public void setUserCustom(UserCustom userCustom) { 26 27 this.userCustom = userCustom; 28 29 } 30 31 32 33 //可包装其他的查询条件,订单,商品。。。 34 35 }
UserMapper.xml中配置新的查询
UserMapperTest.java中新增测试
测试结果
在上面的输入中,属于每一列都成功映射
当我们修改查询语句为:
其中id,起了别名叫做id_
测试结果:
很明显,由于查询条件,生日和地址为空,由于id的映射失败,导致查询id失败,只有sex一列映射成功,故查询成功(1代表男,2代表女)
如法炮制,对mapper.xml编辑和mapper.java编辑
测试代码(复制修改)
测试结果
总结:查询出来的结果集只有一行且一列,可以使用简单类型进行输出映射。
1 <!--用户综合查询总数--> 2 3 <select id="findUserCount" parameterType="com.nuc.mybatis.po.UserQueryVo" 4 5 resultType="int"> 6 7 select count(*) from user 8 9 <!--where可以自动去掉第一个and--> 10 11 <where> 12 13 <if test="userCustom!=null"> 14 15 <if test="userCustom.sex!=null and userCustom.sex!=‘‘"> 16 17 and user.sex=#{userCustom.sex} 18 19 </if> 20 21 <if test="userCustom.username!=null and userCustom.username!=‘‘"> 22 23 and user.username=#{userCustom.username} 24 25 </if> 26 27 </if> 28 29 </where> 30 31 </select>
1 <!--sql片段 2 3 经验:基于单表来定义sql片段,这样,sql片段的可重用度就高 4 5 在sql片段中不要用where,因为你很有可能查询条件不止一个 6 7 --> 8 9 <sql id="Query_user"> 10 11 <if test="userCustom!=null"> 12 13 <if test="userCustom.sex!=null and userCustom.sex!=‘‘"> 14 15 and user.sex=#{userCustom.sex} 16 17 </if> 18 19 <if test="userCustom.username!=null and userCustom.username!=‘‘"> 20 21 and user.username=#{userCustom.username} 22 23 </if> 24 25 </if> 26 27 </sql>
将之前的sql语句修改如下:
<!--用户综合查询总数--> <select id="findUserCount" parameterType="com.nuc.mybatis.po.UserQueryVo" resultType="int"> select count(*) from user <!--where可以自动去掉第一个and--> <where> <!--引用sql的id,如果refid引用的sql的id不在本mapper中,则需要家其他mapper的namespace--> <include refid="Query_user"/> </where> </select>
1 <sql id="Query_user"> 2 3 <if test="userCustom!=null"> 4 5 <if test="userCustom.sex!=null and userCustom.sex!=‘‘"> 6 7 and user.sex=#{userCustom.sex} 8 9 </if> 10 11 <if test="userCustom.username!=null and userCustom.username!=‘‘"> 12 13 and user.username=#{userCustom.username} 14 15 </if> 16 17 </if> 18 19 <if test="ids!=null"> 20 21 <!-- 22 23 collection:指定输入对象集合中的属性 24 25 item:每次遍历生成的对象名 26 27 open:开始遍历拼接的串 28 29 close:结束时拼接的串 30 31 separator:每个对象的中间拼接的串 32 33 我们要实现 and(id=1 OR id=10 OR id=16) 34 35 --> 36 37 <foreach collection="ids" item="user_id" open="and(" close=")" separator="OR"> 38 39 <!--每次遍历拼接的串--> 40 41 id=#{user_id} 42 43 </foreach> 44 45 </if> 46 47 </sql>
添加属性,及其get set 方法
修改测试类
1 // 用户综合查询总数 2 3 @Test 4 5 public void testFindUser() throws Exception{ 6 7 SqlSession sqlSession = sqlSessionFactory.openSession(); 8 9 //创建UserMapper的对象,mybatisCount自动调用 10 11 UserMapper userMapper = sqlSession.getMapper(UserMapper.class); 12 13 //创建包对象,设置查询条件 14 15 UserQueryVo userQueryVo = new UserQueryVo(); 16 17 UserCustom userCustom = new UserCustom(); 18 19 // 由于这里使用动态sql所以不设置某个值,就不会拼接在sql语句中 20 21 // userCustom.setSex("1"); 22 23 userCustom.setUsername("小明"); 24 25 List<Integer> list = new ArrayList<>(); 26 27 list.add(1); 28 29 list.add(10); 30 31 list.add(16); 32 33 userQueryVo.setIds(list); 34 35 userQueryVo.setUserCustom(userCustom); 36 37 int count= userMapper.findUserCount(userQueryVo); 38 39 System.out.println(count); 40 41 }
测试结果
sql语句成功修改!
下来拿之前的数据库的表为例,具体字段不作说明
根据上面的步骤。
第一步:每张表记录的数据内容
第二步:每张表重要的字段设置
第三步:数据库级别表与表之间的关系
先分析数据库级别之间有关系的表之间的业务关系:
第四步:表与表之间的业务关系
SELECT
orders.*,
USER.username,
USER.sex,
USER.address
FROM
orders,
USER
WHERE orders.user_id = user.id
Orders.java
1 package com.nuc.mybatis.po; 2 3 4 5 import java.util.Date; 6 7 import java.util.List; 8 9 10 11 public class Orders { 12 13 private Integer id; 14 15 16 17 private Integer userId; 18 19 20 21 private String number; 22 23 24 25 private Date createtime; 26 27 28 29 private String note; 30 31 32 33 //用户信息 34 35 private User user; 36 37 38 39 //订单明细 40 41 private List<Orderdetail> orderdetails; 42 43 44 45 public Integer getId() { 46 47 return id; 48 49 } 50 51 52 53 public void setId(Integer id) { 54 55 this.id = id; 56 57 } 58 59 60 61 public Integer getUserId() { 62 63 return userId; 64 65 } 66 67 68 69 public void setUserId(Integer userId) { 70 71 this.userId = userId; 72 73 } 74 75 76 77 public String getNumber() { 78 79 return number; 80 81 } 82 83 84 85 public void setNumber(String number) { 86 87 this.number = number == null ? null : number.trim(); 88 89 } 90 91 92 93 public Date getCreatetime() { 94 95 return createtime; 96 97 } 98 99 100 101 public void setCreatetime(Date createtime) { 102 103 this.createtime = createtime; 104 105 } 106 107 108 109 public String getNote() { 110 111 return note; 112 113 } 114 115 116 117 public void setNote(String note) { 118 119 this.note = note == null ? null : note.trim(); 120 121 } 122 123 124 125 public User getUser() { 126 127 return user; 128 129 } 130 131 132 133 public void setUser(User user) { 134 135 this.user = user; 136 137 } 138 139 140 141 public List<Orderdetail> getOrderdetails() { 142 143 return orderdetails; 144 145 } 146 147 148 149 public void setOrderdetails(List<Orderdetail> orderdetails) { 150 151 this.orderdetails = orderdetails; 152 153 } 154 155 }
OrdersCustom .java
1 package com.nuc.mybatis.po; 2 3 4 5 public class OrdersCustom extends Orders { 6 7 private String username; 8 9 private String sex; 10 11 private String address; 12 13 public String getUsername() { 14 15 return username; 16 17 } 18 19 public void setUsername(String username) { 20 21 this.username = username; 22 23 } 24 25 public String getSex() { 26 27 return sex; 28 29 } 30 31 public void setSex(String sex) { 32 33 this.sex = sex; 34 35 } 36 37 public String getAddress() { 38 39 return address; 40 41 } 42 43 public void setAddress(String address) { 44 45 this.address = address; 46 47 } 48 49 50 51 }
OrdersMapperCustom.java
1 package com.nuc.mybatis.mapper; 2 3 4 5 import java.util.List; 6 7 8 9 public interface OrdersMapperCustom { 10 11 public List<OrdersMapperCustom> findOrdersUser()throws Exception; 12 13 }
OrdersMapperCustom .xml
1 <?xml version="1.0" encoding="UTF-8" ?> 2 3 <!DOCTYPE mapper 4 5 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 6 7 "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 8 9 <mapper namespace="com.nuc.mybatis.mapper.OrdersMapperCustom"> 10 11 <!--resultType:返回值的映射的pojo对象--> 12 13 <select id="findOrdersUser" resultType="com.nuc.mybatis.po.OrdersCustom"> 14 15 SELECT 16 17 orders.*, 18 19 user.username, 20 21 user.sex, 22 23 user.address 24 25 FROM 26 27 orders, 28 29 user 30 31 WHERE orders.user_id = user.id 32 33 </select> 34 35 36 37 </mapper>
OrdersMapperTest.java
1 package com.nuc.mybatis.test; 2 3 4 5 import com.nuc.mybatis.mapper.OrdersMapperCustom; 6 7 import org.apache.ibatis.io.Resources; 8 9 import org.apache.ibatis.session.SqlSession; 10 11 import org.apache.ibatis.session.SqlSessionFactory; 12 13 import org.apache.ibatis.session.SqlSessionFactoryBuilder; 14 15 import org.junit.Before; 16 17 import org.junit.Test; 18 19 20 21 import java.io.InputStream; 22 23 import java.util.List; 24 25 26 27 public class OrdersMapperTest { 28 29 private SqlSessionFactory sqlSessionFactory; 30 31 @Before 32 33 public void setUp() throws Exception{ 34 35 String resource = "SqlMapConfig.xml"; 36 37 InputStream inputStream = Resources.getResourceAsStream(resource); 38 39 //创建会话工厂 40 41 sqlSessionFactory = new 42 43 SqlSessionFactoryBuilder().build(inputStream); 44 45 } 46 47 @Test 48 49 public void testFindOrdersUser() throws Exception { 50 51 SqlSession sqlSession = sqlSessionFactory.openSession(); 52 53 // 创建代理对象 54 55 OrdersMapperCustom ordersMapperCustom = sqlSession 56 57 .getMapper(OrdersMapperCustom.class); 58 59 // 调用maper的方法 60 61 List<OrdersMapperCustom> list = ordersMapperCustom.findOrdersUser(); 62 63 System.out.println(list); 64 65 sqlSession.close(); 66 67 } 68 69 }
测试结果
第三步:
1 <resultMap type="com.nuc.mybatis.po.Orders" id="OrdersUserResultMap"> 2 3 <!-- 配置映射的订单信息 --> 4 5 <!-- id:指定查询列中的唯 一标识,订单信息的中的唯 一标识,如果有多个列组成唯一标识,配置多个id 6 7 column:订单信息的唯 一标识 列 8 9 property:订单信息的唯 一标识 列所映射到Orders中哪个属性 10 11 --> 12 13 <id column="id" property="id"/> 14 15 <result column="user_id" property="userId"/> 16 17 <result column="number" property="number"/> 18 19 <result column="createtime" property="createtime"/> 20 21 <result column="note" property="note"/> 22 23 <!-- 配置映射的关联的用户信息 --> 24 25 <!-- association:用于映射关联查询单个对象的信息 26 27 property:要将关联查询的用户信息映射到Orders中哪个属性 28 29 --> 30 31 <association property="user" javaType="com.nuc.mybatis.po.User"> 32 33 <!-- id:关联查询用户的唯 一标识 34 35 column:指定唯 一标识用户信息的列 36 37 javaType:映射到user的哪个属性 38 39 --> 40 41 <id column="user_id" property="id"/> 42 43 <result column="username" property="username"/> 44 45 <result column="sex" property="sex"/> 46 47 <result column="address" property="address"/> 48 49 </association> 50 51 </resultMap>
1 <!-- 查询订单关联查询用户信息,使用resultmap --> 2 3 <select id="findOrdersUserResultMap" resultMap="OrdersUserResultMap"> 4 5 SELECT 6 7 orders.*, 8 9 USER.username, 10 11 USER.sex, 12 13 USER.address 14 15 FROM 16 17 orders, 18 19 USER 20 21 WHERE orders.user_id = user.id 22 23 </select>
第四步
1 //查询订单关联查询用户使用resultMap 2 3 public List<Orders> findOrdersUserResultMap()throws Exception;
测试
1 @Test 2 3 public void testFindOrdersResultMap() throws Exception { 4 5 SqlSession sqlSession = sqlSessionFactory.openSession(); 6 7 // 创建代理对象 8 9 OrdersMapperCustom ordersMapperCustom = sqlSession 10 11 .getMapper(OrdersMapperCustom.class); 12 13 // 调用maper的方法 14 15 List<Orders> list = ordersMapperCustom.findOrdersUserResultMap(); 16 17 System.out.println(list); 18 19 sqlSession.close(); 20 21 }
要求:对orders映射不能出现重复记录。
解决思路:
添加属性在之前已经实现,且注释。
只需要配置xml文件和接口,写一个测试类即可
1 <!-- 订单及订单明细的resultMap 2 3 使用extends继承,不用在中配置订单信息和用户信息的映射 4 5 --> 6 7 <resultMap type="com.nuc.mybatis.po.Orders" id="OrdersAndOrderDetailResultMap" extends="OrdersUserResultMap"> 8 9 <!-- 订单信息 --> 10 11 <!-- 用户信息 --> 12 13 <!-- 使用extends继承,不用在中配置订单信息和用户信息的映射 --> 14 15 16 17 <!-- 订单明细信息 18 19 一个订单关联查询出了多条明细,要使用collection进行映射 20 21 collection:对关联查询到多条记录映射到集合对象中 22 23 property:将关联查询到多条记录映射到com.nuc.mybatis.po.Orders哪个属性 24 25 ofType:指定映射到list集合属性中pojo的类型 26 27 --> 28 29 <collection property="orderdetails" ofType="com.nuc.mybatis.po.Orderdetail"> 30 31 <!-- id:订单明细唯 一标识 32 33 property:要将订单明细的唯 一标识 映射到com.nuc.mybatis.po.Orderdetail的哪个属性 34 35 --> 36 37 <id column="orderdetail_id" property="id"/> 38 39 <result column="items_id" property="itemsId"/> 40 41 <result column="items_num" property="itemsNum"/> 42 43 <result column="orders_id" property="ordersId"/> 44 45 </collection> 46 47 </resultMap> 48 49 <!-- 查询订单关联查询用户及订单明细,使用resultmap --> 50 51 <select id="findOrdersAndOrderDetailResultMap" resultMap="OrdersAndOrderDetailResultMap"> 52 53 SELECT 54 55 orders.*, 56 57 USER.username, 58 59 USER.sex, 60 61 USER.address, 62 63 orderdetail.id orderdetail_id, 64 65 orderdetail.items_id, 66 67 orderdetail.items_num, 68 69 orderdetail.orders_id 70 71 FROM 72 73 orders, 74 75 USER, 76 77 orderdetail 78 79 WHERE orders.user_id = user.id AND orderdetail.orders_id=orders.id 80 81 </select>
1 //查询订单(关联用户)及订单明细 2 3 public List<Orders> findOrdersAndOrderDetailResultMap() throws Exception; 4 5 @Test 6 7 public void testfindOrdersAndOrderDetailResultMap() throws Exception { 8 9 SqlSession sqlSession = sqlSessionFactory.openSession(); 10 11 // 创建代理对象 12 13 OrdersMapperCustom ordersMapperCustom = sqlSession 14 15 .getMapper(OrdersMapperCustom.class); 16 17 // 调用maper的方法 18 19 List<Orders> list = ordersMapperCustom.findOrdersAndOrderDetailResultMap(); 20 21 System.out.println(list); 22 23 sqlSession.close(); 24 25 }
orders.*,
USER.username,
USER.sex,
USER.address,
orderdetail.id orderdetail_id,
orderdetail.items_id,
orderdetail.items_num,
orderdetail.orders_id,
items.name items_name,
items.detail items_detail,
items.price items_price
FROM
orders,
USER,
orderdetail,
items
WHERE orders.user_id = user.id AND orderdetail.orders_id=orders.id AND orderdetail.items_id = items.id
1 <!-- 查询用户及购买的商品信息,使用resultmap --> 2 3 <select id="findUserAndItemsResultMap" resultMap="UserAndItemsResultMap"> 4 5 SELECT 6 7 orders.*, 8 9 USER.username, 10 11 USER.sex, 12 13 USER.address, 14 15 orderdetail.id orderdetail_id, 16 17 orderdetail.items_id, 18 19 orderdetail.items_num, 20 21 orderdetail.orders_id, 22 23 items.name items_name, 24 25 items.detail items_detail, 26 27 items.price items_price 28 29 FROM 30 31 orders, 32 33 USER, 34 35 orderdetail, 36 37 items 38 39 WHERE orders.user_id = user.id AND orderdetail.orders_id=orders.id AND orderdetail.items_id = items.id 40 41 </select>
1 <!-- 查询用户及购买的商品 --> 2 3 <resultMap type="com.nuc.mybatis.po.User" id="UserAndItemsResultMap"> 4 5 <!-- 用户信息 --> 6 7 <id column="user_id" property="id"/> 8 9 <result column="username" property="username"/> 10 11 <result column="sex" property="sex"/> 12 13 <result column="address" property="address"/> 14 15 16 17 <!-- 订单信息 18 19 一个用户对应多个订单,使用collection映射 20 21 --> 22 23 <collection property="ordersList" ofType="com.nuc.mybatis.po.Orders"> 24 25 <id column="id" property="id"/> 26 27 <result column="user_id" property="userId"/> 28 29 <result column="number" property="number"/> 30 31 <result column="createtime" property="createtime"/> 32 33 <result column="note" property="note"/> 34 35 36 37 <!-- 订单明细 38 39 一个订单包括 多个明细 40 41 --> 42 43 <collection property="orderdetails" ofType="com.nuc.mybatis.po.Orderdetail"> 44 45 <id column="orderdetail_id" property="id"/> 46 47 <result column="items_id" property="itemsId"/> 48 49 <result column="items_num" property="itemsNum"/> 50 51 <result column="orders_id" property="ordersId"/> 52 53 <!-- 商品信息 54 55 一个订单明细对应一个商品 56 57 --> 58 59 <association property="items" javaType="com.nuc.mybatis.po.Items"> 60 61 <id column="items_id" property="id"/> 62 63 <result column="items_name" property="name"/> 64 65 <result column="items_detail" property="detail"/> 66 67 <result column="items_price" property="price"/> 68 69 </association> 70 71 </collection> 72 73 </collection> 74 75 </resultMap>
mapper.java
1 //查询用户购买商品信息 2 3 public List<User> findUserAndItemsResultMap()throws Exception;
多对多查询总结
1 //mybatis默认支持一级缓存,不需要在配置文件去配置。 2 3 @Test 4 5 public void testCache1() throws Exception{ 6 7 SqlSession sqlSession = sqlSessionFactory.openSession();//创建代理对象 8 9 UserMapper userMapper = sqlSession.getMapper(UserMapper.class); 10 11 //下边查询使用一个SqlSession 12 13 //第一次发起请求,查询id为1的用户 14 15 User user1 = userMapper.findUserById(1); 16 17 System.out.println(user1); 18 19 // 如果sqlSession去执行commit操作(执行插入、更新、删除),清空SqlSession中的一级缓存,这样做的目的为了让缓存中存储的是最新的信息,避免脏读。 20 21 //更新user1的信息 22 23 user1.setUsername("测试用户22"); 24 25 userMapper.updateUser(user1); 26 27 //执行commit操作去清空缓存 28 29 sqlSession.commit(); 30 31 //第二次发起请求,查询id为1的用户 32 33 User user2 = userMapper.findUserById(1); 34 35 System.out.println(user2); 36 37 sqlSession.close(); 38 39 40 41 }
一个service方法中包括 很多mapper方法调用。
1 service{ 2 3 //开始执行时,开启事务,创建SqlSession对象 4 5 //第一次调用mapper的方法findUserById(1) 6 7 8 9 //第二次调用mapper的方法findUserById(1),从一级缓存中取数据 10 11 //方法结束,sqlSession关闭 12 13 }
如果是执行两个service调用查询相同 的用户信息,不走一级缓存,因为session方法结束,sqlSession就关闭,一级缓存就清空。
1 // 二级缓存测试 2 3 @Test 4 5 public void testCache2() throws Exception { 6 7 SqlSession sqlSession1 = sqlSessionFactory.openSession(); 8 9 SqlSession sqlSession2 = sqlSessionFactory.openSession(); 10 11 SqlSession sqlSession3 = sqlSessionFactory.openSession(); 12 13 // 创建代理对象 14 15 UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class); 16 17 // 第一次发起请求,查询id为1的用户 18 19 User user1 = userMapper1.findUserById(1); 20 21 System.out.println(user1); 22 23 24 25 //这里执行关闭操作,将sqlsession中的数据写到二级缓存区域 26 27 sqlSession1.close(); 28 29 30 31 //使用sqlSession3执行commit()操作 32 33 UserMapper userMapper3 = sqlSession3.getMapper(UserMapper.class); 34 35 User user = userMapper3.findUserById(1); 36 37 user.setUsername("张明明"); 38 39 userMapper3.updateUser(user); 40 41 //执行提交,清空UserMapper下边的二级缓存 42 43 sqlSession3.commit(); 44 45 sqlSession3.close(); 46 47 48 49 UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class); 50 51 // 第二次发起请求,查询id为1的用户 52 53 User user2 = userMapper2.findUserById(1); 54 55 System.out.println(user2); 56 57 58 59 sqlSession2.close(); 60 61 }
<select id="findOrderListResultMap" resultMap="ordersUserMap" useCache="false">
总结:针对每次查询都需要最新的数据sql,要设置成useCache=false,禁用二级缓存。
如下:
<insert id="insertUser" parameterType="cn.itcast.mybatis.po.User" flushCache="true">
总结:一般下执行完commit操作都需要刷新缓存,flushCache=true表示刷新缓存,这样可以避免数据库脏读。
记得添加到class
1 <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 2 3 xsi:noNamespaceSchemaLocation="../config/ehcache.xsd"> 4 5 <defaultCache 6 7 maxElementsInMemory="1000" 8 9 maxElementsOnDisk="10000000" 10 11 eternal="false" 12 13 overflowToDisk="false" 14 15 timeToIdleSeconds="120" 16 17 timeToLiveSeconds="120" 18 19 diskExpiryThreadIntervalSeconds="120" 20 21 memoryStoreEvictionPolicy="LRU"> 22 23 </defaultCache> 24 25 </ehcache>
实现方法如下:通过设置刷新间隔时间,由mybatis每隔一段时间自动清空缓存,根据数据变化频率设置缓存刷新间隔flushInterval,比如设置为30分钟、60分钟、24小时等,根据需求而定。
项目源码见链接: 密码: vcae
版权声明:本文为CSDN博主「EasyChill」的原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/Song_JiangTao/article/details/80022214
原文:https://www.cnblogs.com/Altwoman/p/11365294.html