Spring 框架: Spring 框架为了解决软件开发的复杂性而创建的。Spring 使用的是基本的 JavaBean 来完成以前非常复杂的企业级开发。Spring 解决了业务对象,功能模块之间的耦合,不仅在 javase,web 中使用,大部分 Java 应用都可以从 Spring 中受益。 Spring 是一个轻量级控制反转(IoC)和面向切面(AOP)的容器。
SpringMVC 框架 Spring MVC 属于 SpringFrameWork 3.0 版本加入的一个模块,为 Spring 框架提供了构建 Web 应用程序的能力。现在可以 Spring 框架提供的 SpringMVC 模块实现 web 应用开发,在 web 项目中可以无缝使用 Spring 和 Spring MVC 框架。
(1) 创建 Dao 接口实现类 public class StudentDaoImpl implements StudentDao
(2) 实现接口中 select 方法
public List selectStudents() {
SqlSession session = MyBatisUtil.getSqlSession();
List studentList = session.selectList(
"com.bjpowernode.dao.StudentDao.selectStudents");
session.close();
return studentList;
}
测试查询操作: MyBatisTest 类中创建 StudentDaoImpl 对象
public class MyBatisTest {
StudentDao studentDao = new StudentDaoImpl();
}
@Test
public void testSelect() throws IOException {
final List studentList = studentDao.selectStudents();
studentList.forEach( stu -> System.out.println(stu));
}
(3) 实现接口中 insert 方法
public int insertStudent(Student student) {
SqlSession session = MyBatisUtil.getSqlSession();
int nums = session.insert(
"com.bjpowernode.dao.StudentDao.insertStudent",student);
session.commit();
session.close();
return nums;
}
测试 insert
@Test
public void testInsert() throws IOException {
Student student = new Student();
student.setId(1006);
student.setName("林浩");
student.setEmail("[email protected]");
student.setAge(26);
int nums = studentDao.insertStudent(student);
System.out.println("使用 Dao 添加数据:"+nums);
}
(4) 实现接口中 update 方法
public int updateStudent(Student student) {
SqlSession session = MyBatisUtil.getSqlSession();
int nums = session.insert(
"com.bjpowernode.dao.StudentDao.updateStudent",student);
session.commit();
session.close();
return nums;
}
测试 update
@Test
public void testUpdate() throws IOException {
Student student = new Student();
student.setId(1006);
student.setAge(28);
int nums = studentDao.updateStudent(student);
System.out.println("使用 Dao 修改数据:"+nums);
}
(5) 实现接口中 delete 方法
public int deleteStudent(int id) {
SqlSession session = MyBatisUtil.getSqlSession();
int nums = session.insert(
"com.bjpowernode.dao.StudentDao.deleteStudent",1006);
session.commit();
session.close();
return nums;
}
测试 delete
@Test
public void testDelete() throws IOException {
int nums = studentDao.deleteStudent(1006);
System.out.println("使用 Dao 修改数据:"+nums);
}
传统 Dao 开发方式的分析
在前面例子中自定义 Dao 接口实现类时发现一个问题:Dao 的实现类其实并没有干什么实质性的工作,它仅仅就是通过 SqlSession 的相关 API 定位到映射文件 mapper 中相应 id 的 SQL 语句,真正对 DB 进行操作的工作其实是由框架通过 mapper 中的 SQL 完成的。
所以,MyBatis 框架就抛开了 Dao 的实现类,直接定位到映射文件 mapper 中的相应 SQL 语句,对DB 进行操作。这种对 Dao 的实现方式称为 Mapper 的动态代理方式。
Mapper 动态代理方式无需程序员实现 Dao 接口。接口是由 MyBatis 结合映射文件自动生成的动态代理实现的。
MyBatis 框架 Dao 代理
Dao 代理实现 CURD
步骤
(1) 去掉 Dao 接口实现类
image.png
(2) getMapper 获取代理对象 只需调用 SqlSession 的 getMapper()方法,即可获取指定接口的实现类对象。该方法的参数为指定 Dao接口类的 class 值。
SqlSession session = factory.openSession(); StudentDao dao = session.getMapper(StudentDao.class);
@Test
public void testSelect() throws IOException {
final List studentList = studentDao.selectStudents();
studentList.forEach( stu -> System.out.println(stu));
}
insert 方法:
@Test
public void testInsert() throws IOException {
Student student = new Student();
student.setId(1006);
student.setName("林浩");
student.setEmail("[email protected]");
student.setAge(26);
int nums = studentDao.insertStudent(student);
System.out.println("使用 Dao 添加数据:"+nums);
}
update 方法
@Test
public void testUpdate() throws IOException {
Student student = new Student();
student.setId(1006);
student.setAge(28);
int nums = studentDao.updateStudent(student);
System.out.println("使用 Dao 修改数据:"+nums);
}
delete 方法
@Test
public void testDelete() throws IOException {
int nums = studentDao.deleteStudent(1006);
System.out.println("使用 Dao 修改数据:"+nums);
}
package com.bjpowernode.vo;
public class QueryParam {
private String queryName;
private int queryAge;
//set ,get 方法
}
接口方法: List selectMultiObject(QueryParam queryParam);
mapper 文件:
或
测试方法:
@Test
public void selectMultiObject(){
QueryParam qp = new QueryParam();
qp.setQueryName("李力");
qp.setQueryAge(20);
List stuList = studentDao.selectMultiObject(qp);
stuList.forEach( stu -> System.out.println(stu));
}
接口方法: List selectByNameAndAge(String name,int age);
mapper 文件:
测试方法:
@Test
public void testSelectByNameAndAge(){
//按位置参数
List stuList = studentDao.selectByNameAndAge("李力",20);
stuList.forEach( stu -> System.out.println(stu));
}
例如: Map data = new HashMap(); data.put(“myname”,”李力”); data.put(“myage”,20);
接口方法: List selectMultiMap(Map map);
mapper 文件:
测试方法:
@Test
public void testSelectMultiMap(){
Map data = new HashMap<>();
data.put("myname","李力");// #{myname}
data.put("myage",20); // #{myage}
List stuList = studentDao.selectMultiMap(data);
stuList.forEach( stu -> System.out.println(stu));
}
@Test
public void testSelectUseResultMap(){
QueryParam param = new QueryParam();
param.setQueryName("李力");
param.setQueryAge(20);
List stuList = studentDao.selectUseResultMap(param);
stuList.forEach( stu -> System.out.println(stu));
}
实体类属性名和列名不同的处理方式
(1) 使用列别名和
步骤:
创建新的实体类 PrimaryStudent
package com.bjpowernode.domain;
/**
*
Description: 实体类
*
Company: http://www.bjpowernode.com
*/
public class PrimaryStudent {
private Integer stuId;
private String stuName;
private Integer stuAge;
// set , get 方法
}
接口方法 List selectUseFieldAlias(QueryParam param);
mapper 文件:
4.测试方法
@Test
public void testSelectUseFieldAlias(){
QueryParam param = new QueryParam();
param.setQueryName("李力");
param.setQueryAge(20);
List stuList;
stuList = studentDao.selectUseFieldAlias(param);
stuList.forEach( stu -> System.out.println(stu));
}
(2) 使用
步骤:
接口方法 List selectUseDiffResultMap(QueryParam param);
mapper 文件:
测试方法
@Test
public void testSelectUseDiffResultMap(){
QueryParam param = new QueryParam();
param.setQueryName("李力");
param.setQueryAge(20);
List stuList;
stuList = studentDao.selectUseDiffResultMap(param);
stuList.forEach( stu -> System.out.println(stu));
}
例 1: java 代码中提供要查询的 “%力%” 接口方法: List selectLikeFirst(String name);
mapper 文件:
测试方法:
@Test
public void testSelectLikeOne(){
String name="%力%";
List stuList = studentDao.selectLikeFirst(name);
stuList.forEach( stu -> System.out.println(stu));
}
例 2:mapper 文件中使用 like name "%" #{xxx} "%"
接口方法: List selectLikeSecond(String name);
mapper 文件:
测试方法:
@Test
public void testSelectLikeSecond(){
String name="力";
List stuList = studentDao.selectLikeSecond(name);
stuList.forEach( stu -> System.out.println(stu));
}
@Test
public void testSelect() throws IOException {
Student param = new Student();
param.setName("李力");
param.setAge(18);
List studentList = studentDao.selectStudentIf(param);
studentList.forEach( stu -> System.out.println(stu));
}
动态 SQL 之
标签的中存在一个比较麻烦的地方:需要在 where 后手工添加 1=1 的子句。因为,若 where 后的所有条件均为 false,而 where 后若又没有 1=1 子句,则 SQL 中就会只剩下一个空的 where,SQL出错。所以,在 where 后,需要添加永为真子句 1=1,以防止这种情况的发生。但当数据量很大时,会严重影响查询效率。
使用标签,在有查询条件时,可以自动添加上 where 子句;没有查询条件时,不会添加where 子句。需要注意的是,第一个标签中的 SQL 片断,可以不包含 and。不过,写上 and 也不错,系统会将多出的 and 去掉。但其它中 SQL 片断的 and,必须要求写上。否则 SQL 语句将拼接出错。
语法: 其他动态 sql
接口方法: List selectStudentWhere(Student student);
mapper 文件:
测试方法:
@Test
public void testSelectWhere() throws IOException {
Student param = new Student();
param.setName("李力");
param.setAge(18);
List studentList = studentDao.selectStudentWhere(param);
studentList.forEach( stu -> System.out.println(stu));
}
动态 SQL 之
标签用于实现对于数组与集合的遍历。对其使用,需要注意: collection 表示要遍历的集合类型, list ,array 等。 open、close、separator 为对遍历内容的 SQL 拼接。
语法:
#{item 的值}
(1) 遍历 List<简单类型>
表达式中的 List 使用 list 表示,其大小使用 list.size 表示。
需求:查询学生 id 是 1002,1005,1006 接口方法: List selectStudentForList(List idList);
mapper 文件:
测试方法:
@Test
public void testSelectForList() {
List list = new ArrayList<>();
list.add(1002);
list.add(1005);
list.add(1006);
List studentList = studentDao.selectStudentForList(list);
studentList.forEach( stu -> System.out.println(stu));
}
(2) 遍历 List<对象类型>
接口方法: List selectStudentForList2(List stuList);
mapper 文件:
测试方法:
@Test
public void testSelectForList2() {
List list = new ArrayList<>();
Student s1 = new Student();
s1.setId(1002);
list.add(s1);
s1 = new Student();
s1.setId(1005);
list.add(s1);
List studentList = studentDao.selectStudentForList2(list);
studentList.forEach( stu -> System.out.println(stu));
}
接口方法: List selectStudentSqlFragment(List stuList);
mapper 文件:
select id,name,email,age from student
测试方法:
@Test
public void testSelectSqlFragment() {
List list = new ArrayList<>();
Student s1 = new Student();
s1.setId(1002);
list.add(s1);
s1 = new Student();
s1.setId(1005);
list.add(s1);
List studentList = studentDao.selectStudentSqlFragment(list);
studentList.forEach( stu -> System.out.println(stu));
}
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);
}