内容
B/S技术体系
html:浏览器骨架 超文本标记语言
css:炫酷的页面 静态显示
JavaScript:行为
jQuery:是一个库,封装了js;也是一个前端框架(其它前端框架:vue易、react难、ajs国内不怎么用了)
tomcat:服务器
xml:可扩展标记语言 写配置文件
servlet:tomcat组件——获取请求、处理请求、响应请求
jsp:响应请求的页面显示 动态显示 本质也是servlet
EL:替代jsp表达式
JSTL:替代jsp脚本中断
cookie:识别是否来自同一个浏览器 客户端
session:识别是否来自同一个浏览器 服务器端
filter:tomcat组件
listener:tomcat组件
ajax:实现异步请求,部分改变
json:数据交换格式,传输数据用的
1.jdbc概述
1.1 数据持久化:断电之后数据不会消失
1.2 Java中的数据存储技术:
1.3 JDBC提供统一接口,实现依赖具体的数据库,由数据库厂商提高实现类
1.4 JDBC编程步骤
2.数据库连接
2.1 驱动Driver获得连接对象
方式一:
Driver driver=new com.mysql.jdbc.Driver();//实现类of java.sql.Driver
String url="jdbc:mysql://localhost:3306/test";//jdbc url:协议:子协议(标识数据库驱动程序)://子名称(标识数据库=主机名:端口号/数据库名称)
Properties prop=new Properties();
prop.setProperty("user","root");
prop.setProperty("password","123");
Connection connection=driver.connect(url,prop);
方式二:
//不希望出现第三方com.sql.jdbc.Driver,反射来解决
Class clazz=Class.forName("com.mysql.jdbc.Driver");
Driver driver=(Driver)clazz.newInstance();
...//与方式一一样获取connection
方式三:
String url="jdbc:mysql://localhost:3306/test";
String user="root";
String password="123";
Class clazz=Class.forName("com.mysql.jdbc.Driver");
Driver driver=(Driver)clazz.newInstance();
DriverManager.register(driver);
Connection conn=DriverManager.getConnection(url,user,password);
方式四:
String url="jdbc:mysql://localhost:3306/test";
String user="root";
String password="123";
//省略掉的方式三中的部分是因为mysql的Driver中已在静态代码块中以实现
Class.forName("com.mysql.jdbc.Driver");
Connection conn=DriverManager.getConnection(url,user,password);
方式五(推荐):
jdbc.properties
diver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/test
user=root
password=123
//读取配置文件的方式jdbc.properties
InputStream resource=当前类.class.getClassLoader().getResourceAsStream("jdbc.properties");
Properties prop=new Properties();
prop.load(resource);
String driver=prop.getProperty("driver");
String url=prop.getProperty("url");
String user=prop.getProperty("user");
String password=prop.getProperty("password");
Class.forName(driver);
Connection conn=DriverManager.getConnection(url,user,password);
方式五的优势:换数据库只需要改配置文件即可,不需要改代码,解耦数据与代码
2.2 Statement
通过conn.createStatement()来获取
该对象调用 int executeUpdate(String sql)/ResultSet executeQuery(String sql)来执行sql语句
其弊端:
PreparedStatement可以避免Statement弊端,此外其具有更高的效率,因为预编译所以对于只是参数不同的同一条sql只编译一次,而Statement会编译n次
3.使用PreparedStatement实现crud
PreparedStatement对象通过conn.prepareStatement()来获取
//准备sql
try{
Connection conn=JDBCUtils.getConnection();//使用工具类,工具类具体内容在下面
//增
String sql="insert into user(id,name,birth) values(?,?,?)";//?为占位符,占位符从1开始编号
PreparedStatement ps=conn.prepareStatement(sql);
ps.setString(1,"202001");
ps.setString(2,"煤气罐");
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
java.util.Date date=sdf.parse("2008-02-02");
ps.setDate(3,date);
//执行sql
ps.execute(sql);
//改
String sql="update user set name=? where id=?";
PreparedStatement ps=conn.preparsStatment(sql);
ps.setObject(1,"tom");
ps.setInt(2,11);
ps.execute();
//通用增删改
String sql="";
JDBCUtils.execute(conn,sql,参数们);
//查
String sql="select * from user";
PreparedStatment ps=conn.prepareStatement(sql);
ResultSet set=ps.executeQuery();
while(set.next()){
User u=new User();//表对应的pojo
u.setId(set.getString(1));
u.setString(set.getString(2));
u.setBirth(set.getDate(3));
System.out.println(u.toString());
}
//通用查
String sql="";
JDBCUtils.executeQuery(conn,sql,参数们);
}catch(Exception e){
e.printStackTrace();
}finally{
//关闭资源
BCUtils.close(conn,ps);
}
ORM思想 object relational mapping
JDBCUtils
!!这里举例的查询通用方法只是显示,可以优化成返回结果集,然后再编写一个处理结果集的工具类
public class JDBCUtils{
private Connection conn=null;
static{
InputStream resource=ClassLoader.getSystemClassLoader().getResourceAsStream("jdbc.properties");
Properties prop=new Properties();
prop.load(resource);
String driver=prop.getProperty("driver");
String url=prop.getProperty("url");
String user=prop.getProperty("user");
String password=prop.getProperty("password");
Class.forName(driver);
conn=DriverManager.getConnection(url,user,password);
}
//获取连接
public static Connection getConnection() throws Exception{
return conn;
}
//关闭资源
public static void close(Connection conn, Statement s){
//PreparedStatement继承于Statement
try{
if(s!=null)
s.close();
}catch(...){
...}
try{
if(conn!=null)
conn.close();
}catch(...){
...}
}
public static void close(Connection conn,Statement s,ResultSet result){
try{
}catch...//同上,多一个result的关闭
}
//通用增删改
public static void execute(Connection conn,String sql,Object ...args) throws Exception{
PreparedStatement ps=conn.prepareStatement(sql);
for(int i=0;i<args.length;i++){
ps.setObject(i+1,args[i]);
}
ps.execute();
}
//通用查,这里只针对某个表的所有查询,不是针对不同的表
public static void executeQuery(Connection conn,String sql,Object ...args){
PreparedStatement ps=conn.prepareStatement(sql);
for(int i=0;i<args.length;i++)
ps.setProperty(i+1,args[i]);
ResultSet result=ps.executeQuery();
//获取结果集的元数据
ResultSetMetaData rs=result.getMetaData();
int column=rs.getColumnCount();
while(result.next()){
User u=new User();
for(int i=0;i<column;i++){
Object o=result.getObject(i+1);
//获取列名
String cn=rs.getColumnName(i+1);
//赋给属性
Field f=User.class.getDeclaredField(cn);//当属性名和表字段名不一致时not OK
String cn=rs.getColumnLabel(i+1);//如果没其起别名就返回列名,以后不使用getColumnName()
Field f=User.class.getDeclaredField(cn)//要在sql中给字段起别名,即同属性名,才可使这个语句正确
f.setAccessible(true);//以防属性为私有
f.set(u,f);
}
System.out.println(u.toString());
}
}
//通用查,针对不同表
public static void executeQuery(Connection conn,String sql,Class<T> clazz,Object ...args){
...//相同代码省略
while(result.next()){
T t=clazz.newInstance();
...
}
}
}
JDBC API小结
4.Blob(tinyblob 255 blob 65k mediumblob 16M longblob 4G)二进制大型数据类型
FileInputStream in=new FileInputStream(new File("1.jpg"));
ps.setBlob(5,in);
//别忘了关闭流
//获取结果集中blob
Blob photo=result.getBlob(5);
Inputstream binaryStream=photo.getBinaryStream();
FileOutputStream out=new FileOutputStream("2.jpg");
byte[] b=new byte[1024];
int len;
while((len=binaryStream.read(b))!=-1){
out.write(b,0,len);
}
注意事项:
5.批量操作
!!使用PreparedStatement实现高效的批量插入
PreparedStatement | Statement |
---|---|
预编译,可复用编译的语句 | 不能预编译,导致相同执行语句因为数据不一样要重新编译 |
!!编译意味着要语法检查、语义检查,语句翻译所以费时,预编译需要缓存编译好的内容,以以空间换时间
//这里记得要try-catch一下,有资源关闭的地方都需要,为了关注批量操作本身这里省略没写
//注意变量定义要放在try-catch语句之外
Connection conn=JDBCUtils。getConnection();
conn=setAutoCommit(false);//不允许自动提交,别执行就提交,让它最后提交,优化速度
String sql="insert into user(name) values(?)";
PreparedStatement ps=conn.prepareStatement(sql);
for(int i=0;i<=20000;i++){
ps.setObject(1,"user_"+i);
//攒sql
ps.addBatch();//添加批处理的参数
if(i>0&&i%500=0){
//执行batch
ps.executeBatch();
//清空batch
ps.clearBatch();
}
}
conn.commit();
JDBCUtils.close(conn,ps);
!!mysql正常情况下是关闭批处理的,需要在配置文件中开启:写在url后面rewriteBatchedStatements=true
jdbc.properties
diver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/test?rewriteBatchedStatements=true
user=root
password=123
6.事物
6.1 概念:一组逻辑操作单元(DML操作,简单来说就是增删改),使数据从一种状态变为另一种一致的状态
6.2 原则:要么全做成功,要么全部没做,所以有失败则回滚
!!数据一旦提交就不可回滚
6.3 会自动提交的操作
try{
conn.setAutoCommit(false);
事物
conn.commit();
}
catch(Exception e){
conn.rollback();
略
}
finally{
conn.setAutoCommit(true);//以防别人要用自动提交,针对数据库连接池
关闭资源
}
6.4 ACID属性
6.5 数据库并发三个问题
6.5 隔离级别
6.7 MySQL中的命令
创建用户:create user 用户名 identified by ‘密码’;
赋予权限:grant select,insert,update,delete on 库名.* to 用户名@主机名 identified by ‘密码’;
查看隔离级别:select @@tx_isolation;
设置隔离级别:set global transaction isolation level 隔离级别;
//获取隔离级别
conn.getTransactionIsolation();
//设置隔离级别
conn.setTransctionIsolation(Connection.TRANSACTION_READ_COMMITED);
7.数据库连接池
7.1 普通方式获取连接及关闭连接的弊端
7.2 数据库连接池可以解决这些问题
7.3 JDBC开源的数据库连接池(DataSource的实现类)
7.4 数据源(DataSource 接口):连接池+连接池管理 使用DataSource代替DriverManager获取连接高效快速
以C3P0为例
数据源对象ds
ds.setDriverClass("com.mysql.jdbc.Driver");
ds.setJdbcUrl("...");
ds.setUser("..");
ds.setPassword("...");
ds.setInitialPoolSize(10);
等等设置
DataSource.destroy(ds);//销毁连接池
!!也可通过配置文件xml操作 cpds=new ComboPooledDataSource(“配置文件名”);
在JDBCUtils中使用连接池获取连接
private static ComboPooledDataSource cpds=new ComboPooledDataSource();//池子有一个就可以了
public static Connection getConnection() throws SQLException{
return cpds.getConnection();
}
8.Apache—DBUtils
替代我们自己编写的JDBCUtils
API: