Java道经第2卷
心法: mysql是一个关系型数据库,由瑞典mysql-ab公司开发,目前属于oracle旗下产品,在web应用方面是最好的RDBMS应用软件之一:
C/C++/Python/Java/Perl/PHP/Ruby
等。MyISAM
是mysql5之前的默认数据库引擎,最为常用,拥有较高的插入,查询速度,但不支持事务。InnoDB
是mysql5之后的默认数据库引擎,支持ACID事务,支持行级锁定。Structured Query Language
结构化查询语言,是在关系型数据库上执行数据操作,数据检索以及数据维护的标准语言:
武技: 卸载mysql数据库:
sc delete MySQL57
Program Files/Program Files(x86)/Program Data
目录中所有与mysql相关的目录。regedit
打开注册表,删除以下两个目录中的所有mysql相关目录:
HKEY_LOCAL_MACHINE\SYSTEM\ControlSetXXX\Services\Eventlog\Application
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Eventlog\Application
武技: 安装mysql数据库:
mysql-installer-community-5.7.23.0.msi
进入安装界面:接受协议,Next。Choosing a Setup Type
界面:勾选 Server only
,Next。Installation
界面:点击 Execute
执行安装,进度条结束后,Next。
Execute
安装c++环境,Next。Product Configuration
界面:Next。Group Replication
界面:Next。Type and Networking
界面:确认端口号为3306,Next。Accounts and Roles
界面:填两遍登录密码如 root
,Next:
Windows Service
界面:确认服务名为 MySQL57
,Next。Plugins and Extensions
界面:Next。Apply Configuration
界面:点击 Execute
开始安装,安装结束后点击 Finish
回到 Product Configuration
界面。Product Configuration
界面:Next。Installation Complete
界面:点击 Finish
完成安装。C:\Program Files\MySQL\MySQL Server 5.7
%MYSQL_HOME%\bin
mysqladmin --version
.NetFramework4.5.exe
C:\Windows\Temp
,右键属性 -> 安全 -> 添加everyone权限(完全控制)。武技: 使用cmd操作数据库:
net start/stop mysql57
mysql [-D库名] [-hlocalhost] -uroot -p
exit/quit
show databases
create database 库名 [character set utf8mb4];
drop database 库名
use 库名
select version()/database()/user()
:查看当前数据库版本/当前库名/当前用户名。show status/variables
:查看当前数据库状态/配置变量。show tables
:查看当前数据库表,无法看到临时表。武技: 在IDEA中连接mysql服务端:
mysql
,添加jdk8配置。Database选项卡 -> + -> Data Source -> MySQL
mysql-connector-java-8.0.15.jar
:
Driver:MySQL -> Go to Driver -> + -> Custom Jars
Name/Comment/Host/Port/User/Password
jdbc:mysql://localhost:3306?serverTimezone=UTC
Test Connection
进行测试。File -> Settings -> Languages & Frameworks -> SQL Dialects
。Global SQL Dialect/Project SQL Dialect
为 MySQL
。心法: 数据定义语言DDL负责操作数据库的元信息,如表,用户,列,索引等。
心法:
grant all on 库名.* to '账号'@'localhost' identified by '密码' with grant option
:
with grant option
表示该用户可以为其他用户授权。flush privileges
:不刷新可能导致授权失败。select user, host from mysql.user
:IDEA爆红不影响。drop user '账号'@'localhost'
。mysqladmin -u账号 -p旧密码 password 新密码
。ddl.用户.sql
decimal(n, m) 比 double(n, m) 精度高:小数位数最多m位,超出四舍五入,不足补0,且小数位数 + 整数位数 + 小数点占1位,总体位数不能超出n,超出时报错。
心法: mysql的表是所有账号通用的:
create table if not exists 表名 (字段列表) engine=引擎 default charset=字符集 comment '注释'
tinyint(n)/int(n)/decimal(n, m)/char(n)/varchar(n)/datetime
等类型。unsigned
标记为无符号,默认有符号。not null
标记为不能插入空数据,列最好不为null。auto_increment
标记为该列自增,只能用于数字列。comment
指定注释。default
指定默认值,字段尽量给默认值。primary key ()
指定本张表的主键列。create table if not exists user()
show create table 表名
desc 表名/show columns from 表名
show table status like '%表名%'
rename table 表名 to 新表名
drop table 表名
drop table if exists 表名
truncate table 表名
alter table 表名 add 列名 类型
alter table 表名 modify 列名 新类型
alter table 表名 change 字段名 新字段名 字段属性
alter table 表名 drop column 列名
create table 新表名 (select * from 表名)
table
前额外添加 temporary
修饰即可。ddl.表.sql
心法: 约束就是对column添加一些强制校验规则以保证数据的正确性,添加约束前尽量保持表中无数据或者无错误数据:
select * from information_schema.table_constraints where table_name = '表名'
not null
:该列非空,即不能插入空值:
字段 类型 not null
alter table 表名 modify 字段 类型 not null
alter table 表名 modify 字段 类型 null
unique
:该列唯一,即不能插入重复数据:
字段 类型 unique
或字段列表末尾添加 ,unique (字段)
alter table 表名 add [constraint 约束名] unique (字段)
,约束名默认字段名。alter table 表名 drop key/index 约束名
primary key
:该列唯一且非空,一张表只能有一个主键约束列:
字段 类型 primary key
或字段列表末尾添加 primary key (字段)
alter table 表名 add [constraint 约束名] primary key (字段)
,约束名默认primary。alter table 表名 drop primary key
foreign key
:主表的某字段连接从表的主键或唯一约束字段,二者必须同类型同长度:
,foreign key (外键字段) references 从表(从表主键)
alter table 表名 add [constraint 约束名] foreign key (字段) references 从表(主键)
,约束名随机。alter table 表名 drop foreign key 约束名
ddl.约束.sql
心法: 索引底层使用自平衡B-tree结构,可以提高查询效率,但建立索引时需要额外创建一张索引结构表,耗时长,占空间,需要定期维护,且索引会随着表中记录的变化而变化,这意味着每条记录的操作将为此多付出4、5次的磁盘I/O,所以尽量只在经常被查询的字段上建立索引:
show index from 表名
create index 索引名 on 表名 (字段)
,索引名必须指定。drop index 索引名 on 表名
ddl.索引.sql
心法: 视图就是一条查询sql语句的结果集,不占空间,且除了本身外不包含任何数据:
*
作为结果集的查询字段:
create view 视图名 as (结果集)
:创建视图。create or replace view 视图名 as (结果集)
:创建/修改视图。drop view 视图名
ddl.视图.sql
心法: DML负责操作表中的记录,如 insert/delete/update
等语句:
insert into 表名 (字段列表) values (值列表)
update 表名 set 字段名=值, 字段名=值... where 条件
delete from 表名 where 条件
:
dml.数据操作语言.sql
心法: 事务是一组不可分割的业务关系,在SQL中指的是一组不可拆分的DML语句,这组语句要么都成功,要么都失败:
commit/rollback
。Atomicity
:一组事务,要么成功提交,要么失败回滚。Consistency
:一个事务执行之前和执行之后数据库都必须处于一致性状态。Isolation
:并发环境中,不同事务同时操作相同数据时,事务之间互不影响。Durability
:只要事务成功,它对数据库所做的更新就必须永久的保存下来。心法: 事务隔离级别指一个事务对数据库的修改与并行的另一个事务的隔离程度,即当我操作数据库的时候,允许你做什么,当两个并发事务同时访问数据库表相同的行时,不同的数据隔离级别会发生不同的并发现象:
read uncommitted
读未提交:允许读取未提交的数据,此时可能出现脏读现象:
read committed
读已提交:只允许读取已提交的数据,避免脏读,但会发生不可重复读的现象:
repeatable read
重复读:我操作某行数据时不允许别人操作,此时可以避免脏读和不可重复读,但是会发生幻读:
serializable
序列化读:一个事务执行完毕再执行下一个:
repeatable read
:
set transaction isolation level read uncommitted/read committed/repeatable read/serializable
武技: 利用idea导出表:
dump data to file(s)
:
add table definition(sql)
:用于生成表结构。single file
:用于生成一个单独的sql文件。dump data to file(s) -> SQL Insert
,选择路径,导出文件。武技: 利用idea导入表:
Run SQL Script
武技: 利用cmd导出表:
mysqldump -hlocalhost -u帐号 -p 库名 [表1 表2...]> 文件绝对路径.sql
:
-p
后面不能加密码,命令末尾不要添加分号。--default-character-set=utf8mb4
可以指定编码。-d
,代表删除数据,只导出表结构。武技: 利用cmd导入表:
mysql -uroot -p
source 文件绝对路径.sql
心法: DQL负责查询表中的记录,所有select开头的语句全属于DQL语句:
资源/SQL/mysql.sql
select 字段列表 from 查询范围
:
*
,更不建议将 *
和其它字段一起查询,影响查询效率。as
标注,也可省略不写,别名不建议使用中文。as
标注,对表起别名可以提高查询效率。order by 排序字段列表 排序规则
用于对结果集排序:
asc
代表升序,默认可省略,desc
代表降序。order by
是对结果集的排序,所以必须要写在语句最后,也是程序最后一步运行的。order by
不参与任何计算,也不会改变任何一个值。where 条件
用于在查询的过程中,逐条进行条件判断:
where
关键字也只能有一个。and/or/not/<>/!=
等符号,且 and
优先级高于 or
。like
用于在查询的过程中,进行模糊匹配:
%
表示随意个数占位,_
表示只占一位。\
作为转义字符,也可使用 escape
单独指定。in(字段列表)
:字段的值只要出现在这个字段列表中就返回true。not in(字段列表)
:字段的值只要没出现在这个字段列表中就返回true。between x and y
:字段的值只要在x与y之间返回true,包括x也包括y。not between x and y
:字段的值只要不在x与y之间返回true,不包括x也不包括y。case when 条件 then 返回值 end
:相当于java中的switch结构。ifnull(字段, a)
:若字段为null,返回a,否则返回原字段。if(字段, a, b)
:若字段为null,则返回b,否则返回a,可嵌套。if(条件, a, b)
:若条件成立,返回a,否则返回b,可嵌套。dql.基础查询.sql
心法: 利用a查询提供一个临时的结果集供b使用,则可以称a为b的子查询:
any(子查询)
:某些信息符合,结果集中是or的关系,不等式专用。some(子查询)
:某些信息符合,结果集中是or的关系,等式专用。all(子查询)
:全部信息符合,结果集中是and的关系。exists(子查询)/not exists(子查询)
。dql.父子查询.sql
心法: limit m, n
用于进行分页查询,表示从第m条开始(包括m),显示n条:
limit n
,以提升分页效率。dql.分页查询.sql
心法: select * from 表A join 表B on 联合条件
用于联表查询,两表成功相连需要一个联合条件:
inner join
:仅仅显示满足连接条件的信息,inner
可省略。left join
:完整显示左侧信息,即使不满足连接条件。right join
:完整显示右侧信息,即使不满足连接条件。dql.联表查询.sql
心法: group by
可以对1或N个字段进行分组,最终仅返回一列数据,且不会忽略null值:
from
前的字段只建议是 group by
后出现的字段。count(字段)/max(字段)/min(字段)/sum(字段)/avg(字段)
等一起使用:
where
,在分组后进行条件筛选时使用 having
。dql.分组查询.sql
心法: union/union all
用于返回两个结果集的并集,并去重/不去重:
dql.并集查询.sql
心法: regexp
关键字可以进行正则查询:
select * from 表名 where 字段 regexp '正则表达式模板'
dql.正则查询.sql
心法: Java Data Base Connectivity
是java和数据库连接中间件,是sun公司面对各个数据库提供的一组接口,用于使用java代码连接和操作数据库,但前提是java程序中必须添加了对应数据库的驱动包,该jar包由对应的数据库厂商提供:
Structure -> Libraries -> 加号 -> Java
,选择项目中的驱动包,OK至完成。武技: 搭建JDBC,测试连接:
资源/SQL/jdbc.sql
mysql.mysql-connector-java(8.0.15)(runtime)
junit.junit(4.12)(test)
Class.forName("com.mysql.cj.jdbc.Driver")
jdbc:mysql://IP地址:端口号/数据库名?参数列表
:
username/password
:数据库用户名/密码,可不在此指定。serverTimezone=UTC
:指定时区为东8区,mysql8+版本的驱动必须填写。useUnicode=true&characterEncoding=utf8
:使用Unicode字符集的utf8编码实现。autoReconnect=false
:当数据库连接异常中断时,是否自动重新连接,默认false。maxReconnects=5
:当autoReconnect设置为true时,重试连接的次数,默认3次。initialTimeout=3
:当autoReconnect设置为true时,两次重连之间的时间间隔,单位是秒,默认2秒。autoReconnectForPools=true
:是否使用针对数据库连接池的重连策略,默认false。failOverReadOnly=true
:自动重连成功后,连接是否设置为只读,默认true。useSSL=false
:消除控制台的一个红色警告,使用SSL漏洞修复。connectTimeout
:和数据库服务器建立socket连接时的超时,单位是毫秒,0表示永不超时,默认0。socketTimeout
:socket操作(读写)超时,单位是毫秒,0表示永不超时,默认0。DriverManager.getConnection(连接串, 账号, 密码)
connection.isClosed()
connection.close()
jdbc.ConnectTest
武技: 将驱动数据库,获取连接和关闭连接的代码封装到 jdbc.v1.DataSource
类中:
jdbc.DataSourceTest
:
武技: 开发 jdbc.v2.DataSource
并添加连接池功能:
List
类型。synchronized
保护,以免多人获取到同一个实例。jdbc.DataSourceTest
:使用 jdbc.v2.DataSource
测试。武技: 开发 jdbc.v3.DataSource
并将数据源提取到属性文件中,以解耦代码:
Directory
,命名 resources
。Mark Directory as -> Resources Root
。jdbc/db.properties
。package/folder
。K=V
的形式提取到属性文件中。PropertyResourceBundle.getBundle(属性文件地址)
:不要后缀。bundle.getString(String key)
:通过key来获取属性文件中的value值。jdbc.DataSourceTest
:使用 jdbc.v3.DataSource
测试。武技: 开发 jdbc.v4.DataSource
并对数据源使用工厂模式以分离生产者和使用者:
jdbc.DataSourceTest
:使用 jdbc.v4.DataSource
测试。心法: JdbcTemplate类用于发送各种类型的SQL语句,需要注入据源类。
jdbc.v4.JdbcTemplate
武技: 开发执行DDL语句方法并测试:
Connection
连接实例:
dataSource.getConnection()
Statement
媒介实例,用于发送SQL,执行SQL并带回结果:
connection.createStatement()
statement.execute(String sql)
:仅当返回结果的类型是 ResultSet
时为true。jdbc.JdbcTemplateTest.execute()
。武技: 开发执行DML语句方法并测试:
Connection
连接实例:
dataSource.getConnection()
PrepareStatement
媒介实例,该媒介类型支持动态绑定问号:
connection.prepareStatement(String sql)
statement.setObject(int i, Object o)
statement.executeUpdate()
jdbc.JdbcTemplateTest.insert()/update()/delete()
武技: 开发执行DQL语句中的查询多条结果集的方法并测试:
Connection
连接实例:
dataSource.getConnection()
PrepareStatement
媒介实例,该媒介类型支持动态绑定问号:
connection.prepareStatement(String sql)
statement.setObject(int i, Object o)
connection.executeQuery()
List<Map>
结构:
resultSet.getMetaData()
:获取元数据。metaData.getColumnCount()
:获取结果集的总列数。metaData.getColumnName(int i)
:获取第i个列的列名,i从1开始。resultSet.getObject(String columnLabel)
:通过列名获取对应的值。jdbc.JdbcTemplateTest.selectForList()
武技: 开发执行DQL语句中的查询单条结果集的方法并测试:
jdbc.JdbcTemplateTest.queryForMap()
武技: 开发执行DQL语句中的查询结果集数量的方法并测试:
jdbc.JdbcTemplateTest.queryForInt()
心法: int[] batchUpdate(String sql, Object[]... params)
负责批量处理多条相同类型的SQL,需要设置事务保护,返回批量DML操作的影响条目数数组。
武技: 开发执行批处理同类型SQL的方法并测试:
Connection
连接实例:
dataSource.getConnection()
connection
的自动提交属性:
connection.setAutoCommit(false)
:默认true。PrepareStatement
媒介实例,该媒介类型支持动态绑定问号:
connection.prepareStatement(String sql)
statement.setObject(int i, Object o)
pstmt.addBatch(sql)
pstmt.executeBatch()
connection
,手动提交或者回滚本次操作:
connection.commit()
:提交操作。connection.rollback()
:在异常捕捉中进行处理。finally
块中,将自动提交属性还原:
connection.setAutoCommit(true)
:默认为true。jdbc.JdbcTemplateTest.batchUpdateWithSameSql()
心法: int[] batchUpdate(String... sqls)
负责批量处理多条不同类型的SQL,需要设置事务保护,该方法需要传入一个完整SQL的数组,返回批量DML操作的影响条目数数组。
武技: 开发执行批处理不同类型SQL的方法并测试:
Connection
连接实例:
dataSource.getConnection()
connection
的自动提交属性:
connection.setAutoCommit(false)
:默认true。Statement
媒介实例:
connection.createStatement()
stmt.addBatch(sql)
stmt.executeBatch()
connection
,手动提交或者回滚本次操作:
connection.commit()
:提交操作。connection.rollback()
:在异常捕捉中进行处理。finally
块中,将自动提交属性还原:
connection.setAutoCommit(true)
:默认为true。jdbc.JdbcTemplateTest.batchUpdateWithDifferentSql()
武技: 将JDBC项目打包成到Java存档,即JAR文件:
Project Structure -> Artifacts -> 加号 -> JAR -> From Modules with dependicies
Build -> Build Artifacts
build
,完成jar包导出。Object Relation Mapping 对象关系映射旨在通过操作java对象的方式来操作数据库,如将类名映射表名,成员属性名映射表字段名,成员属性类型映射表字段类型,类实例映射表记录等。
心法: mybatis 是一个底层半封装了JDBC的持久层的开源ORM框架,封装了驱动,连接,statement等业务代码,但不封装SQL语句,支持注解或XML方式单独开发SQL语句,其前身是apache的ibatis项目,2010年迁移到了google-code并改名为mybatis,2013年11月迁移到github,其核心对象如下:
SqlSessionFactoryBuilder
:用于创建session工厂,且创建完session工厂后即可销毁:
SqlSessionFactory
:session工厂用于获取一个session会话,可以重复使用,但不该被重复创建,建议以单例模式来管理。SqlSession
:session会话用于获取数据库连接的接口,每个线程都该独享一个session会话,建议设置为局部变量。Executor
:session会话中的SQL执行者,有基本和缓存两种执行器实现。MappedStatement
:SQL执行者中,专门负责SQL组装和结果转换的的SQL管理者:
武技: mybatis基本配通:
资源/SQL/mybatis.sql
org.mybatis.mybatis(3.5.1)
:mybatis核心依赖。mysql.mysql-connector-java(8.0.15)(runtime)
:mysql驱动包,oracle需要ojdbc6.jar依赖。log4j.log4j(1.2.17)
:log for java日志接口包。org.apache.logging.log4j.log4j-core(2.3)
:log for java日志接口包。org.slf4j.slf4j-api(1.7.25)
:simple logging facade for java日志接口包。org.slf4j.slf4j-log4j12(1.7.25)
:slf4j和log4j的整合包,是一个实现。classpath:jdbc/mb-db.properties
:配置驱动,连接串,账号和密码。classpath:log4j.properties
:名称和位置固定。classpath:mybatis/mybatis-core.xml
:
<properties resource=""/>
:从classpath下引入属性文件。<environments>/<environment>
:环境标签,支持配置多环境。<transactionManager type="JDBC">
:配置JDBC事务管理类,此事务支持提交和回滚。<dataSource type="POOLED">
:配置连接池,拥有 driver/url/username/password
等属性。mybatis.MyBatisTest.testBuild()
:
Resources.getResourceAsStream("主配路径")
:返回主配的字节流对象。new SqlSessionFactoryBuilder().build(主配字节流对象)
:创建session工厂。factory.openSession()/openSession(true)
:从session工厂中打开一个具有/没有事务保护的session。session.getConnection().isClosed()
:通过session获取一个连接并测试连接状态。session.close()
:关闭session,可使用 try-with-resource
结构。武技: 封装MyBatisUtil工具类,使用双重检查锁来返回一个单例的session工厂:
mybatis.util.MyBatisUtil
mybatis.MyBatisUtilTest
心法: Mapper配置文件用于配置SQL语句块以及SQL相关配置:
entity.Student
:
<typeAliases>/<package name="">
配置单个/整包别名,别名不区分大小写:
资源/图片/mybatis内置别名.png
mapper.StudentMapper
:相当于MVC结构中的DAO层:
mapper/StudentMapper.xml
:须与Mapper接口同名同包(classpath下都算同包):
<mapper namespace="">
:命名空间必须对应填写Mapper接口全名。<mappers>/<package name="">
整包扫描接口:
File -> Settings -> Editor
:
Inspections -> SQL
:取勾 No data sources configured/SQL dialect detection
Color Scheme -> General -> Code -> Injected language fragment
:取勾 Background
心法: maven项目在打包时仅会将 src/main/java
中的.java文件进行打包,若希望将该包下的.xml文件一并打包,则需要在pom.xml中的 <build>
中进行如下配置:
<!--设置maven打包时将*Mapper文件一并打包-->
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*Mapper.xml</include>
</includes>
</resource>
</resources>
心法: CRUD语句块必须使用id/parameterType/resultType属性分别对应接口方法的方法名/参数类型/返回值或其泛型类型:
@Param()
起别名,实体参数随意。#{}
SQL占位符:用于自动获取实体参数中的指定属性,支持连调,并自动补充单引号:
useGeneratedKeys="true" keyProperty="id"
用于配置添加语句块的主键回注功能。${}
SQL拼接符:用于自动获取实体参数中的指定属性,支持连调,但不补充单引号且存在注入漏洞:
${value}
。flushCache
:每次调用该语句块前是否清空一级缓存以保证结果最新,默认false。useCache
:是否使用二级缓存,默认true。timeout
:语句块超时时间,默认数值由驱动器决定。fetchSize
:结果集条目数达到此阈值时立刻返回一批结果,默认数值由驱动器决定。statementType
:设置SQL媒介类型,可选PREPARED/STATEMENT/CALLABLE,默认PREPARED。<sql id="">
用来封装一个SQL重用代码段。<include refid="">
可以在当前文件中任意位置引入某个SQL重用代码段。mybatis.StudentMapperTest
:获取Mapper接口实例并调用对应方法:
factory.openSession()
session.getMapper(StudentMapper.class)
session.commit()
session.close()
心法: oracle数据库不支持主键自增,可以使用如下方式进行主键回注:
<insert id="insert">
<!--该语句块在主SQL之后执行-->
<!--查询最后一条插入记录的主键并回注到参数实体的int类型的id属性中-->
<selectKey order="AFTER" resultType="int" keyProperty="id">
<!--`select uuid()`:可以返回一个随机字符串-->
SELECT last_insert_id()
</selectKey>
insert into student (id, name, gender, age, info)
values (#{id}, #{name}, #{gender}, #{age}, #{info})
</insert>
心法: DQL语句块支持使用resultMap替代resultType,以指向一个独立的 <resultMap>
:
<resultMap id="" type="">
:使用id唯一标识,使用type设置最终返回值类型。<result column="" property="" javaType="" jdbcType=""/>
:配置普通字段:
<id>
一般用于配置主键字段,无论什么情况下都建议配置以提高效率,全部属性和 <result>
一样。mybatis.StudentMapperTest.list()
心法: 二级缓存需要在主配 <settings>
中使用 <setting name="cacheEnabled" value="true"/>
开启:
<cache>
:用于在SQL配置文件中开启二级缓存,此时所有DQL都会被缓存,所有DML都会更新缓存:
eviction
:设置缓存逐出机制,如默认的LRU(逐出最长时间不被使用的),FIFO(先进先出),SOFT(按GC规则逐出)等。flushInterval
:设置缓存刷新间隔的毫秒数,默认不设置,表示缓存仅仅调用语句时刷新。readOnly
:缓存默认对每个调用者仅返回一个拷贝,效率低但安全,只读缓存对每个调用者都返回缓存本体,效率高但不安全。size
:设置缓存大小,默认1024个,表示缓存最多存储1024个结果集或对象的引用。type
:设置第三方/自定义缓存类全名,以覆盖mybatis的默认缓存机制。<cache-ref namespace="">
:用于引入其他Mapper配置文件的缓存配置。心法: 接口开发时,可使用注解替代SQL语句块以简化代码:
entity.Teacher
。mapper.TeacherMapper
:开发CRUD方法:
@Select/@Insert/@Update/@Delete
用于编写SQL。@Options
用于配置缓存,超时时间,主键回注等功能。@Results/@Result
用于配置SQL高级映射。mapper/TeacherMapper
:命名空间仍要对应接口类全名,但不再写SQL语句块。<mappers>
中整包扫描接口。mybatis.TeacherMapperTest
心法: 动态SQL指的是在SQL块中使用动态标签来完成选择判断,循环等操作:
<script></script>
,其中内容和XML版本一致。entity.User
mapper.UserMapper
mapper/UserMapper.xml
心法: 条件标签配合OGNL表达式用于判断是否允许拼接部分指定的SQL语句:
<if test='OGNL表达式'>
:用于单独条件判断。<where>
:WHERE语句不为空时,生成 WHERE
关键字并删除WHERE语句中第一个 AND/OR
:
<trim prefix="WHERE" prefixOverrides="AND|OR">
<choose>
:用于多选一条件判断:
<when test='OGNL表达式'>
用于设置条件。<otherwise>
用于设置所有条件均不满足时的处理。mybatis.UserMapperTest.selectByIf()
mybatis.UserMapperTest.selectByTrim()
mybatis.UserMapperTest.selectByChoose()
心法: <foreach>
用于循环拼接部分指定的SQL语句:
collection
:值固定为 array/list
或一个值为数组或列表的Map结构的KEY值。item
:设置循环中间变量。open/close
:设置循环开始/结束时拼接的字符串SQL代码。separator
:设置拼接符,自动忽略SQL语句中多余的拼接符。mybatis.UserMapperTest.selectWithArray()
mybatis.UserMapperTest.selectWithList()
mybatis.UserMapperTest.selectWithMap()
心法: <set>
用于控制修改操作时自动生成 SET
关键字并删除最后一个逗号,等效于 <trim prefix="SET" suffixOverrides=",">
mybatis.UserMapperTest.updateBySet()
mybatis.UserMapperTest.updateByTrim()
心法: _parameter
是SQL语句块中的内置参数,可以在OGNL表达式中直接使用:
_parameter
即表示该参数。_parameter.get("param1/别名")
表示第一个参数/对应别名的那个参数。#{param1/别名}
来获取第一个参数/对应别名的那个参数。mybatis.UserMapperTest.selectByParam()
心法: mybatis多表间支持一对一和一对多两种关系:
mybatis.entity.Dept/Emp
:
<settings>
中配置懒加载模式以解决一次主查询附带N次子查询的N+1问题:
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="aggressiveLazyLoading" value="false"/>
心法: 在员工实体中埋一个部门实体属性:
JOIN
联表,返回值使用 <resultMap>
对全部字段进行映射:
<association>
用于映射关联字段,需要配置 javaType/property/jdbcType/column
属性。<association>
内部需要将关联字段对应的实体类的全部属性也映射一遍。mybatis.EmpMapperTest.selectWithDeptByJoin()
<resultMap>
对非同名的字段进行映射:
<association select="工作空间.SQL块id">
调用2步SQL块。mybatis.EmpMapperTest.selectWithDeptBySelect()
@Result(one=@One(""))
替代 <association select="">
。mybatis.EmpMapperTest.selectWithDeptByOne()
心法: 在部门实体中埋一个员工实体列表属性:
JOIN
,返回值使用 <resultMap>
对全部字段进行映射:
<collection>
用于映射关联字段,需要配置 property/jdbcType/column
属性。<collection>
需要配置 ofType
属性以映射实体类关联属性的泛型类型。<collection>
内部需要将关联属性的泛型所对应的实体类的全部属性也映射一遍。mybatis.DeptMapperTest.selectWithEmpsByJoin()
<resultMap>
对非同名的字段进行映射:
EmpMapper.xml
中开发按部门编号查员工的2步SQL块(无需配置接口方法),可直接使用1步SQL块的字段。<collection select="工作空间.id">
调用2步SQL块。mybatis.DeptMapperTest.selectWithEmpsBySelect()
@Result(many=@Many(""))
替代 <collection select="">
配置。@Result(javaType="List.class")
替代 <collection ofType="Emp">
配置。心法: Spring 是2003年兴起的一个轻量级的JAVA开源框架,核心特性是控制反转和面向切面编程,支持xml配置,注解配置和纯java代码方式配置,个人建议基本配置如数据源建议使用可读性更高的xml配置,开发相关如Service注入Dao等建议使用更简单的注解配置。
武技: spring基本配通:
org.springframework.spring-context-support(4.3.14.RELEASE)
spring/app-ioc.xml
:
New -> Xml Configuration File -> Spring Config
以创建spring主配。spring.entity.Cat
<bean id="" name="" class="">
:id设置唯一标识,name设置别名,class设置实体类类全名。spring/CatTest.getBean()
:
new ClassPathXmlApplicationContext("")
:创建spring容器,主配路径从classpath出发。new FileSystemXmlApplicationContext("")
:创建spring容器,主配路径从项目出发。context.getBean()
:通过id/name/类.class的方式获取spring容器中管理的某实例。context.close()
:销毁spring容器以释放资源。心法: Inversion of Control
控制反转:就是将实例化过程和实例生命周期管理都交给spring容器,以解决手动new实例时,侵入性和耦合度双高的问题:
<bean class="静态工厂全名" factory-method="静态工厂方法名"/>
<bean id="实例工厂ID" class="实例工厂全名"/>
<bean factory-bean="实例工厂ID" factory-method="实例工厂方法名"/>
getBean()
时才被new:
<bean class="实体类全名" lazy-init="true/false">
<bean class="实体类全名" scope="singleton/prototype">
<bean class="实体类全名" init-method="初始化方法名" destroy-method="销毁方法名"/>
心法: depend injection
依赖注入是指在IOC产生实例的同时向成员属性,构造器参数等注值。
武技: spring可以在IOC的过程中向bean的成员属性或构造器参数注值:
spring.entity.Dog
:
spring/app-di.xml
:管理实体类并在 <bean>
内部向成员属性和构造器参数注值:
<constructor-arg index="构造器形参角标" value="参数值" type="参数类型全名">
<constructor-arg>
中仍可以使用 <array>/<list>/<set>
等子标签。<property name="" value=""/>
:注入如String,Integer等简单类型属性值。<property name=""> + <array>/<list>/<set> + <value>
:注入数组类/List/Set类型属性值。<property name=""> + <map> + <entry>
:注入Map类型属性值。<property name=""> + <props> + <prop>
:注入Properties类型属性值。<property ref="Cat的bean的id">
:外部注入另一个实体类:
<property>
内部包裹Cat的 <bean>
即可。spring.DogTest.di()
心法: Spring容器初始化时,@Autowired会使用属性的类全名去匹配容器中所有bean的class值,若成功直接实例化(实现类也算成功),若失败再用属性名匹配容器中所有bean的id值,若成功进行实例化,如也失败则直接报错。
武技: 测试@Autowired的自动注入特性:
<context:annotation-config />
spring.service.DogService
:
spring/DogTest.autowired()
:获取业务类实例并调用业务方法。武技: 使用@Component的三个子注解替换所有 <bean>
:
spring.component.mapper.DogMapper
:
@Repository
以被spring管理。spring.component.service.DogService
:
spring.component.service.impl.DogServiceImpl
:
@Service
以被spring管理。spring.component.controller.DogController
:
@Controller
以被spring管理。<context:component-scan base-package="包路径"/>
spring.DogTest.component()
心法: springboot支持使用纯java代码代替xml配置。
武技: 使用纯java代码代替xml配置:
com.jolbox.bonecp-spring(0.8.0.RELEASE)
:第三方bonecp连接池。spring.config.DataSourceConfig
@Configuration
表示该类是一个配置类。@ComponentScan("")
以进行@ComponentScan包扫描。@PropertySource("")
以读取数据源属性文件。@Value("${xxx}")
以读取数据源属性文件中的属性值。@Bean
表示这个方法相当于一个 <bean>
配置。<bean>
的 id
。<bean>
的 class
。spring.DataSourceTest
: 注入配置类中的bean并使用:
new AnnotationConfigApplicationContext(xxx.class)
创建spring容器。武技:
spring.proxy.UserService
并开发CRUD四个接口方法。spring.proxy.UserServiceImpl
并重写四个接口方法。武技: jdk动态代理的客户(聘请代理的对象)必须是某接口的实现类:
spring.proxy.JdkProxyCompany
:
j.l.r.InvocationHandler.invoke()
工作清单。Proxy.newProxyInstance()
以得到一个代理对象。spring.ProxyTest.jdkProxy()
武技: cglib是spring提供的动态代理,可以对任何非final类进行代理:
spring.proxy.CglibProxyCompany
:
o.s.c.p.MethodInterceptor.intercept()
工作清单。new Enhancer().create()
以得到一个代理对象。spring.ProxyTest.cglibProxy()
心法: Aspect Oriented Programming,面向切面编程,是OOP的延续,它通过预编译的方式在运行期,使用动态代理来实现业务代码和切面代码的逻辑分离,降低耦合度,从而提高程序的重用性,主要作用于控制事务的传播。
org.springframework.spring-aspects(4.3.14.RELEASE)
spring.aspect.UserServiceImpl
:
@Component
以被spring容器扫描和管理。int[] selectById(int id)
武技: 使用注解配置AOP:
spring.aspect.UserAspectByAnn
:
@Aspect
表示这是一个切面类。@Component
以被spring容器扫描和管理。@Pointcut("execution([修饰符] 返回类型 [包名].[类名].方法名(形参) [异常])")
指定切点范围。*
表示占1位,..
表示任意占位。@Around("切点方法名()")
指向切点方法名。ProceedingJoinPoint
:
pjp.getArgs()
:获取业务方法的参数列表。pjp.proceed()
:执行业务方法,其返回值就是业务方法的原返回值。Object
类型。<context:component-scan base-package=""/>
包扫描 @Component
。<aop:aspectj-autoproxy />
驱动 @Aspect
。spring.AopTest.aop()
武技: 使用XML配置AOP:
spring.aspect.UserAspectByXml
:
@Aspect
,不开发切点方法,不为环绕通知方法标记 @Around
,其余同上。<context:component-scan base-package=""/>
包扫描 @Component
。<aop:config ></aop:config>
<aop:pointcut id="" expression="execution(PE表达式)"/>
<aop:aspect ref="切面类的<bean>的id">
<aop:around method="通知方法名" pointcut-ref="切点id(不带括号)"/>
spring.AopTest.aop()
武技: 将junit4.12+整合到spring中,可以在单元测试时初始化容器:
org.springframework.spring-test(4.3.14.RELEASE)
spring.SpringJunit4Test
@RunWith(SpringJUnit4ClassRunner.class)
以指定使用整合方案。@ContextConfiguration("classpath:")
以指定XML配置文件路径:
classes=XXXConfig.class
即可。@Autowired
:
武技: 将mybatis与spring整合练习小猪表的CRUD:
资源/SQL/sm.sql
org.mybatis.mybatis(3.5.1)
:mybatis核心包。mysql.mysql-connector-java(8.0.15)(runtime)
:mysql驱动包。com.jolbox.bonecp-spring(0.8.0.RELEASE)
:bonecp连接池包。org.apache.logging.log4j(2.3)
:日志包。log4j.log4j(1.2.17)
:日志包。org.slf4j.slf4j-api(1.7.25)
:日志包。org.slf4j.slf4j-log4j12(1.7.25)(test)
:日志包。org.projectlombok.lombok(1.18.12)(provided)
:lombok工具包。junit.junit(4.12)(test)
:junit测试包。org.springframework.spring-context-support(4.3.14.RELEASE)
:spring核心包。org.springframework.spring-test(4.3.14.RELEASE)
:spring测试包。org.springframework.spring-aspects(4.3.14.RELEASE)
:spring切面包。org.springframework.spring-jdbc(4.3.14.RELEASE)
:spring事务包。org.mybatis.mybatis-spring(1.3.0)
:SM整合包。jdbc/sm-db.properties
:配置驱动,连接串,账号和密码。log4j.properties
:名称固定,位置固定在classpath下。sm.entity.Pig
。sm.mapper.PigMapper
并开发CRUD接口方法。sm/mapper/PigMapper.xml
:
spring/app-sm.xml
:
<context:property-placeholder location=""/>
引入属性文件。o.m.s.m.MapperScannerConfigurer
并注入 basePackage
以配置接口包。c.j.b.BoneCPDataSource
并注入相关数据源信息。o.m.s.SqlSessionFactoryBean
:
typeAliasesPackage
以整包设置别名。dataSource
以引入数据源。mapperLocations
以配置Mapper配置文件,同名同包时可省略此项配置。sm.PigMapperTest
:使用spring-test进行测试:
PigMapper
并调用insert()。此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。