1 Sql语句 增删改查
1.1 建表
-- cmd展示数据库
show databases ;
-- cmd登录数据库
mysql localhost -u root -p
-- auto_increment 自动增长,每添加一个表项id自动增1
-- char定长字符串 0-255,不足十个字符按十个字符算, varchar变长字符串:有几个字符给几个的空间
-- varchar(20)最多20个字符的空间,char(11)直接给11个字符空间
create table tbuser(
id int primary key auto_increment comment 'ID 唯一标识',
username varchar(20) not null unique comment '用户名',
name varchar(10) not null comment '姓名',
age int comment '年龄',
gender char(1) default '男' comment '性别'
)comment '用户表';
图形化界面创建:
price decimal(8.2)//最多8位,2位小数
image varchar(300) 图像存储的是路径
# 查看指定表结构
desc tbuser;
# 查看建表语句
show create table tbuser;
1.2 修改删除
alter table tbuser add height varchar(11) comment '身高';
alter table tbuser modify height varchar(13) comment '身高';
# 修改height名字为height1
alter table tbuser change height height1 varchar(13) comment '身高';
alter table tbuser drop column height1;
rename table tbuser to tb_user;
# 删除表
drop table if exists tbuser;
insert into tb_user (id,username,name) values (2,"haha","haha"),(3,"haha2","haha2");
# 全部字段添加数据
insert into tb_user values xxx
update tb_user set username="bus" where id=1;
delete from tb_user where id=1;
#删除表中所有数据
delete from tb_user;
1.3 查询
1.3.1 基本查询
# distinct表示不要重复
select distinct job from tb_emp;
# 查询并起别名
select name as 姓名 from tb_emp;
1.3.2 条件查询
select * from tb_emp where id=5;
select * from tb_emp where id is null;
# 查询id不等于5的信息
select * from tb_emp where id !=5;
# 与上一个同义
select * from tb_emp where id <>5;
select * from tb_emp where id >5 and id<10;
select * from tb_emp where id between 5 and 10;
# id在5-10范围而且要gender=2
select * from tb_emp where id between 5 and 10 and gender=2;
select * from tb_emp where id =5 or id=6;
# 与上一个同义
select * from tb_emp where id in (5,6);
# _表示一个字符
select * from tb_emp where name like '__';
# %表示任意字符
select * from tb_emp where name like '张%';
1.3.3 聚合函数
# 统计,不对null值运算
select count(id) from tb_emp;
select count(*) from tb_emp;
select min(entrydate) from tb_emp;
select max(entrydate) from tb_emp;
select avg(entrydate) from tb_emp;
select sum(entrydate) from tb_emp;
1.3.4 分组查询
# 根据性别分组,统计各自数量
select gender,count(*) from tb_emp group by gender;
# 查询entrydate<='2015-1-1',并职位分组,获取员工数量>=2的职位
# where是分组之前过滤,之后不能使用聚合函数,having是分组之后的过滤
select job,count(*) from tb_emp where entrydate<='2015-1-1' group by job having count(*)>=2;
1.3.5 排序查询
# 排序,asc升序默认,desc默认,此句asc在前
select * from tb_emp order by entrydate asc,id desc ;
1.3.6 分页查询
起始索引0可以省略
2 多表设计
外键约束
关系:一对一、一对多、多对多;多对多关系,需要一张中间表;一对多在多的一方添加一个外键
外键约束分为:物理外键(容易死锁)、逻辑外键(service层)
要把外键表相关信息删除之后,才能删除关联信息
create table class(id int primary key auto_increment);
//class_id是外键字段名
create table student(id int primary key auto_increment,class_id int,constraint foreign key(class_id) references class(id));
create table teacher(id int primary key);
create table student (id int primary key);
create table teacher_student(teacher_id int,student_id int,constraint foreign key(teacher_id) references teacher(id),constraint foreign key(student_id) references student(id));
3 多表查询
笛卡尔积:两个集合所有的组合情况; 需要设置条件消除无效笛卡尔积,比如where x.id=y.id
3.1 内连接
集合A,B交集的数据
-- 查询员工的姓名,部门(内连接实现)
select tb_emp.name ,tb_dept.name from tb_dept,tb_emp where tb_emp.dept_id=tb_dept.id;
-- 起别名
select e1.name ,b.name from tb_dept e1 ,tb_emp b where b.dept_id=e1.id;
# 显式内连接
select tb_emp.name ,tb_dept.name from tb_emp inner join tb_dept on tb_emp.dept_id=tb_dept.id;
3.2 外连接
查询集合A或B的所有
# 左外连接
select tb_emp.name ,tb_dept.name from tb_emp left join tb_dept on tb_emp.dept_id=tb_dept.id;
# 右外连接
select tb_emp.name ,tb_dept.name from tb_emp right join tb_dept on tb_emp.dept_id=tb_dept.id;
3.3 子查询
嵌套select语句
1.标量子查询
返回单个值
select * from tb_emp where dept_id=(select id from tb_dept where name='张三丰');
2.列子查询
返回一列
# 查询教研部与咨询部所有员工信息
select * from tb_emp where dept_id in (select id from tb_dept where name='教研部' or name='咨询部')
3.行子查询
返回一行
# 查询与金庸的出生日期以及职位都相同的信息
select * from tb_emp where (entrydate,job) =(select entrydate,job from tb_emp where name='金庸')
4.列子查询
返回多行多列
# 查询入职日期为2000-01-01的员工信息以及部门名称
select * from (select * from tb_emp where entrydate>'2000-01-01') e ,tb_dept d where e.dept_id=d.id
4 事务
# 事务:一组操作的集合,要么同时成功,要么同时失败
# 开启事务
start transaction ;
# 删除部门
delete from tb_dept where id=3;
#删除员工
delete from tb_emp where dept_id=3;
# 提交事务,如果上面两行都成功使用
commit ;
# 回滚事务,只有上面两行有一个失败就使用,相对于撤销原操作
rollback ;
5 索引
默认底层结构:B+树
IBD文件:存放数据库的数据与索引
create index inname on tb_emp(name);
show index from tb_emp;
# 删除索引
drop index inname on tb_emp;
6 MyBatis
6.1 配置
MyBatis是dao层(持久层)框架
数据库连接池:容器,管理数据库连接
接口:DataSource
产品:Druid、Hikari
<!-- druyid连接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.8</version>
</dependency>
lombok :注解提供相应方法
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
//@Getter
//@Setter
//@ToString
//@EqualsAndHashCode
@Data//相当于以上四个
@NoArgsConstructor//无参构造
@AllArgsConstructor//全参构造
public class user {}
#配置mybatis日志,指定输出到控制台
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
6.2 删除
UserMapper接口
@Mapper
public interface UserMapper {
// #{id}表示占位符
//如果有返回值,成功返回值为1
@Delete("delete from emp where id=#{id}")
public void list(Integer id);
}
MybatisApplicationTests测试启动类
@SpringBootTest
class MybatisApplicationTests {
@Autowired
private UserMapper userMapper;
@Test
public void testUser(){
userMapper.list(10);
}
}
成功!
'#'表示预编译Sql:性能更高、更安全
性能更高:将编译后的结果缓存起来
安全原因:防止SQL注入
SQL注入是web应用程序在接收相关数据参数时未做好过滤,将其直接带入到数据库中查询,导致攻击者可以拼接执行构造的SQL语句
//$是拼接,后台直接是delete from emp where id=id
@Delete("delete from emp where id=${id}")
public void list(Integer id);
6.3 插入
UserMapper接口
@Mapper
public interface UserMapper {
//获取返回的主键
@Options(keyProperty = "id",useGeneratedKeys = true)
//更新是@Update
@Insert("insert into dept (id, name,create_name,update_name) values (#{id},#{name},#{create_name},#{update_name})")
public void insert(user u);
}
MybatisApplicationTests
@Test
public void testUser(){
user u=new user();
u.setAge((short) 18);
u.setGender((short) 1);
u.setName("123");
u.setPhone(String.valueOf(12321));
u.setId(12);
userMapper.insert(u);
System.out.println(u.getId());
}
}
6.3 查询
UserMapper接口
@Select("select * from dept where id=#{id}")
public user select(Integer id);
MybatisApplicationTests
@SpringBootTest
class MybatisApplicationTests {
@Autowired
private UserMapper userMapper;
@Test
public void testUser(){
user u=userMapper.select(2);
System.out.println(u);
}
}
null原因:数据封装
实体类属性名与数据库查询返回的字段一致,mybatis会自动封装,不一致则不会
解决方法一:起别名
@Select("select id, name, create_time createName, update_time updateName from dept where id=#{id}")
public user select(Integer id);
解决方法二:@Results
@Results({
@Result(column="create_time",property="createName"),
@Result(column="update_time",property="updateName"),
})
@Select("select * from dept where id=#{id}")
public user select(Integer id);
}
解决方法三:
application.properties
#开启mybatis驼峰命名自动映射开关
mybatis.configuration.map-underscore-to-camel-case=true
6.4 XML
同包同名:XML映射文件名与Mapper接口名称一致
xml的sql语句的id要与mapper接口方法名、返回类型一致
//namespace是接口copy->copy reference
<mapper namespace="com.tencent.mybatis.mapper.UserMapper">
</mapper>
xml要导入的文件:
<?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">
UserMapper接口
动态SQL-if
<mapper namespace="com.tencent.mybatis.mapper.UserMapper">
<select id="select" resultType="com.tencent.mybatis.polo.user">
select * from dept
-- 如果if不成立,where不会创建,还会自动除去条件前面的and或者or
-- 如果where改为set,那么set会自动除去条件后面的‘,’
<where>
<if test="name!=null">
name like concat('%',#{name},'%');
</if>
<if test="id!=null">
-- 没有<where>标签,name不成立id成立会报错
and id =#{id}
</if>
</where>
</select>
</mapper>
删除
UserMapper接口
@Mapper
public interface UserMapper {
public void deleteId(List<Integer> ids);
}
接口的ids要与MybatisApplicationTests的ids对应,不然报错
<mapper namespace="com.tencent.mybatis.mapper.UserMapper">
<!-- collection遍历的集合,item是遍历出的元素,separator分隔符-->
<delete id="deleteId">
delete from dept where id in
<foreach collection="ids" item="id" separator="," open="(" close=")">
#{id}
</foreach>
</delete>
</mapper>
MybatisApplicationTests
@SpringBootTest
class MybatisApplicationTests {
@Autowired
private UserMapper userMapper;
@Test
public void testUser(){
List<Integer> ids= Arrays.asList(1,2,3);
userMapper.deleteId(ids);
}
}
6.5 解决Could not autowire. No beans of ‘UserMapper‘ type found问题
文件夹放入与启动项文件同级
成功!