8、使用注解开发
8.1 面向接口编程
真正的开发中,很多时候会选择面向接口编程
根本原因:解耦,可拓展,提高复用,分层开发中,上层不用管具体的实现,大家都遵守共同的标准,使开发变得更容易,规范性更好
–在一个面向对象的系统中,系统的各种功能是由许许多多的不同对象协作完成的。在这种情况下,各个对象内部是如何实现自己的,对系统设计人员来说就不那么重要了;
–而各个对象间的协作关系则成为系统设计的关键,小到不同类之间的通信,大到各模块之间的交互,在系统设计之初都是要着重考虑的,这也是系统设计的主要工作内容。面向接口编程就是指按照这种思想编程.
关于接口的理解
- 接口从更深层次的理解,应是定义(规范、约束)与实现(名实分离的原则)的分离
- 接口的本身反映了系统设计人员对系统的抽象理解
- 接口应有俩类
- 第一类是对一个个体的抽象,它可对应为一个抽象体(abstract class)
- 第二类是对一个个体某方面的抽象,即可形成一个抽象面(interface)
- 一个个体可能有多个抽象面,抽象体与抽象面是有区别的。
三个面向区别
- 面向对象是指,我们考虑问题时,以对象为单位,考虑它的属性及方法
- 面向过程是指,我们考虑问题时,以一个具体的流程(事务过程)为单位,考虑它的实现。
- 接口设计与非接口设计时针对复用技术而言的,与面向对象(过程)不是一个问题,更多的体现是在系统整体的架构
8.2 使用注解开发
1、注解在接口上实现
@Select("select * from user")
List<User> getUsers();
2、需要在核心配置文件绑定接口
<!--绑定接口-->
<mappers>
<mapper class="com.nine.dao.UserMapper"/>
</mappers>
3、测试
本质:反射机制实现
底层:动态代理!
Mybatis详细执行流程
8.3 CRUD
我们可以在工具类创建的时候实现自动提交
@Param注解的作用是给参数命名
参数命名后就能根据名字得到参数值,正确的将参数传入sql语句中(一般通过#{}的方式,${}会有sql注入的问题)。
编写接口,增加注解
package com.nine.dao;
import com.nine.pojo.User;
import org.apache.ibatis.annotations.*;
import java.util.List;
import java.util.Map;
/**
* @Author 韦浪
* @create 2020/10/29 12:43
*/
public interface UserMapper {
@Select("select * from user")
List<User> getUsers();
@Select("select * from user where id = #{id}")
User getUserById(@Param("id") int id);
@Insert("insert into user(id,name,pwd) values (#{id},#{name},#{password})")
int addUser(User user);
@Update("update user set name=#{name},pwd=#{password} where id = #{id}")
int updateUser(User user);
@Delete("delete from user where id = #{id}")
int deleteUser(@Param("id") int id);
}
对接口进行绑定
<!--绑定接口-->
<mappers>
<mapper class="com.nine.dao.UserMapper"/>
</mappers>
测试类
注意:【我们必须要讲接口注册绑定到我们的核心配置文件中!】
关于@Param()注解
- 基本类型的参数或者String类型,需要加下
- 引用类型不需要加
- 如果只有一个基本类型的话,可以忽略,但是建议大家都加上!
- 我们在SQL中引用的就是我们这里的@Param()中设定的属性名
#{} 和 ${}的区别
一般采用#{}能够很大程序能防止SQl注入
9、Lombok
Project Lombok is a java library that automatically plugs into your editor and build tools, spicing up your java.
Never write another getter or equals method again, with one annotation your class has a fully featured builder, Automate your logging variables, and much more.
- java library
- plugs
- build tools
- with one annotation your class
使用步骤:
1、在IDEA中安装Lombok插件!
2、在项目中导入lombok的jar包
3、在实体类上加注解即可
@Getter and @Setter
@FieldNameConstants
@ToString
@EqualsAndHashCode
@AllArgsConstructor, @RequiredArgsConstructor and @NoArgsConstructor
@Log, @Log4j, @Log4j2, @Slf4j, @XSlf4j, @CommonsLog, @JBossLog, @Flogger, @CustomLog
@Data
@Builder
@SuperBuilder
@Singular
@Delegate
@Value
@Accessors
@Wither
@With
@SneakyThrows
@val
@var
experimental @var
@UtilityClass
Lombok config system
Code inspections
Refactoring actions (lombok and delombok
@Data:无参构造、get、set、tostring、hashcode、equals
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode
@ToString
@Getter
10、多对一处理
- 多个学生,对应一个老师
- 对于学生这边而言,关联。。 多个学生,关联一个老师(多对一)
- 对于老师而言,集合,一个老师,有很多个学生(一对多)
CREATE TABLE `teacher` (
`id` INT(10) NOT NULL,
`name` VARCHAR(30) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8
INSERT INTO teacher(`id`,`name`) VALUES (1, '秦老师');
CREATE TABLE `student` (
`id` INT(10) NOT NULL,
`name` VARCHAR(30) DEFAULT NULL,
`tid` INT(10) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `fktid` (`tid`),
CONSTRAINT `fktid` FOREIGN KEY (`tid`) REFERENCES `teacher` (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('1', '小明', '1');
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('2', '小红', '1');
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('3', '小张', '1');
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('4', '小李', '1');
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('5', '小王', '1');
测试环境搭建
1、导入lombok
2、新建实体类Teacher、Student
3、建立Mapper接口
4、建立Mapper.xml文件
5、在核心配置文件中绑定注册我们的Mapper接口或者文件
6、测试查询是否成功
按照查询嵌套处理
<?xml version="1.0" encoding="UTF8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--configuration核心配置文件-->
<mapper namespace="com.nine.dao.StudentMapper">
<!--
思路:
1、查询所有学生的信息
2、根据查询出来的学生的tid,寻找对应的老师,子查询
-->
<select id="getStudent" resultMap="StudentTeacher">
select * from student
</select>
<resultMap id="StudentTeacher" type="Student">
<result property="id" column="id"/>
<result property="name" column="name"/>
<!--复杂的属性我们需要单独处理 对象:association 集合:collection-->
<association property="teacher" column="tid" javaType="Teacher" select="getTeacher"/>
</resultMap>
<select id="getTeacher" resultType="Teacher">
select * from teacher where id = #{id}
</select>
</mapper>
按照结果嵌套处理
<!--按照结果嵌套处理-->
<select id="getStudent2" resultMap="StudentTeacher2">
select s.id sid,s.name sname,t.name tname
from student s,teacher t
where s.tid = t.id;
</select>
<resultMap id="StudentTeacher2" type="Student">
<result property="id" column="sid"/>
<result property="name" column="sname"/>
<association property="teacher" javaType="Teacher">
<result property="name" column="tname"/>
</association>
</resultMap>
@Test
public void test2(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
List<Student> studentList2 = mapper.getStudent2();
for (Student student : studentList2) {
System.out.println(student);
}
sqlSession.close();
}
Student(id=1, name=小明, teacher=Teacher(id=0, name=秦老师))
Student(id=2, name=小红, teacher=Teacher(id=0, name=秦老师))
Student(id=3, name=小张, teacher=Teacher(id=0, name=秦老师))
Student(id=4, name=小李, teacher=Teacher(id=0, name=秦老师))
Student(id=5, name=小王, teacher=Teacher(id=0, name=秦老师))
回归Mysql多对一查询方式:
- 子查询
- 多表查询
11、一对多处理
例:一个老师拥有多个学生
对老师而言,就是一对多的关联!
实体类
学生
@Data
public class Student {
private int id ;
private String name;
private int tid;
}
老师
@Data
public class Teacher {
private int id;
private String name;
//一个老师拥有多个学生
private List<Student> students;
}
按照结果嵌套处理:
<!--按结果嵌套查询-->
<select id="getTeacher" resultMap="TeacherStudent">
select s.id sid,s.name sname,t.name tname,t.id tid
from student s,teacher t
where s.tid = t.id
and t.id = #{tid};
</select>
<resultMap id="TeacherStudent" type="Teacher">
<result property="id" column="tid"/>
<result property="name" column="tname"/>
<!--复杂的属性我们需要单独处理 对象:association 集合:collection
javaType=""指定的属性类型!
集合中的泛型信息,我们使用ofType获取
-->
<collection property="students" ofType="Student">
<result property="id" column="sid"/>
<result property="name" column="sname"/>
<result property="tid" column="tid"/>
</collection>
</resultMap>
小结
1、关联-association
2、集合-collection
3、javaType & ofType
1、javaType是用来指定实体类中属性的类型
2、ofType 用来指定映射到List或者集合中的pojo类型,泛型中的约束类型!
注意点:
- 保证SQL的可读性,尽量保证通俗易懂
- 注意一对多和多对一中,属性名和字段的问题!
- 如果问题不好排查错误,可以使用日志,建议使用Log4j