数据库分为关系型数据库和非关系型数据库,我们要学的MySQL数据库是关系型数据库。
Mysql的介绍这里不做赘述,网上一大片,这里直接步入正题!!!
SQL语言是一种结构化查询语言(Structured Query Language),结构化查询语言是关系型数据库标准语言,其特点是:简单,灵活,功能强大。
SQL包含6个部分:
- 数据查询语言(DQL): 其语句,也称为“数据检索语句”,用以从表中获得数据,确定数据怎样在应用程序给出。保留字SELECT是DQL(也是所有SQL)用得最多的动词,其他DQL常用的保留字有WHERE,ORDER
BY,GROUP BY和HAVING。这些DQL保留字常与其他类型的SQL语句一起使用。- 数据操作语言(DML): 其语句包括动词INSERT,UPDATE和DELETE。它们分别用于添加,修改和删除表中的行。也称为动作查询语言。
- 事务处理语言(TPL): 它的语句能确保被DML语句影响的表的所有行及时得以更新。TPL语句包括BEGIN TRANSACTION,COMMIT和ROLLBACK。
- 数据控制语言(DCL): 它的语句通过GRANT或REVOKE获得许可,确定单个用户和用户组对数据库对象的访问。某些RDBMS可用GRANT或REVOKE控制对表单个列的访问。
- 数据定义语言(DDL): 其语句包括动词CREATE和DROP。在数据库中创建新表或删除表(CREAT TABLE 或 DROP TABLE);为表加入索引等。DDL包括许多与人数据库目录中获得数据有关的保留字。它也是动作查询的一部分。
- 指针控制语言(CCL): 它的语句,像DECLARE CURSOR,FETCH INTO和UPDATE WHERE CURRENT用于对一个或多个表单独行的操作。
我们使用过程中主要使用数据查询语言(DQL)数据定义语言(DDL)和数据操作语言(DML)
对象:数据库和表
关键字:create
、alter
、drop
、truncate
(删除当前表再新建一个一模一样的表结构)
创建数据库:create database 库名;
删除数据库:drop database 库名;
切换数据库:use 库名;
创建表:create table 表名(
字段名 类型(大小) 关系描述);
查看数据库里存在的表:show tables;
修改表:alter table 表名 约束;
删除表:drop table 表名 ;
查看生成表的sql语句:show create table 表名 ;
查看表结构:desc 表名;
例:
#注意在MySQL数据库里写可以不带";",但是在DOS命令下写必须带。
create database school; #建库
drop database school; #删库
use school; #用库
create table student( #建表
id int(4) primary key auto_increment,
name varchar(20),
socre int(3),
);
show tables;
alter table student rename studentplus; #修改表名 rename
alter table student add password varchar(20); #添加字段 add
alter table student change password pwd varchar(20);
alter table student modify pwd int;
alter table student drop pwd;
drop table student;
show create table student;
desc student;
对象:纪录(行)
关键词:insert?
、update
?、delete
插入:insert into 表名 values(全属性); (插入所有的字段)
insert into 表名(属性1,属性2) values (属性1,属性2); (插入指定的字段)
更新:update 表名 set 属性1 = ‘值’,属性2= ‘值’ where 主键(通常) = 值;
删除:delete from 表名 where 主键(通常) = 值;
注意:
truncate和delete的区别:truncate是删除表,再重新创建这个表。属于DDL,delete是一条一条删除表中的数据,属于DML。
insert into student values(01,'Tonny',90);
insert into student(name,score) values ('Keby',98),('somenne',78);
update student set name = 'Tonn',score = '99' where id = 01;
delete from student where id = 01;
select ... from student where 条件 group by 分组字段 having 条件 order by 排序字段 #最复杂不过如此
执行顺序:from --> where --> group by --> having --> order by
简单条件运算符:> < = != <> >= <=
逻辑运算符:&& || ! and or not (用于连接条件表达式)
模糊查询:like、between and、in、not in、is null
将一列数据作为一个整体,进行纵向的计算。
注意:聚合函数的计算,排除null值。
注意:
例如:
#所有字段查询
select * from student;
#带条件查询
SELECT * FROM `student` WHERE id > 1;
SELECT * FROM `student` WHERE name like '%on%'; #模糊查询
select count(id) from student;
# 综合
SELECT *,AVG(score) FROM `student` WHERE id > 1 GROUP BY id HAVING AVG(score)>20 ORDER BY id DESC;
嵌套查询也叫子查询,是把内层的查询结果作为外层的查询条件,并且可以多层嵌套。
语法格式:
select 字段名列表 from 表名 where 字段名 运算符(select 字段名 from 表名 where 条件) # select * ...就是查询全部
**注意:**外层的where的条件必须和内层的select查询的字段名一样,个数也一样。
语法格式:
select 字段名列表 from 表一,表二 where 条件;
但是这种查询,很容易出现笛卡尔积,为了避免,我们可以将条件尽量细致化。
笛卡尔积
1.什么是笛卡尔积:两个集合的乘积,产生一个 新的集合。表示两个集合所有的可能的组合情况
2.笛卡尔积和关系:笛卡尔积中,去掉没有意义 或不存在的组合,就是关系(规范的二维表)
语法格式:
select 字段名列表 from 表1 连接方式 join 表2 on 表1.字段=表2.字段;
左连接:left join?
( 以左表为基准,匹配右表的所有内容,不够的显示NULL )
右连接:right join?
(以右表为基准,去匹配左表的内容,不够的显示NULL )
联合查询是可合并多个相似的选择查询的结果集。等同于将一个表追加到另一个表,从而实现将两个表的查询组合在一起,使用为此为UNINO或UNION ALL
联合查询:将多个查询的结果合并到一起(纵向合并):字段数不变,多个查询的记录数合并.
select 语句1
union[union 选项]
select 语句2
union|[union 选项]
select 语句n
//all:表示无论重复都输出
//distinct: 去重(整个重复)(默认的)
select *from addr
union all
select *from addr;
主关键字(primary key ):?简称主键,它是表中的一个字段,它的值用于唯一地标识表中的某一条记录。
外关键字(foreign key) :?简称外键,是用于建立或加强两个表数据之间的链接的一列。
如果公共关键字在一个关系中是主关键字,那么这个公共关键字被称为另一个关系的外键
。由此可见,外键表示了两个关系之间的相关联系。
以另一个关系的外键作主关键字的表被称为主表(父表),具有此外键的表被称为主表的从表(子表)。
外键又称作外关键字
。
主键:
定义:唯一标识一条记录,不能有重复的,不允许为空。
作用:用来保证数据完整性
个数:只有一个
外键:
定义:表的外键是另一个表的主键,外键可以有重复的,可以是空值。
作用:用来和其他表建立联系。
个数:一个表可以有许多外键。
# 创建学生表加主键方法一
create table student(
sid char(4) primary key,# 设置主键
sname char(20),
sage int,
ssex char(2)
);
# 创建课程表加主键方法二
create table course(
cid char(4),
cname char(8),
primary key(cid)
);
# 创建成绩表设置外键
create table score(
sid char(4),
cid char(4),
score int(3),
foreign key(sid)references student(sid),
foreign key(cid)references course(cid),
)
alter table 表名 drop primary key;# 删除主键
alter table 表名 add primary key (列名);# 现有列上添加主键
alter table 子表名 add [constraint fk_son]foreign key(子表的外键名称)references 父表名(父表的主键名称); #添加外键约束。fk_sno为外键ID名,若不添加,系统会自动配一个。
alter table 子表名 drop foreign key fk_sno; #删除外键约束。fk_sno为外键ID名, 若不知,可查询建表明细
注:外键一般不在正常工作中使用,一般使用的都是虚拟外键,即有外键功能,不真正设置表外键。?
前言:
在JDK1.0刚开始发布时,并没有跟着发布一个连接数据库的API,那么那时的开发人员,如果想要连接到数据库的话,该怎么做呢?那时的通常做法是使用另一个数据库驱动管理器——ODBC。
ODBC(Open Database Connectivity?开放数据库互连)提供了一种标准的API(应用程序编程接口)方法来访问数据库管理系统(DBMS)。
这些API利用SQL来完成其大部分任务。ODBC本身也提供了对SQL语言的支持,用户可以直接将SQL语句送给ODBC。
ODBC的设计者们努力使它具有最大的独立性和开放性:与具体的编程语言无关,与具体的数据库系统无关,与具体的操作系统无关。
虽然使用ODBC的确是让Java开发人员也可以在应用中连接上数据库了,但由于ODBC毕竟并非是为Java而准备的,ODBC自身是使用C语言开发,标准接口也是对于C语言而言。因此那时的Java开发人员如果需要使用ODBC则不得不在Java程序中添加C语言的ODBC函数调用,使得许多Java自身的特性无法充分发挥,比如平台无关性、面向对象特性等。
因此在众多开发人员的强烈需求下,JDBC 1.0 随JDK1.1发布了。
众所周知,JDBC技术的实施需要六个步骤,我们一个个分析:
首先,我们需要使用配置文件配置数据库连接信息,用properties文件:
jdbc.url=jdbc:mysql://localhost:3309/pbip?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.username=root
jdbc.password=root
在连接数据库之前,首先要加载想要连接的数据库的驱动到JVM(Java虚拟机),
这通过java.lang.Class类的静态方法forName(String className)实现。
代码如下:
/**
* 注册驱动
*/
private void driver(){
try {
Class.forName(properties.getProperty("jdbc.driver"));
}catch (ClassNotFoundException e){
e.printStackTrace();
}
}
?要连接数据库,需要向java.sql.DriverManager请求并获得Connection对象,该对象就代表一个数据库的连接。
?使用DriverManager的getConnectin(String url , String username , String password )方法传入指定的欲连接的数据库的路径、数据库的用户名和密码来获得。
代码如下:
/**
* 建立连接
*/
private Connection conn;
public void conn(){
try {
conn = DriverManager.getConnection(
properties.getProperty("jdbc.url"),
properties.getProperty("jdbc.username"),
properties.getProperty("jdbc.password")
);
}catch (SQLException e){
e.printStackTrace();
}
}
?要执行SQL语句,必须获得java.sql.Statement实例,Statement实例分为以下3种类型:
1、执行静态SQL语句。通常通过Statement实例实现。
2、执行动态SQL语句。通常通过PreparedStatement实例实现。
3、执行数据库存储过程。通常通过CallableStatement实例实现。
具体的实现方式:
private PreparedStatement ps;
/**
* pst对象
* @param sql
* @param values
*/
public void getPst(String sql,Object...values){ //不定参数---数组
try {
ps = conn.prepareStatement(sql);
for (int i = 0;i<values.length;i++){
ps.setObject(i+1,values[i]);
}
}catch (SQLException e){
e.printStackTrace();
}
}
两种情况:
1、执行更新返回的是本次操作影响到的记录数。
2、执行查询返回的结果是一个ResultSet对象。
? ResultSet包含符合SQL语句中条件的所有行,并且它通过一套get方法提供了对这些
行中数据的访问。
? 使用结果集(ResultSet)对象的访问方法获取数据:
//增删改
public void executeUpdate(){
try {
ps.executeUpdate();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
//查
public ResultSet executeQuery(){
try {
rs = ps.executeQuery();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return rs;
}
/**
* 关闭连接
*/
public void close(){
try {
if(rs!=null){
rs.close();
}
if(ps!=null){
ps.close();
}
if(conn!=null){
conn.close();
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
public class JdbcTest {
JdbcUtil jdbcUtil = JdbcUtil.getInstance();
@Test
public void jdbcTest() throws Exception{
jdbcUtil.conn();
String sql = "SELECT * FROM category_tab";
jdbcUtil.getPst(sql);
ResultSet rs = jdbcUtil.executeQuery();
while (rs.next()){
System.out.println(
rs.getInt(1)+"-"+
rs.getString(2)+
rs.getString(3)
);
}
}
}
这是JDBC最为简单的交互数据库的方式,我们一般项目中还需要用到其他配置,一般不再手写sql,而是放在mapper中,后续学习mybatis中的时候就会知道。
DRUID是阿里巴巴开源平台上一个数据库连接池实现,它结合了C3P0、DBCP、PROXOOL等DB池的优点,同时加入了日志监控,可以很好的监控DB池连接和SQL的执行情况,可以说是针对监控而生的DB连接池(据说是目前最好的连接池。
和其它连接池一样DRUID的DataSource类为com.alibaba.druid.pool.DruidDataSource,基本配置参数如下:(主要介绍几个非常常用的)
配置 | 缺省值 | 说明 |
---|---|---|
name | 配置这个属性的意义在于,如果存在多个数据源,监控的时候可以通过名字来区分开来。 如果没有配置,将会生成一个名字,格式是:“DataSource-” + System.identityHashCode(this) | |
jdbcUrl | 连接数据库的url,不同数据库不一样。例如: mysql : jdbc:mysql://10.20.153.104:3306/druid2 oracle : jdbc:oracle:thin:@10.20.149.85:1521:ocnauto | |
username | 连接数据库的用户名 | |
password | 连接数据库的密码。 | |
driverClassName | 根据url自动识别 | 这一项可配可不配,如果不配置druid会根据url自动识别dbType,然后选择相应的driverClassName(建议配置下) |
initialSize | 0 | 初始化时建立物理连接的个数。初始化发生在显示调用init方法,或者第一次getConnection时 |
maxActive | 8 | 最大连接池数量 |
… | … | … |
druid.url=jdbc:mysql://localhost:3306/blog?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
druid.username=root
druid.password=root
druid.driverClassName=com.mysql.cj.jdbc.Driver
import com.alibaba.druid.pool.DruidDataSource;
import org.apache.ibatis.datasource.unpooled.UnpooledDataSourceFactory;
/**
* 使用druid作为数据源
*/
public class MyDateSource extends UnpooledDataSourceFactory {
public MyDateSource(){
this.dataSource= new DruidDataSource();
}
}
<configuration>
<!-- properties文件-->
<properties resource="config/druid.properties"/>
<!--实体类地址-->
<typeAliases>
<package name="com.dyit.mybatis.domain.entity"/>
</typeAliases>
<!--数据库配置-->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC" />
<dataSource type="com.dyit.mybatis.druid.util.MyDateSource">
<property name="driverClassName" value="${druid.driverClassName}" />
<property name="url" value="${druid.url}" />
<property name="username" value="${druid.username}" />
<property name="password" value="${druid.password}" />
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="mapper/Car.mapper.xml" />
</mappers>
</configuration>
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.ibatis.type.Alias;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Alias("Car")
public class Car {
private Integer id;
private String color;
private Double price;
}
package com.dyit.mybatis.druid.mapper;
import com.dyit.mybatis.domain.entity.Car;
import java.util.List;
public interface ICarMapper {
void save(Car car);
void delete(int id);
void update(Car car);
List<Car> findAll();
}
<mapper namespace="com.dyit.mybatis.druid.mapper.ICarMapper" >
<!--表和类的映射关系-->
<resultMap id="CarMapper" type="Car">
<id property="id" column="car_id"/> <!--主键-->
<result property="color" column="car_color"/>
<result property="price" column="car_price"/>
</resultMap>
<insert id="save">
insert INTO car_tab(car_color,car_price) values (#{color},#{price})
</insert>
<delete id="delete">
delete from car_tab where car_id = #{id}
</delete>
<update id="update">
update car_tab set car_color = #{color} where car_id = #{id}
</update>
<select id="findAll" resultMap="CarMapper">
select * from car_tab
</select>
</mapper>
@Test
public void testSelect()throws Exception{
Reader reader = Resources.getResourceAsReader("mybatisConfiguration.xml");
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader);
SqlSession sqlSession = sessionFactory.openSession();
ICarMapper mapper = sqlSession.getMapper(ICarMapper.class);
List<Car> all = mapper.findAll();
sqlSession.commit();
sqlSession.close();
}
这是最简易和原始的方法,我们可以封装SqlSession一系列操作,使用更加方便:
public class MybatisUtil {
private static MybatisUtil instance;
private SqlSessionFactory SessionFactory;
private MybatisUtil(String fileName){
init(fileName);
}
public void init(String fileName){
try{
SessionFactory = new SqlSessionFactoryBuilder().build(
Resources.getResourceAsReader(fileName)
);
}catch (Exception e){
LogUtil.INSTANCE.debug(MybatisUtil.class,e);
}
}
public static MybatisUtil getInstance(String fileName){
if (instance == null){
instance = new MybatisUtil(fileName);
}
return instance;
}
public SqlSession OpenSession(){
SqlSession sqlSession = SessionFactory.openSession();
return sqlSession;
}
public void sessionClose(SqlSession sqlSession){
sqlSession.commit();
sqlSession.close();
}
}
@Test
//插入一辆车
public void testSave2() {
SqlSession sqlSession = m.OpenSession();
ICarMapper mapper = sqlSession.getMapper(ICarMapper.class);
mapper.save2("银白色",4000000.00,"阿斯顿马丁");
m.sessionClose(sqlSession);
}
以上就是他们的全部使用方法,当然,不是唯一的。
DriverManager
- 在java类中创建/关闭连接时会妨碍应用程序性能,而且创建连接到关闭连接的步骤重复发生,浪费资源。
- 不支持连接池。
数据源
- 由于不在类中创建/关闭连接,因此它们可以提高应用程序性能,它们由应用程序服务器管理,并且可以在运行时获取。
- 它提供了一个创建连接池的工具。
- 有助于企业应用程序