DDL–对库的操作语句
创建库 create database 库名 [character set 码表 collate 字符校对集]
显示所有库 show databases;
删除库 drop database 库名;
修改数据库码表 alter database 库名 character set 码表 collate 字符校对集
使用数据库 use 库名
查看当前使用的库 select database();
显示创建库语句 show create database 库名;
DDL–对表的操作语句
1.创建表
CREATE TABLE table_name
(
field1 datatype 约束/主键约束 auto_increment,
field2 datatype 约束,
field3 datatype 约束
)[character set 字符集 collate 校对规则]
create table t_user(
id int,
name varchar(20),
sal double(4,3),
birthday datetime,
hiredate timestamp
);
varchar最好指定长度
整型一般不指定.
2.查看当前库中有哪些表
show tables;
3.查看表的结构
desc 表名; description
desc t_user;
4.删除表
drop table 表名;
drop table t_user;
5.添加一列
alter table 表名 add 列名 类型;
alter table t_user add photo blob;
6.修改列的类型
alter table 表名 modify 列名 类型;
alter table t_user modify photo varchar(20);
7.修改列的名称
alter table 表名 change 旧列名 新列名 数据类型;
将 photo这一列 改名为 image
alter table t_user change photo image varchar(20);
8.删除某列
alter table 表名 drop 列名;
alter table t_user drop image;
9.修改表的名称
rename table 旧表名 to 新名;
rename table t_user to user;
10.(用的极少)修改表的字符集. (如果创建表时不指定,默认使用数据库的字符集)
alter table 表名 character set 字符集 collate 校对集;
alter table t_user character set utf8 collate utf8_bin;
DML 之增删改查 – 对表数据的增删改
1.为表添加记录
insert into 表名[(列名1,列名2...)] values (值1,值2...);
1>指定要插入那些列
insert into t_user(name,email) values('tom','tom@itcast.cn');
****注意: 数据类型为字符串类型的.需要使用单引号包裹.
2>不指定插入哪些列, 需要指定每一列的值
insert into t_user values(null,'jerry','jerry@itcast.cn');
2.删除记录语句
DELETE FROM 表名 [WHERE 条件];
不加where条件为删除整张表。
3.修改一条记录
update 表名 set 列名1 = 值 , 列名2 = 值 ....[where 条件1,条件2...]
DML 之 对数据的查询语句
语法:
SELECT selection_list /*要查询的列名称*/
FROM table_list /*要查询的表名称*/
WHERE condition /*行条件*/
GROUP BY grouping_columns /*对结果分组*/
HAVING condition /*分组后的行条件*/
ORDER BY sorting_columns /*对结果排序*/
LIMIT offset_start, row_count /*结果限定*/
1.条件查询
就是在查询时给出WHERE子句,在WHERE子句中可以使用如下运算符及关键字:
=、!=、<>、<、<=、>、>=;
BETWEEN...AND...;
BETWEEN后应该填较小的值,AND后填较大的值。
IN(SET)/NOT IN(SET)
IS NULL/IS NOT NULL
null的特性: null不等于null 所以判断是为空或不为空是不应该写 “某值=null”,
应该用 IS NULL 和 IS NOT NULL 运算符。
//---条件连接符
AND; &&
OR; ||
NOT; !
2.模糊查询:
表达式:select 要显示的列名 from 库名 where 筛选的列名 like 表达式
where 字段 like '表达式';
% => 通配 通配任意个字符.
_ => 通配 通配单个字符.
说明: LIKE 条件后 跟模糊查询表达式, "_" 代表一个任意字符
3.去除重复记录
select distinct 要显示的列名 from 库名;
4.给列名添加别名:在列名后加 AS "别名"
例子:select sal*12 + IFNULL(comm,0) as '年收入' from emp;
5.升序降序:
asc 升序
desc 降序
select 要显示的列名 from 库名 order by 列名1 asc,列名2 desc;
6.聚合函数:
聚合函数是用来做纵向运算的函数:
COUNT():统计指定列不为NULL的记录行数;
MAX():计算指定列的最大值,如果指定列是字符串类型,那么使用字符串排序运算;
MIN():计算指定列的最小值,如果指定列是字符串类型,那么使用字符串排序运算;
SUM():计算指定列的数值和,如果指定列类型不是数值类型,那么计算结果为0;
AVG():计算指定列的平均值,如果指定列类型不是数值类型,那么计算结果为0;
7.分组查询
当需要分组查询时需要使用GROUP BY子句,例如查询每个部门的工资和,这说明要使用部分来分组
select deptno,sum(sal) from emp group by 列名;
HAVING子句
4>查询工资总和大于9000的部门编号以及工资和:
select deptno,sum(sal) from emp group by deptno having sum(sal)>9000;
使用having在分组之后加条件.
where和having都可以加条件?
1.where在分组之前加条件.
2.having在分组之后加条件.
where的效率要远远高于having. 分组本身消耗资源非常大.
8.LIMIT用来限定查询结果的起始行,以及总行数。
1>查询5行记录,起始行从0开始
select * from emp limit 0,5;
JDBC
读取数据的模板:
public class helloJDBC {
@Test
//更新数据库
public void fun() throws SQLException{
Connection connection = jdbcUtil.getConnection();
Statement statement = connection.createStatement();
String sql="insert into t_job values (null,'test',2000)";
statement.executeUpdate(sql);
jdbcUtil.close(connection, statement, null);
}
@Test
//查询数据库
public void getData() throws SQLException{
Connection connection = jdbcUtil.getConnection();
Statement statement = connection.createStatement();
String sql = "select * from t_job";
ResultSet res = statement.executeQuery(sql);
while(res.next()){
int id = res.getInt("id");
String name = res.getString("name");
int sal = res.getInt("sal");
System.out.println(id+":"+name+":"+sal);
}
jdbcUtil.close(connection, statement, res);
}
}
1.读取与关闭资源的工具包
public class jdbcUtil {
private static String driver;
private static String url;
private static String user;
private static String password;
static {
try {
// 获取配置文件的信息
Properties pro = new Properties();
//将db.properties放置在src目录下,用加载类资源方式加载配置文件,可以在java和web项目下通用。
InputStream is = jdbcUtil.class.getResourceAsStream("/db.properties");
pro.load(is);
driver = pro.getProperty("classname");
url = pro.getProperty("url");
user = pro.getProperty("user");
password = pro.getProperty("password");
is.close();
// 注册驱动
Class.forName(driver);
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("驱动注册失败");
}
}
// 获得链接
public static Connection getConnection() {
Connection connection = null;
try {
connection = DriverManager.getConnection(url, user, password);
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException("连接失败");
}
return connection;
}
//关闭资源
public static void close(Connection conn, Statement sta, ResultSet res) {
try {
if (res != null) {
res.close();
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
if (sta != null) {
sta.close();
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
if (conn != null) {
conn.close();
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
2.批量处理
public class Demo {
@Test
public void fun() throws SQLException{
Connection conn = jdbcUtil.getConnection();
Statement sta = conn.createStatement();
sta.addBatch("create table t_stu(id int primary key auto_increment,name varchar(20))");
sta.addBatch("insert into t_stu values (null,'jack')");
sta.addBatch("insert into t_stu values (null,'rose')");
sta.executeBatch();
jdbcUtil.close(conn, sta, null);
}
@Test
public void fun2() throws SQLException{
Connection conn = jdbcUtil.getConnection();
String sql = "insert into t_stu values (null,?)";
PreparedStatement ps = conn.prepareStatement(sql);
for(int i = 0;i < 100 ; i++){
ps.setString(1, "stu"+i);
ps.addBatch();
}
ps.executeBatch();
jdbcUtil.close(conn,ps,null);
}
}
3.PrepareStatement解决sql注入问题
public class PrepareStatement {
@Test
public void fun() throws SQLException{
String name="sb or 1=1 --";
int pwd=1;
Connection conn = jdbcUtil.getConnection();
String sql = "select * from t_job where name=? and id=?";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setString(1,name);
ps.setInt(2,pwd);
ResultSet res = ps.executeQuery();
if(res.next()){
System.out.println("登陆成功");
}else{
System.out.println("登陆失败");
}
jdbcUtil.close(conn, null, res);
}
}
4.mysql储存大文本数据
public class demo {
@Test
public void fun() throws Exception{
Connection conn = jdbcUtil.getConnection();
String sql = "insert into mytext values (null,?)";
PreparedStatement ps = conn.prepareStatement(sql);
File file = new File("src/MySQL.txt");
FileReader reader = new FileReader(file);
//大文本设置参数的方法用setCharacterStream
ps.setCharacterStream(1, reader, (int)file.length());
ps.executeUpdate();
jdbcUtil.close(conn, ps, null);
}
}
5.事务回滚(多用在转账)
public void test1(){
Connection conn = jdbcUtil.getConnection();
Savepoint sp = null;
String sql_zs1="update account set money=money-1000 where id=1";
String sql_ls1="update- account set money=money+1000 where id=2";
try {
conn.setAutoCommit(false);
sp = conn.setSavepoint();
PreparedStatement ps1 = conn.prepareStatement(sql_zs1);
ps1.executeUpdate();
PreparedStatement ps2 = conn.prepareStatement(sql_ls1);
ps2.executeUpdate();
} catch (SQLException e) {
try {
conn.rollback(sp);
} catch (SQLException e1) {
e1.printStackTrace();
}
e.printStackTrace();
}finally{
try {
conn.commit();
} catch (SQLException e) {
e.printStackTrace();
}
jdbcUtil.close(conn, null, null);
}
}
6.获得插入数据自增长列
Connection conn = null;
PreparedStatement prst = null;
public void test1(){
String sql="insert into t_stu(name) values(?)";
try {
//获得链接
conn = jdbcUtil.getConnection();
//设置获取自增长值
prst= conn.prepareStatement(sql, PreparedStatement.RETURN_GENERATED_KEYS);
//设置数据
prst.setString(1, "sb");
//执行sql
prst.executeUpdate();
//获取自增长值,这里必须先执行executeUpdate才能获得自增长值
ResultSet rs = prst.getGeneratedKeys();
while(rs.next()){
System.out.println(rs.getInt(1));
}
} catch (Exception e) {
}
}
7. 存储过程的调用以及获取数据
public void test3(){
CallableStatement cs = null;
Connection conn = jdbcUtil.getConnection();
String sql = "CALL pro_findById(?,?)";
try {
cs = conn.prepareCall(sql);
//第一个参数是 IN 类型
cs.setInt(1, 2);
//第二个数据是 OUT 类型,所以需要注册
cs.registerOutParameter(2,java.sql.Types.VARCHAR);
cs.executeQuery();
//获得存储过程传出来的参数,这里传入的参数要和注册时用的一样。
String name = cs.getString(2);
System.out.println(name);
} catch (SQLException e) {
e.printStackTrace();
}finally{
jdbcUtil.close(conn, cs, null);
}
}
连接池技术 C3P0
硬编码方式,使用C3P0连接池管理连接
public void testCode() throws Exception { // 创建连接池核心工具类 ComboPooledDataSource dataSource = new ComboPooledDataSource(); // 设置连接参数:url、驱动、用户密码、初始连接数、最大连接数 dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/jdbc_demo"); dataSource.setDriverClass("com.mysql.jdbc.Driver"); dataSource.setUser("root"); dataSource.setPassword("root"); dataSource.setInitialPoolSize(3); dataSource.setMaxPoolSize(6); dataSource.setMaxIdleTime(1000); // ---> 从连接池对象中,获取连接对象 Connection con = dataSource.getConnection(); // 执行更新 con.prepareStatement("delete from admin where id=7").executeUpdate(); // 关闭 con.close();
}
XML配置方式,使用C3P0连接池管理连接
public void testXML() throws Exception { // 创建c3p0连接池核心工具类 // 自动加载src下c3p0的配置文件【c3p0-config.xml】 ComboPooledDataSource dataSource = new ComboPooledDataSource();// 使用默认的配置 PreparedStatement pstmt = null; // 获取连接 Connection con = dataSource.getConnection(); for (int i=1; i<11;i++){ String sql = "insert into employee(empName,dept_id) values(?,?)"; // 执行更新 pstmt = con.prepareStatement(sql); pstmt.setString(1, "Rose" + i); pstmt.setInt(2, 1); pstmt.executeUpdate(); } pstmt.close(); // 关闭 con.close();
}
dbUtil
DbUtils组件
commons-dbutils 是 Apache 组织提供的一个开源 JDBC工具类库,它是对JDBC的简单封装,学习成本极低,并且使用dbutils能极大简化jdbc编码的工作量,同时也不会影响程序的性能。因此dbutils成为很多不喜欢hibernate的公司的首选。
DbUtils组件,
1. 简化jdbc操作
2. 下载组件,引入jar文件 : commons-dbutils-1.6.jar
实例
|-- DbUtils 关闭资源、加载驱动
|-- QueryRunner 组件的核心工具类:定义了所有的与数据库操作的方法(查询、更新)
Int update(Connection conn, String sql, Object param); 执行更新带一个占位符的sql
Int update(Connection conn, String sql, Object… param); 执行更新带多个占位符的sql
Int[] batch(Connection conn, String sql, Object[][] params) 批处理
T query(Connection conn ,String sql, ResultSetHandler<T> rsh, Object... params) 查询方法
Int update( String sql, Object param);
Int update( String sql, Object… param);
Int[] batch( String sql, Object[][] params)
注意: 如果调用DbUtils组件的操作数据库方法,没有传入连接对象,那么在实例化QueryRunner对象的时候需要传入数据源对象: QueryRunner qr = new QueryRunner(ds);
DbUtils提供的封装结果的一些对象:
1) BeanHandler: 查询返回单个对象
2) BeanListHandler: 查询返回list集合,集合元素是指定的对象
3) ArrayHandler, 查询返回结果记录的第一行,封装对对象数组, 即返回:Object[]
4) ArrayListHandler, 把查询的每一行都封装为对象数组,再添加到list集合中
5) ScalarHandler 查询返回结果记录的第一行的第一列 (在聚合函数统计的时候用)
6) MapHandler 查询返回结果的第一条记录封装为map
使用DbUtil 优化
QueryRunner qr = new QueryRunner();
public void addContact(Contact contact) {
Connection conn = null;
String sql = "INSERT INTO contact VALUES(?,?,?,?,?,?,?)";
try {
conn = JdbcUtil.getConnection();
qr.update(conn, sql,
contact.getId(),
contact.getName(),
contact.getAge(),
contact.getGender(),
contact.getTel(),
contact.getQq(),
contact.getEmail());
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}finally{
JdbcUtil.close(conn, null, null);
}
}
public List<Contact> findAllContact() {
Connection conn = null;
String sql = "SELECT * FROM contact";
try {
conn = JdbcUtil.getConnection();
List<Contact> list = qr.query(conn, sql, new BeanListHandler<Contact>(Contact.class));
return list;
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}finally{
JdbcUtil.close(conn, null, null);
}
}
使用DbUitl 和 C3p0 连接池 快捷方便 实现 Sql语句 处理 (一般都用这个,谁还写连接,直接写 QureyRunner的query和undate方法)
不过使用c3p0 记得在 src下引入 c3p0-config.xml 文件 ,配置数据库连接池信息
以后JdbcUtil用这个,
public class JdbcUtils {
/**
* 1. 初始化C3P0连接池
*/
private static DataSource dataSource;
static {
dataSource = new ComboPooledDataSource();
}
/**
* 2. 创建DbUtils核心工具类对象
*/
public static QueryRunner getQueryRuner(){
// 创建QueryRunner对象,传入连接池对象
// 在创建QueryRunner对象的时候,如果传入了数据源对象;
// 那么在使用QueryRunner对象方法的时候,就不需要传入连接对象;
// 会自动从数据源中获取连接(不用关闭连接)
return new QueryRunner(dataSource);
}
}