1. 软件开发常用结构
1.1 三层架构
- 界面层(表示层,视图层):主要功能是接受用户的数据,显示请求的处理结果。使用 web 页面和用户交互,手机 app 也就是表示层的,用户在 app 中操作,业务逻辑在服务器端处理。
- 业务逻辑层:接收表示传递过来的数据,检查数据,计算业务逻辑,调用数据访问层获取数据。
- 数据访问层:与数据库打交道。主要实现对数据的增、删、改、查。将存储在数据库中的数据提交给业务层,同时将业务层处理的数据保存到数据库.
三层的处理请求的交互:
用户—> 界面层—>业务逻辑层—>数据访问层—>DB 数据库
为什么要使用三层?
1,结构清晰、耦合度低, 各层分工明确
2,可维护性高,可扩展性高
3,有利于标准化
4,开发人员可以只关注整个结构中的其中某一层的功能实现
5,有利于各层逻辑的复用
三层对应的处理框架
- 界面层—servlet—springmvc(框架)
- 业务逻辑层—service类–spring(框架)
- 数据访问层—dao类–mybatis(框架)
2. MyBatis框架介绍
2.1 MyBatis 解决的主要问题
- 传统JDBC编程存在的问题
- 代码比较多,开发效率低
- 需要关注 Connection ,Statement, ResultSet 对象创建和销毁
- 对 ResultSet 查询的结果,需要自己封装为 List
- 重复的代码比较多些
- 业务代码和数据库的操作混在一起
public void findStudent() {
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
//注册 mysql 驱动
Class.forName("com.mysql.jdbc.Driver");
//连接数据的基本信息 url ,username,password
String url = "jdbc:mysql://localhost:3306/springdb";
String username = "root";
String password = "123456";
//创建连接对象
conn = DriverManager.getConnection(url, username, password);
//保存查询结果
List<Student> stuList = new ArrayList<>();
//创建 Statement, 用来执行 sql 语句
stmt = conn.createStatement();
//执行查询,创建记录集,
rs = stmt.executeQuery("select * from student");
while (rs.next()) {
Student stu = new Student();
stu.setId(rs.getInt("id"));
stu.setName(rs.getString("name"));
stu.setAge(rs.getInt("age"));
//从数据库取出数据转为 Student 对象,封装到 List 集合
stuList.add(stu);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
//关闭资源
if (rs != null) ;
{
rs.close();
}
if (stmt != null) {
stmt.close();
}
if (conn != null) {
conn.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
- MyBatis 解决的主要问题
减轻使用 JDBC 的复杂性,不用编写重复的创建 Connetion , Statement ; 不用编写关闭资源代码。直接使用 java 对象,表示结果数据。让开发者专注 SQL 的处理。 其他分心的工作由 MyBatis 代劳。
MyBatis 可以完成:
1. 注册数据库的驱动,例如 Class.forName(“com.mysql.jdbc.Driver”))
2. 创建 JDBC 中必须使用的 Connection , Statement, ResultSet 对象
3. 从 xml 中获取 sql,并执行 sql 语句,把 ResultSet 结果转换 java 对象
List<Student> list = new ArrayLsit<>();
ResultSet rs = state.executeQuery(“select * from student”);
while(rs.next){
Student student = new Student();
student.setName(rs.getString(“name”));
student.setAge(rs.getInt(“age”));
list.add(student);
}
4.关闭资源
ResultSet.close() , Statement.close() , Conenection.close()
2.2 IDEA中如何使用MyBatis
MyBatis入门案例
- 第一步: 创建 mysql 数据库和表
数据库名 ssm ;表名 student - 第二步:创建 maven 工程
- 第三步:在Pom文件加入 MyBatis依赖和数据库驱动依赖
<!--mybatis依赖 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.1</version>
</dependency>
<!--mysql驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.23</version>
</dependency>
</dependencies>
- 第四步:编写 Student 实体类
创建包 com.bjpowernode.entity, 包中创建 Student 类
package com.bjpowernode.entity;
//实体类推荐和表名一样
public class Student {
//定义属性,目前要求是属性名和列名一样
private Integer id;
private String name;
private String email;
private Integer age;
public Student(){}
public Student(Integer id, String name, String email, Integer age) {
this.id = id;
this.name = name;
this.email = email;
this.age = age;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", email='" + email + '\'' +
", age=" + age +
'}';
}
}
- 第五步:编写 Dao 接口 StudentDao
创建 com.bjpowernode.dao 包,创建 StudentDao 接口
package com.bjpowernode.dao;
import com.bjpowernode.entity.Student;
import java.util.List;
//接口操作student表
public interface StudentDao {
//查询student表的所有数据
public List<Student> selectStudents();
//插入方法
/**
*
* @param student:插入数据库中的数据
* @return int:表示执行insert操作后,影响数据库中的行数
*/
public int insertStudents(Student student);
}
- 第六步:编写 Dao 接口 Mapper 映射文件 StudentDao.xml
要求:
- 在 dao 包中创建文件 StudentDao.xml
- 要求 StudentDao.xml 文件名称和接口 StudentDao 一样,区分大小写的一样。
<?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="com.bjpowernode.dao.StudentDao">
<!--
select:表示查询操作
id:你要执行sql语句的唯一标识,mybatis会使用这个id的值找到要执行的sql语句
可以自定义,但是要求你要求你使用接口中的方法名称。
resultType:表示结果类型的,是sql语句执行后得到ResultSet,遍历这个ResultSet得到java对象的类型。
值写的是类型的全限定名称。
-->
<select id="selectStudents" resultType="com.bjpowernode.entity.Student">
select id,name,email,age from student
</select>
<!--插入操作-->
<insert id="insertStudents">
insert into student values(#{id},#{name},#{email},#{age})
</insert>
</mapper>
<!--
sql映射文件:写sql语句,mybatis会执行这些sql
1. 指定约束文件
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
mybatis-3-mapper.dtd:是约束文件,扩展名是dtd的
2. 约束文件的作用:限制和检查在当前文件中出现的标签,属性必须符合mybatis的要求
3. mapper是当前文件的根标签,必须的
namespace 是命名空间,唯一值的,可以是自定义的字符串,要求你使用dao接口的全限定名称.
4. 在当前文件中可以使用特点的标签,表示数据库的特定操作
<select>:表示执行查询
<update>:表示更新数据库的操作,就是在<update>标签中写的是update sql语句
<insert>:表示插入
<delete>:表示的是删除
-->
- 第七步:创建 MyBatis 主配置文件
项目 src/main 下创建 resources 目录,设置 resources 目录为 resources root
创建主配置文件:名称为 mybatis.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>
<!--settings:控制mybatis全局行为的-->
<settings>
<!--设置mybatis输出日志-->
<setting name="logImpl" value="STDOUT_LOGGING" />
</settings>
<!--环境配置:数据库的连接信息
default : 必须和某个environment中的id值一样
告诉mybatis即将连接的是哪个数据库的的连接信息,也就是访问哪个数据库
(这里的不同不是数据库产品的不同,而是在不同项目运行状态下使用的数据库不用)
如:在线上和本地使用的数据库不同,
-->
<environments default="mydev">
<!--environment:一个数据库信息的配置,环境
id:一个唯一值,自定义的,表示环境的名称
-->
<environment id="mydev">
<!--transactionManager:mybatis的事务类型
type:JDBC(表示使用jdbc中的connection对象的commit,rollback做事务处理)-->
<transactionManager type="JDBC"/>
<!--dataSource:表示数据源,连接数据库的
type:表示数据源的类型,POOLED表示使用的连接池
-->
<dataSource type="POOLED">
<!--
driver,url,username,password 是固定的们不能自定义
-->
<!--driver,数据库驱动类名-->
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<!--url,数据库连接地址-->
<property name="url" value="jdbc:mysql://localhost:3306/ssm"/>
<!--username,连接数据库的用户名称-->
<property name="username" value="root"/>
<!--password,连接数据库的用户的密码-->
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!--sql映射文件的地址-->
<mappers>
<!--一个mapper标签指定一个文件的位置
从类路径开始的路径信息
-->
<mapper resource="com/bjpowernode/dao/StudentDao.xml"/>
</mappers>
</configuration>
<!--
mybatis的主配置文件:主要定义了数据库的配置信息,sql映射文件的位置
1. 约束文件
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
2. 根标签:<configuration>
-->
- 创建测试类
package com.bjpowernode;
import com.bjpowernode.entity.Student;
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;
import java.util.List;
public class MyApp {
public static void main(String[] args) throws IOException {
//访问mybatis读取student表中内容
// 1.定义mybatis主配置文件的名称,从类路径的根路径开始(target/classes)
String config = "mybatis.xml";
// 2.读取config表示的文件
InputStream in = Resources.getResourceAsStream(config);
// 3.创建SqlSessionFactoryBuilder对象
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
// 4.创建SqlSessionFactory对象
SqlSessionFactory factory = builder.build(in);
// 5.【重要的】获取 SqlSession对象,从SqlSessionFactory中会获取SqlSession
SqlSession sqlSession = factory.openSession();
// 6. 指定要执行的sql语句的标识。sql映射文件中的namespace + "." + 标签的id值
String sqlId = "com.bjpowernode.dao.StudentDao" + "." + "selectStudents";
// 7.执行sql语句,通过sqlId找到语句
List<Student> studentList = sqlSession.selectList(sqlId);
// 8.输出结果
for (Student stu:studentList) {
System.out.println(stu);
}
// 9.关闭SqlSession对象
sqlSession.close();
}
}
2.3 主要类的介绍
- Resources: mybatis中的一个类, 负责读取主配置文件
InputStream in = Resources.getResourceAsStream(“mybatis.xml”); - SqlSessionFactoryBuilder : 创建SqlSessionFactory对象,
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
//创建SqlSessionFactory对象
SqlSessionFactory factory = builder.build(in); - SqlSessionFactory : 重量级对象, 程序创建一个对象耗时比较长,使用资源比较多。
在整个项目中,有一个就够用了。
SqlSessionFactory:接口 , 接口实现类: DefaultSqlSessionFactory
SqlSessionFactory作用: 获取SqlSession对象。SqlSession sqlSession = factory.openSession();
openSession()方法说明:
1. openSession() :无参数的, 获取是非自动提交事务的SqlSession对象
2. openSession(boolean): openSession(true) 获取自动提交事务的SqlSession.
openSession(false) 非自动提交事务的SqlSession对象
- SqlSession:
SqlSession接口 :定义了操作数据的方法 例如 selectOne() ,selectList() ,insert(),update(), delete(), commit(), rollback()
SqlSession接口的实现类DefaultSqlSession。
使用要求: SqlSession对象不是线程安全的,需要在方法内部使用, 在执行sql语句之前,使用openSession()获取SqlSession对象。
在执行完sql语句后,需要关闭它,执行SqlSession.close(). 这样能保证他的使用是线程安全的。
3. MyBatis框架Dao代理
小便捷:创建MyBatis的util工具类封装一下部分类的使用
package com.bjpowernode.utils;
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;
public class MyBatisUtils {
private static SqlSessionFactory factory = null;
static {
//读取mybatis主配置文件
String config = "mybatis.xml";//需要和你的项目中名字一样
try {
InputStream in = Resources.getResourceAsStream(config);
//创建SqlSessionFactory对象,使用SqlSessionFactoryBuild
factory = new SqlSessionFactoryBuilder().build(in);
} catch (IOException e) {
e.printStackTrace();
}
}
//获取sqlSession方法
public static SqlSession getSqlSession(){
SqlSession sqlSession = null;
if (factory != null) {
sqlSession = factory.openSession();//非自动提交事务
}
return sqlSession;
}
}
3.1 Dao 代理实现 CURD
(1) 去掉 Dao 接口实现类
(2) getMapper 获取代理对象
只需调用 SqlSession 的 getMapper()方法,即可获取指定接口的实现类对象。该方法的参数为指定 Dao接口类的 class 值。
package com.bjpowernode;
import com.bjpowernode.dao.StudentDao;
import com.bjpowernode.entity.Student;
import com.bjpowernode.utils.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import java.util.List;
public class TestMyBatis {
@Test
public void testSelectStudents(){
/**
* 使用MyBatis的动态代理机制,使用sqlSession,getMapper(dao接口)
* getMapper能够获取的是dao接口的实现类对象
*/
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentDao dao = sqlSession.getMapper(StudentDao.class);
//调用dao的方法执行数据库的操作
List<Student> studentList = dao.selectStudents();
for (Student stu:studentList) {
System.out.println(stu);
}
}
@Test
public void testInsertStudents(){
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentDao dao = sqlSession.getMapper(StudentDao.class);
//调用dao的方法执行数据库的操作
int nums = dao.insertStudents(new Student(1005, "刘备", "liubei@163.com", 25));
sqlSession.commit();
System.out.println("添加成员" + nums);
}
}
3.2 深入理解参数
3.2.1 parameterType
parameterType: 接口中方法参数的类型, 类型的完全限定名或别名。这个属性是可选的,因为 MyBatis 可以推断出具体传入语句的参数,默认值为未设置(unset)。接口中方法的参数从 java 代码传入到mapper 文件的 sql 语句。
例如:
<delete id="deleteStudent" parameterType="int">
delete from student where id=#{studentId}
</delete>
等同于
<delete id="deleteStudent" parameterType="java.lang.Integer">
delete from student where id=#{studentId}
</delete>
如:
<?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="com.bjpowernode.dao.StudentDao">
<!--
parameterType : dao接口中方法参数的数据类型
parameterType的值是java数据类型全限定名称或者是mybatis定义的别名
例如:parameterType="java.lang.Integer"
或 parameterType="int"
注意:parameterType不是强制的,mybatis可以通过反射机制发现接口中的参数的数据类型
所以可以没有,一般不写。
-->
<select id="selectStudentById" parameterType="java.lang.Integer" resultType="com.bjpowernode.entity.Student">
select id,name,email,age from student where id = #{id}
</select>
</mapper>
3.2.2 MyBatis 传递参数
- 一个简单类型的参数:
简单类型: mybatis把java的基本数据类型和String都叫简单类型。
在mapper文件获取简单类型的一个参数的值,使用 #{任意字符}
接口:public Student selectStudentById(Integer id)
mapper:select id,name, email,age from student where id=#{studentId}
- 多个参数,使用@Param命名参数
接口 public List<Student> selectMulitParam(@Param("myname") String name, @Param("myage") Integer age)
使用 @Param("参数名") String name
mapper文件:
<select>
select * from student where name=#{myname} or age=#{myage}
</select>
- 多个参数,使用java对象
语法 #{属性名}
<?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="com.bjpowernode.dao.StudentDao">
<select id="selectStudentById" parameterType="int" resultType="com.bjpowernode.domain.Student">
select id,name, email,age from student where id=${studentId}
</select>
<!--多个参数,使用@Param命名-->
<select id="selectMultiParam" resultType="com.bjpowernode.domain.Student">
select id,name, email,age from student where name=#{myname} or age=#{myage}
</select>
<!--多个参数, 使用java对象的属性值,作为参数实际值
使用对象语法: #{属性名,javaType=类型名称,jdbcType=数据类型} 很少用。
javaType:指java中的属性数据类型。
jdbcType:在数据库中的数据类型。
例如: #{paramName,javaType=java.lang.String,jdbcType=VARCHAR}
我们使用的简化方式: #{属性名} ,javaType, jdbcType的值mybatis反射能获取。不用提供
-->
<!-- <select id="selectMultiObject" resultType="com.bjpowernode.domain.Student">
select id,name, email,age from student where
name=#{paramName,javaType=java.lang.String,jdbcType=VARCHAR}
or age=#{paramAge,javaType=java.lang.Integer,jdbcType=INTEGER}
</select>-->
<select id="selectMultiObject" resultType="com.bjpowernode.domain.Student">
select id,name, email,age from student where
name=#{paramName} or age=#{paramAge}
</select>
<select id="selectMultiStudent" resultType="com.bjpowernode.domain.Student">
select id,name, email,age from student where name=#{name} or age=#{age}
</select>
<!--多个参数使用位置-->
<select id="selectMultiPosition" resultType="com.bjpowernode.domain.Student">
select id,name, email,age from student where
name = #{arg0} or age=#{arg1}
</select>
<!--多个参数,使用Map , 使用语法 #{map的key}-->
<select id="selectMultiByMap" resultType="com.bjpowernode.domain.Student">
select id,name, email,age from student where
name = #{myname} or age=#{age1}
</select>
<!--使用 ${}-->
<select id="selectUse$" resultType="com.bjpowernode.domain.Student">
select * from student where name=${myname}
</select>
<!--
$替换列名
-->
<select id="selectUse$Order" resultType="com.bjpowernode.domain.Student">
select * from student order by ${colName}
</select>
</mapper>
package com.bjpowernode.dao;
import com.bjpowernode.domain.Student;
import com.bjpowernode.vo.QueryParam;
import org.apache.ibatis.annotations.Param;
import java.util.List;
import java.util.Map;
public interface StudentDao {
/**
* 一个简单类型的参数:
* 简单类型: mybatis把java的基本数据类型和String都叫简单类型。
* 在mapper文件获取简单类型的一个参数的值,使用 #{任意字符}
*/
public Student selectStudentById(@Param("studentId") Integer id);
/**
* 多个参数: 命名参数,在形参定义的前面加入 @Param("自定义参数名称")
*/
List<Student> selectMultiParam(@Param("myname") String name,
@Param("myage") Integer age);
/**
* 多个参数,使用java对象作为接口中方法的参数
*/
List<Student> selectMultiObject(QueryParam param);
List<Student> selectMultiStudent(Student student);
/**
* 多个参数-简单类型的,按位置传值,
* mybatis.3.4之前,使用 #{0} ,#{1}
* mybatis。3.4之后 ,使用 #{arg0} ,#{arg1}
*/
List<Student> selectMultiPosition( String name,Integer age);
/**
* 多个参数,使用Map存放多个值
*/
List<Student> selectMultiByMap(Map<String,Object> map);
List<Student> selectUse$(@Param("myname") String name);
List<Student> selectUse$Order(@Param("colName") String colName);
}
3.2.3 # 和 $
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
- .# 和 $区别
- #使用 ?在sql语句中做站位的, 使用PreparedStatement执行sql,效率高
- #能够避免sql注入,更安全。
- $不使用占位符,是字符串连接方式,使用Statement对象执行sql,效率低
- $有sql注入的风险,缺乏安全性。
3.2.4 resultMap和resultType 及模糊查询Like
1)resultType结果类型, 指sql语句执行完毕后, 数据转为的java对象, java类型是任意的。
resultType结果类型的它值
1. 类型的全限定名称 2. 类型的别名, 例如 java.lang.Integer别名是int
处理方式:
1. mybatis执行sql语句, 然后mybatis调用类的无参数构造方法,创建对象。
2. mybatis把ResultSet指定列值付给同名的属性。
<select id="selectMultiPosition" resultType="com.bjpowernode.domain.Student">
select id,name, email,age from student
</select>
对等的jdbc
ResultSet rs = executeQuery(" select id,name, email,age from student" )
while(rs.next()){
Student student = new Student();
student.setId(rs.getInt("id"));
student.setName(rs.getString("name"))
}
2) 定义自定义类型的别名
1)在mybatis主配置文件中定义,使<typeAlias>定义别名
2)可以在resultType中使用自定义别名
3)resultMap:结果映射, 指定列名和java对象的属性对应关系。
1)你自定义列值赋值给哪个属性
2)当你的列名和属性名不一样时,一定使用resultMap
resultMap和resultType不要一起用,二选一
<?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="com.bjpowernode.dao.StudentDao">
<!--selectStudentReturnViewStudent-->
<select id="selectStudentReturnViewStudent" resultType="ViewStudent">
select id,name from student where id=#{sid}
</select>
<!--sql执行后返回一行一列-->
<!--<select id="countStudent" resultType="int">-->
<select id="countStudent" resultType="java.lang.Integer">
select count(*) from student
</select>
<!--返回Map
1)列名是map的key, 列值是map的value
2)只能最多返回一行记录。多余一行是错误
-->
<select id="selectMapById" resultType="java.util.HashMap">
select id,name,email from student where id=#{stuid}
</select>
<!--使用resultMap
1)先定义resultMap
2)在select标签,使用resultMap来引用1定义的。
-->
<!--定义resultMap
id:自定义名称,表示你定义的这个resultMap
type:java类型的全限定名称
-->
<resultMap id="studentMap" type="com.bjpowernode.domain.Student">
<!--列名和java属性的关系-->
<!--注解列,使用id标签
column :列名
property:java类型的属性名
-->
<id column="id" property="id" />
<!--非主键列,使用result-->
<result column="name" property="name" />
<result column="email" property="email" />
<result column="age" property="age" />
</resultMap>
<select id="selectAllStudents" resultMap="studentMap">
select id,name, email , age from student
</select>
<resultMap id="myStudentMap" type="com.bjpowernode.domain.MyStudent">
<!--列名和java属性的关系-->
<id column="id" property="stuid" />
<!--非主键列,使用result-->
<result column="name" property="stuname" />
<result column="email" property="stuemail" />
<result column="age" property="stuage" />
</resultMap>
<!--列名和属性名不一样:第一种方式-->
<select id="selectMyStudent" resultMap="myStudentMap">
select id,name, email , age from student
</select>
<!--列名和属性名不一样:第二种方式
resultType的默认原则是 同名的列值赋值给同名的属性, 使用列别名(java对象的属性名)
-->
<select id="selectDiffColProperty" resultType="com.bjpowernode.domain.MyStudent">
select id as stuid ,name as stuname, email as stuemail , age stuage from student
</select>
<!--第一种 like , java代码指定 like的内容-->
<select id="selectLikeOne" resultType="com.bjpowernode.domain.Student">
select id,name,email,age from student where name like #{name}
</select>
<!--第二种方式:在mapper文件中拼接 like的内容-->
<select id="selectLikeTwo" resultType="com.bjpowernode.domain.Student">
select id,name,email,age from student where name like "%" #{name} "%"
</select>
</mapper>
4. 动态sql
动态sql: sql的内容是变化的,可以根据条件获取到不同的sql语句。
主要是where部分发生变化。
动态sql的实现:
使用的是mybatis提供的标签, <if> ,<where>,<foreach>
4.1 if 标签使用
<!--if
<if test = "使用参数java对象的属性值作为判断条件 语法规则:属性名 = xxx值"
-->
<select id="selectStudentIf" resultType="com.bjpowernode.domain.Student">
<include refid="studentSql"/>
where
<if test="name != null and name != ''">
name = #{name}
</if>
<if test="age > 0">
or age > #{age}
</if>
</select>
缺点:当使用多个if标签命令时,会产生SQL语法错误。如下所示:
<sql id="studentSql">
select id,name,email,age from student
</sql>
<select id="selectStudentIf" resultType="com.bjpowernode.domain.Student">
<include refid="studentSql"/>
where
<if test="name != null and name != ''">
name = #{name}
</if>
<if test="age > 0">
or age > #{age}
</if>
</select>
在输入参数时:若判断name时不符合条件,而age符合条件,此时的sql语句会变为:
select id,name,email,age from student or age = ?
此时存在语法错误。
解决方法:
法1 : 如下所示
缺陷:在实际情况中,若后面两个条件都不符合时会使用 1 = 1查询到所有数据,但是sql原意是查询不到数据。
<select id="selectStudentIf" resultType="com.bjpowernode.domain.Student">
<include refid="studentSql"/>
where
1 = 1
<if test="name != null and name != ''">
and name = #{name}
</if>
<if test="age > 0">
or age > #{age}
</if>
</select>
法2 : 使用where标签,不存在上述缺陷
4.2 where 标签使用
用来包含 多个if的, 当多个if有一个成立的, where会自动增加一个where关键字,并去掉 if中多余的 and ,or等。
<!--where : <where> <if> </if>... </where>
-->
<select id="selectStudentWhere" resultType="com.bjpowernode.domain.Student">
<include refid="studentSql"/>
<where>
<if test="name != null and name != ''">
name = #{name}
</if>
<if test="age > 0">
or age > #{age}
</if>
</where>
</select>
4.3 foreach 标签使用
foreach 标签用于实现对于数组与集合的遍历。对其使用,需要注意:
➢ collection 表示要遍历的集合类型, list ,array 等。
➢ open、close、separator 为对遍历内容的 SQL 拼接。
语法:
<foreach collection="集合类型" open="开始的字符" close="结束的字符"
item="集合中的成员" separator="集合成员之间的分隔符">
#{item 的值}
</foreach>
<!--foreach使用1 ,当传入的List集合中存储的是基本数据类型时
-->
<select id="selectStudentOne" resultType="com.bjpowernode.domain.Student">
<include refid="studentSql"/> where id in
<foreach collection="list" item="myid" open="(" close=")" separator=",">
#{myid}
</foreach>
</select>
<!--foreach使用2 当传入的List集合中存储的是引用数据类型时,直接使用引用.属性名 的方式。
-->
<select id="selectStudentTwo" resultType="com.bjpowernode.domain.Student">
<include refid="studentSql"/> where id in
<foreach collection="list" item="stu" open="(" close=")" separator=",">
#{stu.id}
</foreach>
</select>
4.4 sql代码片段
步骤
1.先定义 <sql id="自定义名称唯一"> sql语句, 表名,字段等 </sql>
2.再使用, <include refid="id的值" />
<!--定义sql代码片段-->
<sql id="studentSql">
select id,name,email,age from student
</sql>
<!--if
<if test = "使用参数java对象的属性值作为判断条件 语法规则:属性名 = xxx值"
-->
<select id="selectStudentIf" resultType="com.bjpowernode.domain.Student">
<include refid="studentSql"/>
where
<if test="name != null and name != ''">
name = #{name}
</if>
<if test="age > 0">
or age > #{age}
</if>
</select>
5. mybatis主配置文件
主配置文件特点:
1. 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">
2.根元素,<configuration>
3.主要包含内容:
➢ 定义别名
➢ 数据源
➢ mapper 文件
<?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文件的位置,从类路径根开始找文件-->
<properties resource="jdbc.properties" />
<!--settings:控制mybatis全局行为-->
<!-- <settings>-->
<!-- <!–设置mybatis输出日志–>-->
<!-- <setting name="logImpl" value="STDOUT_LOGGING"/>-->
<!-- </settings>-->
<!--定义别名-->
<typeAliases>
<!--
第一种方式:
可以指定一个类型一个自定义别名
type:自定义类型的全限定名称
alias:别名(短小,容易记忆的)
-->
<!--<typeAlias type="com.bjpowernode.domain.Student" alias="stu" />
<typeAlias type="com.bjpowernode.vo.ViewStudent" alias="vstu" />-->
<!--
第二种方式
<package> name是包名, 这个包中的所有类,类名就是别名(类名不区分大小写)
-->
<package name="com.bjpowernode.domain"/>
<package name="com.bjpowernode.vo"/>
</typeAliases>
<!--配置pagehelper插件-->
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor" />
</plugins>
<environments default="mydev">
<environment id="mydev">
<!--
transactionManager:mybatis提交事务,回滚事务的方式
type: 事务的处理的类型
1)JDBC : 表示mybatis底层是调用JDBC中的Connection对象的,commit, rollback
2)MANAGED : 把mybatis的事务处理委托给其它的容器(一个服务器软件,一个框架(spring))
-->
<transactionManager type="JDBC"/>
<!--
dataSource:表示数据源,java体系中,规定实现了javax.sql.DataSource接口的都是数据源。
数据源表示Connection对象的。
type:指定数据源的类型
1)POOLED: 使用连接池, mybatis会创建PooledDataSource类
2)UPOOLED: 不使用连接池, 在每次执行sql语句,先创建连接,执行sql,在关闭连接
mybatis会创建一个UnPooledDataSource,管理Connection对象的使用
3)JNDI:java命名和目录服务(windows注册表)
-->
<dataSource type="POOLED">
<!--数据库的驱动类名-->
<property name="driver" value="${jdbc.driver}"/>
<!--连接数据库的url字符串-->
<property name="url" value="${jdbc.url}"/>
<!--访问数据库的用户名-->
<property name="username" value="${jdbc.user}"/>
<!--密码-->
<property name="password" value="${jdbc.passwd}"/>
</dataSource>
</environment>
</environments>
<!-- sql mapper(sql映射文件)的位置-->
<mappers>
<!--第一种方式:指定多个mapper文件-->
<!--<mapper resource="com/bjpowernode/dao/StudentDao.xml"/>
<mapper resource="com/bjpowernode/dao/OrderDao.xml" />-->
<!--第二种方式: 使用包名
name: xml文件(mapper文件)所在的包名, 这个包中所有xml文件一次都能加载给mybatis
使用package的要求:
1. mapper文件名称需要和接口名称一样, 区分大小写的一样
2. mapper文件和dao接口需要在同一目录
-->
<package name="com.bjpowernode.dao"/>
<!-- <package name="com.bjpowernode.dao2"/>
<package name="com.bjpowernode.dao3"/>-->
</mappers>
</configuration>
6. 扩展
6.1 PageHelper 分页方法
使用方法:
- 第一步 : 现在POM中加入PageHelper 依赖
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.1.10</version>
</dependency>
- 第二步:在mybatis主配置文件中加入插件
<!--在<environments>之前加入-->
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor" />
</plugins>
- PageHelper 对象,查询语句之前调用 PageHelper.startPage 静态方法。
@Test
public void testSelect() throws IOException {
//获取第 1 页,3 条内容
PageHelper.startPage(1,3);
List<Student> studentList = studentDao.selectStudents();
studentList.forEach( stu -> System.out.println(stu));
}