mybatis(二)
1.动态代理
-
使用SqlSession.getMapper(dao接口.class) 获取这个dao接口的对象
-
封装一个mybatis工具类
package com.util; 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 java.io.IOException; import java.io.InputStream; /** * Created by IntelliJ IDEA. * User: LvHaoIT (asus) * Date: 2021/5/25 * Time: 11:01 */ public class MyBatisUtil { //调用就自动执行一次 public static SqlSessionFactory factory = null; /** * 静态代码块在类初始化阶段就会自动执行 */ static { String config = "mybatis.xml"; try { InputStream in = Resources.getResourceAsStream(config); factory = new SqlSessionFactoryBuilder().build(in);//为了下面获取sqlSession对象 } catch (IOException e) { e.printStackTrace(); } } /** * 静态方法:静态方法在类加载的使用使用,即当其他类中调用或new的时候,他将执行 * * @return SqlSession */ public static SqlSession getSqlSession() { SqlSession sqlSession = null; if (factory != null) { sqlSession = factory.openSession();//获取一个sqlSession对象,(非自动提交事务) } return sqlSession; } public static SqlSession getSqlSession(boolean flag) { SqlSession sqlSession = null; if (factory != null) { sqlSession = factory.openSession(flag);//获取一个sqlSession对象,(根据结果判断是否自动提交) } return sqlSession; } }
-
调用工具类,完成动态代理
/** * 使用mybatis的动态代理机制,使用SqlSession。getMapper(dao接口) * pper能获取dao接口对应的实现类对象 */ SqlSession sqlSession = MyBatisUtil.getSqlSession(); UsersDao dao = sqlSession.getMapper(UsersDao.class); //dao=com.sun.proxy.$Proxy2 JDK的动态代理 System.out.println("dao=" + dao.getClass().getName()); //调用dao的方法,执行数据库操作 List<Users> usersList = dao.selectUsers(); for (Users user : usersList) { System.out.println(user); }
2.传入参数
从java代码中把数据传入到mapper文件的sql语句中。
2.1 parameterType
-
写在mapper文件中的 一个属性。 表示dao接口中方法的参数的数据类型。
例如UsersDao接口
public Users selectUserById(Integer id);parameterType="java.lang.Integer"
<!-- parameterType : dao接口中方法参数的数据类型 parameterType 它的值是java的数据类型全限定名称或者是mybatis定义的别名 例如:parameterType = "java.lang.Interger" parameterType="int" 可以省略不写,可以自动识别 不是强制的,mybatis通过反射机制能够返现接口参数的类型 --> <select id="selectUserById" parameterType="java.lang.Integer" resultType="com.entity.Users"> select userId , userName,password,sex,email from users where userId=#{id} </select>
2.2 一个简单类型的参数
简单类型: mybatis把java的基本数据类型和String都叫简单类型。
在mapper文件获取简单类型的一个参数的值,使用 #{任意字符}
接口:public Users selectUserById(Integer id);
mapper:select userId , userName,password,sex,email from users where userId=#{id}
-
UsersDao
<select id="selectUserById" resultType="com.entity.Users"> select userId , userName,password,sex,email from users where userId=#{id} </select>
2.3 使用@Param命名参数(多个参数)
语法格式:使用 @Param(“参数名”) String name
-
接口:
public Users selectMutilUsers(@Param("userName") String userName, @Param("sex") String sex);
-
mapper文件
<!--多个属性,使用多个对应的属性名--> <select id="selectMutilUsers" resultType="com.entity.Users"> select userId , userName,password,sex,email from users where userName=#{userName} and sex=#{sex} </select>
2.4 多个参数,使用java对象
语法格式:语法 #{属性名}
-
接口:
public List<Users> selectMutilUsers_01(Users user);
-
mapper文件
<select id="selectMutilUsers_01" resultType="com.entity.Users"> select userId , userName,password,sex,email from users where password=#{password} and sex=#{sex} </select>
2.5 多个参数,使用map传递
语法格式:语法 #{map的key}
-
接口:
public List<Users> selectMutilUsers_Map(Map map);
-
mapper文件
<!--多个属性,使用Map传值--> <!--使用的语法是:#{map的key}--> <select id="selectMutilUsers_Map" resultType="com.entity.Users"> select userId , userName,password,sex,email from users where password=#{MapPassword} and sex=#{MapSex} </select> </mapper>
3.定义别名(当数据库与java类中属性名不匹配的情况)
-
vo: value object , 放一些存储数据的类。比如说 提交请求参数, name ,age
现在想把name ,age 传给一个service 类。vo: view object , 从servlet把数据返回给浏览器使用的类,表示显示结果的类。
-
pojo: 普通的有set, get方法的java类。 普通的java对象
Servlet — StudentService( addStudent( MyParam param) )
-
entity(domain域): 实体类, 和数据库中的表对应的类
3.1 第一种解决方式(使用resultMap定义映射关系)
-
接口:public List selectAllUsers();
-
resultMap
<!--使用resultMap(解决的是数据库里面的列名和java属性名不统一的情况) 第一种方法: 1.先定义resultMap 2.在select标签中,使用resultMap来引用1定义的 --> <!--定义resultMap id:自定义名称,表示你定义的这个resultMap type: java类型的全限定名称 --> <resultMap id="UsersMap" type="com.entity.Users"> <!--列名和java属性的关系--> <!--主键列,使用id标签 column:列名 property:java类型的属性名 --> <id column="userId" property="userId"/> <!--非主键列,使用result--> <result column="userName" property="userName"/> <result column="password" property="password"/> <result column="sex" property="sex"/> <result column="email " property="email"/> </resultMap>
-
userDao.xml
<select id="selectAllUsers" resultMap="UsersMap"> select * from Users order by userId; </select>
3.2 第二种解决方式 (使用查询语句内起别名的方式)
-
UsersDao.xml
<select id="selectAllMyUsers" resultType="com.entity.myUsers"> select userId as Id, userName as Name,password,sex,email from users order by userId </select>
4.# 和 $
4.1 使用过程
-
select id,name, email,age from student where id=#{studentId} # 的结果: select id,name, email,age from student where id=? select id,name, email,age from student where id=${studentId} $ 的结果:select id,name, email,age from student where id=1001 String sql="select id,name, email,age from student where id=" + "1001";
使用的Statement对象执行sql, 效率比PreparedStatement低。
: 可 以 替 换 表 名 或 者 列 名 , 你 能 确 定 数 据 是 安 全 的 。 可 以 使 用 :可以替换表名或者列名, 你能确定数据是安全的。可以使用 :可以替换表名或者列名,你能确定数据是安全的。可以使用(#可以防止sql注入)
4.2 # 和 $区别
- #使用 ?在sql语句中做站位的, 使用PreparedStatement执行sql,效率高
- #能够避免sql注入,更安全。
- $不使用占位符,是字符串连接方式,使用Statement对象执行sql,效率低
- $有sql注入的风险,缺乏安全性。
- $:可以替换表名或者列名
5.mybatis的输出结果
mybatis执行了sql语句,得到java对象。
5.1 resultType结果类型
指sql语句执行完毕后, 数据转为的java对象, java类型是任意的。
resultType结果类型的它值
- 类型的全限定名称
- 类型的别名, 例如 java.lang.Integer别名是int
处理方式:
- mybatis执行sql语句, 然后mybatis调用类的无参数构造方法,创建对象。
- mybatis把ResultSet指定列值付给同名的属性
<select id="selectUsers" resultType="com.entity.Users">
select userId , userName,password,sex,email from users order by userId
</select>
对等的jdbc
ResultSet rs = executeQuery(" select userId , userName,password,sex,email from users order by userId" )
while(rs.next()){
Users user = new Users();
student.setuserId(rs.getInt("userId"));
student.setuserName(rs.getString("username"))
...
}
5.2 定义自定义类型的别名
1)在mybatis主配置文件中定义,使定义别名
2)可以在resultType中使用自定义别名
<typeAliases>
<!--第一种方式
可以指定一个类型一个自定义别名
type:自动以类型的全限定名称
alias:别名(短小容易记忆)-->
<typeAlias type="com.entity.Users" alias="users"/>
<!--第二种方式
<package name="com.entity"/> name就是包名,类名就是别名(类名不区分大小写)
-->
<package name="com.entity"/>
</typeAliases>
5.3 resultMap:结果映射, 指定列名和java对象的属性对应关系。
1)你自定义列值赋值给哪个属性
2)当你的列名和属性名不一样时,一定使用resultMap
<resultMap id="UsersMap" type="com.entity.Users">
<!--列名和java属性的关系-->
<!--主键列,使用id标签
column:列名
property:java类型的属性名
-->
<id column="userId" property="userId"/>
<!--非主键列,使用result-->
<result column="userName" property="userName"/>
<result column="password" property="password"/>
<result column="sex" property="sex"/>
<result column="email " property="email"/>
</resultMap>
<select id="selectAllUsers" resultMap="UsersMap">
select * from Users order by userId;
</select>
注意:resultMap和resultType不要一起用,二选一
5.4 模糊查询
两种方式:
-
在java中直接拼接字符串,然后传递给方法(推荐)
//第一种方式 ,直接在java程序中传递已经拼接好的字符串(推荐) /*接口*/ public List<Users> selectLikeOne(String name); <!--模糊查询方式1 java中拼接like字符串--> <select id="selectLikeOne" resultType="com.entity.Users"> select * from Users where userName like #{name} </select>
-
在xml文件中拼接查询
//第二种方式,传递条件 进入xml中进行拼接 public List<Users> selectLikeTwo(String name); <!--模糊查询方式2 xml中拼接like字符串(%和空格都是必要的)--> <select id="selectLikeTwo" resultType="com.entity.Users"> select * from Users where userName like #{name} "%" </select>