javaweb的作用,属于中间者,负责逻辑处理
这三部分互相协作组成了网页
javaweb也就是这三部分
一.数据库部分(略)
二.javaweb程序
1.JDBC
概念:通过java代码操作数据库
数据库种类有很多,比如Oracle,Mysql,DB2,我们一套代码需要和不同的数据库语言沟通所以就要引入不同的jar包。
(1).DriverManager作用:
1.注册驱动
Class.forName("com.mysql.jdbc.Driver");
按住ctrl+鼠标就可以进入Driver的api文档(前提是得有jar包),查看源码
然后这里面有一个静态代码块,里面有DriverManeger,所以就是用Class.forName("com.mysql.jdbc.Driver")为啥可以用到DriverManager注册驱动的原因。
注意:
jar包5.0以上就可以省略这一句,不用写了
疑问:咋弄
2.获取数据库连接
String url="jdbc:mysql://127.0.0.1:3306/db1?user"; 简写后:jdbc:mysql:///db1
String username="root";
String password="root";
static Connection=getConnection(String url,String user,String password);
注意:
*url的语法:jdbc:mysql://ip地址(域名):端口号/数据库名称?参数键值对1&参数键值对2...
eg: jdbc:mysql://127.0.0.1:3306/db1
*如果连接的是本机mysql并且服务器默认端口号是3306,可以简写为 jdbc:mysql:///db1
*配置useSSL=false参数,禁用安全连接方式,不然有那么长一段字母警告,很烦,并且也可以提高性能
(2)Connecttion作用(数据库连接对象):
1.获取执行SQL的对象
1)普通执行SQL对象:
Statement=createStatement();
2)预编译SQL的执行SQL对象:防止SQL注入
preparedStatement=prepareStatement(sql);
3)执行存储过程的对象:不常用
CallableStatement prepareCall(sql)
2.管理事务
开启事务:BEGIN;/START TRANSACTION;
提交事务:COMMIT;
回滚事务:ROLLBACK;
开启事务:setAutoCommit(false/true);true为自动提交事务;false为手动提交事务,即为开启事务
提交事务:commit();
回滚事务:rollback();
Java代码中事务处理的方式就是异常处理机制
用try cash。。。。,在cash里进行事务的回滚
(3)Statement
作用:执行SQL语句
DDL对表和库的增删改查
DML对数据的增删改
DQL对数据的查询工作
excuteUpdate:执行DML/DDL
返回值:1.影响行数2.DDL语句执行后,直行程也可能返回0
挫折:@test报错
JDBC:
这是jdbc连接数据库不可缺少的步骤
Class.forName("com.mysql.jdbc.Driver");//抛大异常,注册驱动
//获取连接
String url="jdbc:mysql://127.0.0.1:3306/smbms";
String username="root";
String password="root";
Connection conn = DriverManager.getConnection(url, username, password);
//定义sql语句
String sql="UPDATE smbms_user set gender=1 WHERE id=1";
//获取执行sql的对象
Statement stmt = conn.createStatement();
//执行sql,返回值3影响行数
int count = stmt.executeUpdate(sql);
DriverManager:
1.注册驱动
注册驱动虽然用的是这个代码
Class.forName("com.mysql.jdbc.Driver");//抛大异常,注册驱动
但是底层,我们点开可以看到这个Driver类源码里面有一个静态代码块是用的DriverManager.registerDriver
所以这个注册驱动实际上是用的DriverManager
public class Driver extends NonRegisteringDriver implements java.sql.Driver {
public Driver() throws SQLException {
}
static {
try {
DriverManager.registerDriver(new Driver());
} catch (SQLException var1) {
throw new RuntimeException("Can't register driver!");
} }}
2.获取数据库连接
DriverManager返回一个conn连接对象
Connection conn = DriverManager.getConnection(url, username, password);
在这三个参数中url要说一下
String url="jdbc:mysql://127.0.0.1:3306/smbms";
1.如果连接的是本机mysql服务器,并且mysql服务器默认端口是3306,
则url可以简写为jdbc:mysql:///smbms
2.配置useSSL=false参数,是禁用安全连接方式,解决警告提示
jdbc:mysql:///smbms?useSSL=false
Connection:
1.获取执行sql的对象
**.**普通执行sql对象:
Statement createStatement( );
例如:
Statement statement = conn.createStatement();
.预编译sql的执行sql对象:防止sql注入:
PreparedStatement prepareStatement(sql);
2.管理事务
//为ture时自动提交事务,为false手动映射,即为开启事务
开启事务:setAutoCommit(boolean autoCommit)
提交事务:commit();
回滚事务:rollback();
这是一个例子:通过try catch进行事务管理
我们在这里面添加了一个int i=3/0;制造异常
有事务的管理,代码如果遇到错误会回滚
如果关掉事务管理,代码会执行一半,然后报错,只会执行sql1
String sql1="UPDATE smbms_user set gender=2 WHERE id=1";
String sql2="UPDATE smbms_user set gender=2 WHERE id=2";
Statement stmt = conn.createStatement();
try {
conn.setAutoCommit(false);//开启事务
int count1 = stmt.executeUpdate(sql1);
System.out.println(count1);
//制造异常
int i=3/0;
int count2 = stmt.executeUpdate(sql2);
System.out.println(count2);
//提交事务
conn.commit();
} catch (Exception e) {
//回滚事务
conn.rollback();
e.printStackTrace();
}
Statement:执行SQL语句
方法一: int stmt.executeUpdate(sql对象);
int count1 = stmt.executeUpdate(sql);
返回值:
DML会返回数字,更改了几行返回几可以通过这个来判断执行成功与否,
DDL会返回0比如DROP删除数据库操作
DDL: 主要使用CREATE、DROP、ALTER等命令,用于定义和管理数据库的各种对象
DML: DML使用INSERT、UPDATE、DELETE等命令,用于对数据表中的数据进行增查改删的操作
方法二:
ResultSet executeQuery(sql):执行DQL语句
返回值:ResultSet结果集对象
这个会用到ResultSet,我们接下来讲
ResultSet:封装表的查询结果
查询Account表,封装为Account对象,存储到ArrayList集合中
每一行的数据封装为一个对象,这些对象存在ArrayList中,
最后页面展示就把这些对象放出来这就是表查询到页面展示的一个过程
方法一:
封装了表查询的结果
ResultSet rs=stmt.executeQuery(sql); //执行DQL语句,返回ResultSet对象
获取查询结果:
Class.forName("com.mysql.jdbc.Driver"); //抛大异常,注册驱动
String url="jdbc:mysql://127.0.0.1:3306/smbms";
String username="root";
String password="root"; //获取连接对象
Connection conn = DriverManager.getConnection(url, username, password);
String sql="select * from account"; //定义sql语句,DQL查询语句
Statement stmt = conn.createStatement(); //获取statament对象,执行sql
ResultSet rs=stmt.executeQuery(sql); //statement执行sql语句
List<Account> list=new ArrayList<>();
//处理结果,遍历rs中的所有数据rs.next()光标移动到下一行,并且半段当前行是否有数据
while(rs.next()){
Account account=new Account();
int id = rs.getInt(1); //get获取数据
String name=rs.getString(2);
String money=rs.getString(3);
account.setId(id); //把数据放到account对象里
account.setName(name);
account.setMoney(money);
list.add(account); }
System.out.println(list);
//释放资源
rs.close();
stmt.close();
conn.close();
boolean next():
将光标从当前位置向下移动一行,并且判断当前行是否为有效行(有没有数据)
返回值:
ture有效行 ,当前行有数据
false无效行,当前行有数据
xx getXxx
eg:int id = rs.getInt(1); String name=rs.getString(2);
参数:
int列的编号,从1开始
String:列的名称
PreparedStatement:预编译sql语句并执行,预防SQL注入问题
preparedstatement会帮我们把字符转义,解决了sql注入的问题
1.获取preparedstatement对象
之前是执行的时候就传入sql语句ResultSet rs = stmt.executeQuery(sql);
现在是获取对象的时候就传入sql语句PreparedStatement pstmt = conn.prepareStatement(sql);
//SQL语句中的参数值,使用?占位符代替
String sql="select * from user where username=?and password=?";
//通过connection对象,并传入对应的sql语句
PreparedStatement pstmt = conn.prepareStatement(sql);
2.设置参数值
Preparedstatement对象:setXxx(参数1,参数2):给?赋值
Xxx:数据类型;如setInt(参数1,参数2)
参数:
参数1:?的位置编号,从1开始,1表示第一个sql语句中参数
参数2:第二个参数
例如:
pstmt.setString(1,name);
pstmt.setString(2,pwd);
3.执行SQL:
在这一步和statement不一样,statement在这一步需要传值,而preparestatement不需要传值,它在创建pstmt对象的时候已经传过值了
ResultSet rs = pstmt.executeQuery();
ResultSet rs = pstmt.executeUpdate();
PrepareStatement原理:
1.在获取PreparedStatement对象时,将sql语句发送给mysql服务器进行检查,编译(这些很耗时)
2.执行时就不用再进行这些步骤了,速度更快
3.如果sql模板一样,则只需要进行一次检查、编译,从而节约时间
PreparedStatement好处:
1.预编译SQL,性能更高
2.防止SQL注入:将敏感字符进行转义
预编译功能开启,在url的后面加上**&useServerPrepStmts=true**
配置MYSQL执行日志:(重启mysql服务后生效)这个地方我没听懂
Druid数据库连接池:
学了这个以后直接用这个代替之前学的Class.forname()啥啥的,直接用数据库连接池连,复制下面四行代码就可以
在这里我打代码遇到了问题,绝对路径和相对路径都不行,后来我又重新创了一个路径中没有中文的就运行成功了,感觉可能是有中文导致的路径问题
//1.导入jar包
//2.定义配置文件
//3.加载配置文件
Properties prop=new Properties();
// demodruid.class.getResourceAsStream("/druid.properties");
prop.load(new FileInputStream("src/druid.properties"));
// 4.获取连接池对象
DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);
//5.获取数据库连接
Connection connection = dataSource.getConnection();
是一个很好用的小技巧,可以打印出当前的路径,在文件中的的再加入剩下的路径就行了,可以很好的判断是否要加项目名
System.out.println(System.getProperty("user.dir"));
JDBC练习:
准备:
表,实体类,测试用例
表中有很多字段,一一写会浪费时间
增删改查:
连接数据库只有三步有变化:
定义SQL
设置参数
处理结果
查询:
+编写sql语句:String sql="select * from brand";
+是否需要参数:不需要
+处理结果:List<Brand>
获取数据和封装brand对象是个体力活
Properties prop=new Properties();
// demodruid.class.getResourceAsStream("/druid.properties");
prop.load(new FileInputStream("src/druid.properties"));
// 4.获取连接池对象
DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);
//5.获取数据库连接
Connection conn = dataSource.getConnection();
//定义sql
String sql="select * from brand";
//传sql,并且返回pstmt对象
PreparedStatement pstmt = conn.prepareStatement(sql);
//设置参数,这个sql没有参数
//执行sql,返回结果集
ResultSet rs = pstmt.executeQuery();
//处理结果List<Brand>封装Brand对象,装载List集合
Brand brand=null;
List<Brand> brands=new ArrayList<>();
while(rs.next()){
//获取数据 体力活
int id = rs.getInt("id");//可以写列的数字也可以写列名
String brandName = rs.getString("brand_name");
String companyName = rs.getString("company_name");
int ordered = rs.getInt("orderer");
String description = rs.getString("description");
int status = rs.getInt("status");
//封装Brand对象
brand=new Brand();
brand.setId(id);
brand.setBrandName(brandName);
brand.setCompanyName(companyName);
brand.setOrderer(ordered);
brand.setDescription(description);
brand.setStatus(status);
//装载到集合
brands.add(brand);
}
System.out.println(brands);
//释放资源
rs.next();
conn.close();
pstmt.close();
添加:
编写SQL语句:
是否需要参数?需要除了id之外的所有参数
返回结果如何封装?boolean
//模拟接收页面提交的参数
String brandName="娃哈哈";
String companyName="娃哈哈";
int orderer=1;
String description="好喝好喝极了";
int status=1;
Properties prop=new Properties();
prop.load(new FileInputStream("src/druid.properties"));
// 4.获取连接池对象
DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);
//5.获取数据库连接
Connection conn = dataSource.getConnection();
//定义sql
String sql="insert into brand(brand_name,company_name,orderer,description,status)values(?,?,?,?,?)";
//传sql,并且返回pstmt对象
PreparedStatement pstmt = conn.prepareStatement(sql);
//设置参数
pstmt.setString(1,brandName);
pstmt.setString(2,companyName);
pstmt.setInt(3,orderer);
pstmt.setString(4,description);
pstmt.setInt(5,status);
//执行sql
int count = pstmt.executeUpdate();//影响行数
//处理结果
System.out.println(count>0);
//释放资源
// rs.next();无
conn.close();
pstmt.close();
修改(根据id修改):
-
sql语句:update brand set brand_name=?
-
参数:Brand所有数据
-
返回封装:boolean
//接收页面提交的参数
String brandName="笨笨狗";
String companyName="笨笨狗";
int orderer=1000;
String description="好喝好喝极了";
int status=1;
int id=2;Properties prop=new Properties();
// demodruid.class.getResourceAsStream("/druid.properties");
prop.load(new FileInputStream("src/druid.properties"));
// 4.获取连接池对象
DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);
//5.获取数据库连接
Connection conn = dataSource.getConnection();
//定义sql
String sql="update brand set brand_name=?,company_name=?,orderer=?,description=?,status=? where id=?";
//传sql,并且返回pstmt对象
PreparedStatement pstmt = conn.prepareStatement(sql);
//设置参数
pstmt.setString(1,brandName);
pstmt.setString(2,companyName);
pstmt.setInt(3,orderer);
pstmt.setString(4,description);
pstmt.setInt(5,status);
pstmt.setInt(6,id);//执行sql int count = pstmt.executeUpdate();//影响行数 //处理结果 System.out.println(count>0); //释放资源
// rs.next();无
conn.close();
pstmt.close();
删除(根据id删除):
-
删除
-
编写sql语句:delete from brand where id=?
-
是否需要参数:需要id
-
返回结果如何封装:boolean
//模拟页面传参
int id=2;//获取connction对象 Properties prop=new Properties(); //加载配置文件 prop.load(new FileInputStream("src/druid.properties")); //获取连接池对象 DataSource dataSource = DruidDataSourceFactory.createDataSource(prop); //获取数据库连接 Connection conn=dataSource.getConnection(); String sql="delete from brand where id=?"; //获取pstmt对象,在获取对象的时候就已经传入sql PreparedStatement pstmt = conn.prepareStatement(sql); pstmt.setInt(1,id); //执行sql int count = pstmt.executeUpdate(); System.out.println(count>0); pstmt.close(); conn.close();
Maven:
只要点击这个,maven坐标就会自动更新,不用再点刷新键
按alt+insert就可以自动生成坐标
scope作用范围:
runtime:测试运行时有效,主工程无效