书籍就像一盏神灯,它照亮人们最遥远、最黯淡的生活道路。——乌皮特
前言:下面内容是本人Java初学者的学习内容
前提准备:已经安装好mysql数据库,若没有请看Mysql8.0的下载安装
需要学习SQL语句,没有学的请看SQL语句简单学习
一、mysql-connector-java
有了这个Jar包支持,JAVA可以轻松的通过jdbc访问mySQL数据库。
1.下载
进入官网下载地址: https://dev.mysql.com/downloads/connector/j/
如下图操作即可:
直接点击 “No thanks, just start my download.”
解压出来即可
2.导入项目中
(我用的是Idea)
如下图操作:
2.1 新建一个项目工程,再新建一个libs文件夹,用于存放jar包
2.2 接着把刚才下载解压好的 mysql-connector-java-8.0.22.jar,ctrl+c 复制,ctrl+v粘贴进libs文件夹
2.3 导入后,需要激活(有好几种方法,这是其中一种)。打开project-setting(快捷键:ctrl+shirt+alt+s ),点击+号,选择第一个,如下图操作:
2.4 选择路径,好了后点击0K,就可以了。
二、JDBC简介
JDBC其实就是Java DataBase Connectivity:Java数据库连接
她所扮演的角色:提供连接数据库服务器的支持(如下图)
JDBC 重要的 四大物件
DriverManager:注册驱动,选择正确的驱动并加载
Connection:获取连接,由Driver产生,负责与数据库的连接,进行数据传输
Statement:传送SQL语句,由Connection产生,负责将sql语句送到数据库
ResultSet:获取结果集,负责接收Statement(sql)执行后的结果
四大物件关系图:
三、JDBC的实现
1.初始化驱动
通过 Class.forName(“com.mysql.cj.jdbc.Driver”); 将mysql驱动(com.mysql.cj.jdbc.Driver)注册到DriverManager中去
Class.forName是把这个类加载到JVM中,加载的时候,就会执行其中的静态初始化块,完成驱动的初始化的相关工作。
2.与数据库进行连接
这里需要提供:
数据库所处于的ip:127.0.0.1 (本机)
数据库的端口号: 3306 (mysql专用端口号)
数据库名称 helloJava(自己建一个)
支持中文 characterEncoding=UTF-8
时区支持 serverTimezone=GMT
账号 root
密码 123456(我就学习用,简单点好)
String url = "jdbc:mysql://127.0.0.1:3306/helloJava?characterEncoding=UTF-8 && serverTimezone=GMT";
String user = "root";
String password = "123456";
Connection con= DriverManager.getConnection(url, user, password);
3.SQL语句的执行
Statement的常用方法:
(1)executeQuery()方法:运行查询语句,返回ReaultSet对象。
(2)executeUpdata()方法:运行增,删,改操作,返回更新的行数。
(3)addBatch(String sql) :把多条sql语句放到一个批处理中。
(4)executeBatch():向数据库发送一批sql语句执行。
String sql="insert into hero values(null,'提莫',450.0,56)";
Statement st = con.createStatement();
st.executeUpdate(sql);//执行增删改
st.executeQuery(sql);//执行查询
4.获取结果
结果集:ResultSet
执行executeQuery()方法后返回的结果集
常用方法:
(1)getString(String columnName):获得当前行的某一string类型的字段
(2)getFloat(String columnName):获得当前行的某一string类型的字段
(3)getDate(String columnName):获得当前行的某一date类型的字段
(4)getBoolean(String columnName):获得在当前行的某一Boolean类型的字段
(5)getObject(String columnName):获取当前行的某一任意类型的字段
(6)next():移动到下一行
ResultSet rs = st.executeQuery(sql);
while(rs.next()){
......
}
5.关闭连接
手动关闭:
数据库的连接时有限资源,相关操作结束后,养成关闭数据库的好习惯
先关闭ResultSet,Statement,再关闭Connection
Close ResultSet,
Close Statement,
close Connection
//与数据库连接关闭
public static void close(Connection con, Statement st, ResultSet rs) {
try {
if(rs!=null) {
rs.close();
}
if(st!=null) {
st.close();
}
if(con!=null) {
con.close();
}
} catch (SQLException e) {
System.out.println("关闭失败");
e.printStackTrace();
}
}
自动关闭:
实现了AutoCloseable接口的类可以使用try-with-resource自动关闭连接,这样就不会发生忘记关闭连接。
try(Connection con= DriverManager.getConnection(url, user, password);
Statement st = con.createStatement();
) {
String sql="insert into hero values(null,'盖伦',650.0,60)";
st.executeUpdate(sql);
System.out.println("sql语句执行成功");
} catch (SQLException e) {
System.out.println("数据库操作出错");
e.printStackTrace();
}
下面贴上完整的JDBC的代码:
增删改(手动关闭连接)
package priv.jdbc.demo;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class TestJDBC {
public static void main(String[] args) throws ClassNotFoundException {
//加载驱动类
Class.forName("com.mysql.cj.jdbc.Driver");
//获得与数据库的连接
//DriverManager:选择正确的驱动并加载
//Connection :与数据库连接
Connection con=null;
Statement st=null;
/*
建立与数据库的Connection连接
这里需要提供:
数据库所处于的ip:127.0.0.1 (本机)
数据库的端口号: 3306 (mysql专用端口号)
数据库名称 helloJava
支持中文 characterEncoding=UTF-8
时区支持 serverTimezone=GMT
账号 root
密码 123456
*/
String url = "jdbc:mysql://127.0.0.1:3306/helloJava?characterEncoding=UTF-8 && serverTimezone=GMT";
String user = "root";
String password = "123456";
try {
con= DriverManager.getConnection(url, user, password);
System.out.println("连接成功....");
} catch (SQLException e) {
System.out.println("与数据库连接失败");
e.printStackTrace();
}
String sql="insert into hero values(null,'提莫',450.0,56)";//增
//String sql="delete from hero where name='提莫'";//删
//String sql="update hero set hp=500";//改
//Statement:将sql语句送到数据库中执行
try {
st=con.createStatement();
//执行sql语句
int row=st.executeUpdate(sql);
if (row>0) {
System.out.println("插入成功.....");
}
} catch (SQLException e) {
System.out.println("插入失败 ");
e.printStackTrace();
}
//关闭连接
// 数据库的连接时有限资源,相关操作结束后,养成关闭数据库的好习惯
// 先关闭Statement
//再关闭Connection
finally {
if (st!=null) {
try {
st.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (con!=null) {
try {
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
package priv.jdbc.demo;
public class Hero {
public String name;
public float hp;
public int damage;
public Hero(String name, float hp, int damage) {
this.name = name;
this.hp = hp;
this.damage = damage;
}
public Hero(float hp) {
this.hp = hp;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public float getHp() {
return hp;
}
public void setHp(float hp) {
this.hp = hp;
}
public int getDamage() {
return damage;
}
public void setDamage(int damage) {
this.damage = damage;
}
}
增删改(自动关闭连接,try-with-resource)
package priv.jdbc.demo;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class Test {
public static void main(String[] args) throws ClassNotFoundException {
Class.forName("com.mysql.cj.jdbc.Driver");
String url = "jdbc:mysql://127.0.0.1:3306/helloJava?characterEncoding=UTF-8 && serverTimezone=GMT";
String user = "root";
String password = "123456";
try(Connection con= DriverManager.getConnection(url, user, password);
Statement st = con.createStatement();
) {
String sql="insert into hero values(null,'盖伦',650.0,60)";
//String sql="delete from hero where name='提莫'";//删
//String sql="update hero set hp=500";//改
st.executeUpdate(sql);
System.out.println("sql语句执行成功");
} catch (SQLException e) {
System.out.println("数据库操作出错");
e.printStackTrace();
}
}
}
查询
package priv.jdbc.demo;
import java.sql.*;
public class SelectTest {
public static void main(String[] args) throws ClassNotFoundException {
Class.forName("com.mysql.cj.jdbc.Driver");
String url = "jdbc:mysql://127.0.0.1:3306/helloJava?characterEncoding=UTF-8 && serverTimezone=GMT";
String user = "root";
String password = "123456";
try(Connection con= DriverManager.getConnection(url, user, password);
Statement st = con.createStatement();
) {
String sql="select * from hero";
// 执行查询语句,并把结果集返回给ResultSet
ResultSet rs = st.executeQuery(sql);
while (rs.next()) {
int id = rs.getInt("id");// 可以使用字段名
String name = rs.getString(2);// 也可以使用字段的顺序
float hp = rs.getFloat("hp");
int damage = rs.getInt(4);
System.out.format("id=%d,name=%s,hp=%f,damage=%d %n", id, name, hp, damage);
}
} catch (SQLException e) {
System.out.println("数据库操作出错");
e.printStackTrace();
}
}
}
6.预编译PreparedStatement
它是一個继承 Statement 类的接口。
和 Statement一样,PreparedStatement也是用来负责将sql语句送到数据库执行。
但是Statement:SQL发送到数据库服务器先经过编译再执行。
而PreparedStatement:先预编译SQL 语句,暂存在缓存里面,调用时就可以直接执行了。
与创建Statement不同的是,需要根据sql语句创建PreparedStatement。
除此之外,还能够通过设置参数,指定相应的值,而不是Statement那样使用字符串拼接。
优点1-参数设置
Statement 需要进行字符串拼接,可读性和维护性比较差
String sql = “insert into hero values(null,”+"‘提莫’"+","+313.0f+","+50+")";
PreparedStatement 使用参数设置,可读性好,不易犯错
String sql = “insert into hero values(null,?,?,?)”;
优点2-性能表现
PreparedStatement有预编译机制,性能比Statement更快
优点3-防止SQL注入式攻击
假设name是用户提交来的数据
String name = "'盖伦' OR 1=1";
使用Statement就需要进行字符串拼接
拼接出来的语句是:
select * from hero where name = '盖伦' OR 1=1
因为有OR 1=1,这是恒成立的
那么就会把所有的英雄都查出来,而不只是盖伦
如果Hero表里的数据是海量的,比如几百万条,把这个表里的数据全部查出来
会让数据库负载变高,CPU100%,内存消耗光,响应变得极其缓慢
而PreparedStatement使用的是参数设置,就不会有这个问题
实践代码,搓搓小手动起来(=!=):
package priv.jdbc.demo;
import java.sql.*;
public class PreparedStatementTest {
public static void main(String[] args) throws ClassNotFoundException {
Class.forName("com.mysql.cj.jdbc.Driver");
String url = "jdbc:mysql://127.0.0.1:3306/helloJava?characterEncoding=UTF-8 && serverTimezone=GMT";
String user = "root";
String password = "123456";
String sql="insert into hero values (null,?,?,?)";
try(Connection con= DriverManager.getConnection(url, user, password);
// 根据sql语句创建PreparedStatement
PreparedStatement ps = con.prepareStatement(sql);
) {
//设置参数
ps.setString(1,"战争之影-赫卡里姆");
ps.setFloat(2,650.0f);
ps.setInt(3,55);
//执行
ps.execute();
} catch (SQLException e) {
System.out.println("数据库操作出错");
e.printStackTrace();
}
}
}
7.批处理
public void adds(List<Hero> list) {
String sql ="insert into hero values(?,?,?,?)";
try(Connection con= DbUtils.getConnection();
PreparedStatement ps = con.prepareStatement(sql);){
for (Hero h:list) {
ps.setInt(1,h.getId());
ps.setString(2,h.getName());
ps.setFloat(3,h.getHp());
ps.setInt(4,h.getDamage());
ps.addBatch();
}
int[] arr =ps.executeBatch();
System.out.println("批量增加:");
for(int i=0;i<arr.length;i++) {
System.out.print(arr[i]+" ");
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
8.事务
在人员管理系统中,你删除一个人员,你即需要删除人员的基本资料,也要删除和该人员相关的信息,如信箱,文章等等,这样,这些数据库操作语句就构成一个事务!
四个特性:
- 原子性A(atomicity):一组事务,要么成功;要么撤回。
- 一致性C(consistency):事务执行后,数据库状态与其他业务规则保持一致。如转账业务,无论事务执行成功否,参与转账的两个账号余额之和应该是不变的。
- 隔离性I(isolation):事务独立运行。一个事务处理后的结果,影响了其他事务,那么其他事务会撤回。事务的100%隔离,需要牺牲速度。
- 持久性D(durability):事务完成后,它对数据库的修改被永久保持,事务日志能够保持事务的永久性
在事务中的多个操作,要么都成功,要么都失败。
在JDBC中处理事务,都是通过Connection完成的。
同一事务中所有的操作,都在使用同一个Connection对象。(谨记!我是掉过坑…)
- con.setAutoCommit(false):表示开启事务
- con.commit():提交结束事务
- con.rollback():回滚结束事务
JDBC处理事务的代码格式:
try{
con.setAutoCommit(false);//开启事务
......
con.commit();//try的最后提交事务
} catch() {
con.rollback();//回滚事务
}
MYSQL 表的类型必须是INNODB(现在是默认存储引擎)才支持事务
在Mysql中,只有当表的类型是INNODB的时候,才支持事务,所以需要把表的类型设置为INNODB,否则无法观察到事务.
修改表的类型为INNODB的SQL:
alter table hero ENGINE = innodb;
查看表的类型的SQL
show table status from 数据库名;
实践代码,搓搓小手动起来(=!=):
事务代码:
package priv.jdbc.demo;
import java.sql.*;
public class Business {
public static void main(String[] args) throws ClassNotFoundException {
Class.forName("com.mysql.cj.jdbc.Driver");
String url = "jdbc:mysql://127.0.0.1:3306/helloJava?characterEncoding=UTF-8 && serverTimezone=GMT";
String user = "root";
String password = "123456";
try(Connection con= DriverManager.getConnection(url, user, password)){
//关闭自动默认提交,开启事务
con.setAutoCommit(false);
Boolean OK = true;
//给id为101和102的hero数据,hp分别减少和增加100
String sql1 ="update hero set hp = hp - ? where id = ?";
String sql2 ="update hero set hp = hp + ? where id = ?";
try (PreparedStatement prs1 = con.prepareStatement(sql1);
PreparedStatement prs2 = con.prepareStatement(sql2)) {
//设置参数
prs1.setFloat(1,100);
prs1.setInt(2,100);
prs2.setFloat(1,100);
prs2.setInt(2,108);
//执行语句
int row1 = prs1.executeUpdate();
int row2 = prs2.executeUpdate();
if (row1==0 || row2==0) {
OK=false;
System.out.println("rollback!");
con.rollback();
}
if (OK) {
//提交事务
con.commit();
System.out.println("commit!");
}
}catch (SQLException e) {
OK=false;
con.rollback();
e.printStackTrace();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
9.数据库连接池
1.传统方式
当有多个线程,每个线程都需要连接数据库执行SQL语句的话,那么每个线程都会创建一个连接,并且在使用完毕后,关闭连接。
创建连接和关闭连接的过程也是比较消耗时间的,当多线程并发的时候,系统就会变得很卡顿。
同时,一个数据库同时支持的连接总数也是有限的,如果多线程并发量很大,那么数据库连接的总数就会被消耗光 ,后续线程发起的数据库连接就会失败。
2.连接池
与传统方式不同,连接池在使用之前,就会创建好一定数量的连接。
如果有任何线程需要使用连接,那么就从连接池里面借用,而不是自己重新创建。 使用完毕后,又把这个连接归还给连接池供下一次或者其他线程使用。
倘若发生多线程并发情况,连接池里的连接被借用光了,那么其他线程就会临时等待,直到有连接被归还回来,再继续使用。
整个过程,这些连接都不会被关闭,而是不断的被循环使用,从而节约了启动和关闭连接的时间。
3.ConnectionPool构造方法和初始化
- ConnectionPool() 构造方法约定了这个连接池一共有多少连接
- 在init() 初始化方法中,创建了size条连接。 注意,这里不能使用 try-with-resource这种自动关闭连接的方式,因为连接恰恰需要保持不关闭状态,供后续循环使用
- getConnection, 判断是否为空,如果是空的就wait等待,否则就借用一条连接出去
- returnConnection, 在使用完毕后,归还这个连接到连接池,并且在归还完毕后, 调用notifyAll,通知那些等待的线程,有新的连接可以借用了。
package priv.jdbc.demo;
import priv.jdbc.util.DbUtils;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
public class ConnectionPool {
List<Connection> cs = new ArrayList<Connection>();
int size;
public ConnectionPool(int size) {
this.size = size;
init();
}
public void init() {
//这里恰恰不能使用try-with-resource的方式,因为这些连接都需要是"活"的,不要被自动关闭了
try {
for (int i = 0; i < size; i++) {
Connection c = DbUtils.getConnection();
cs.add(c);
}
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public synchronized Connection getConnection() {
while (cs.isEmpty()) {
try {
this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Connection c = cs.remove(0);
return c;
}
public synchronized void returnConnection(Connection c) {
cs.add(c);
this.notifyAll();
}
}
package priv.jdbc.demo;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class Test {
public static void main(String[] args) throws ClassNotFoundException {
Class.forName("com.mysql.cj.jdbc.Driver");
String url = "jdbc:mysql://127.0.0.1:3306/helloJava?characterEncoding=UTF-8 && serverTimezone=GMT";
String user = "root";
String password = "123456";
try(Connection con= DriverManager.getConnection(url, user, password);
Statement st = con.createStatement();
) {
String sql="insert into hero values(null,'盖伦',650.0,60)";
//String sql="delete from hero where name='提莫'";//删
//String sql="update hero set hp=500";//改
st.executeUpdate(sql);
System.out.println("sql语句执行成功");
} catch (SQLException e) {
System.out.println("数据库操作出错");
e.printStackTrace();
}
}
}
四、JDBC的封装
jdbc是连接数据库必不可少的工具,但每次连接都要重新写一遍太麻烦了,也不利于代码的可读性。把重复的代码封装起来,岂不快哉!我查资料看到前辈们把普通的增删改查方法都封装起来了java之对JDBC的完整封装(兼容多种数据库。
但是作为新手的我们,还是应该老实的先敲熟练了,再去自己尝试封装各种方法。
简单的封装:把数据库连接和关闭封装起来。
我还学着前辈把项目结构整了一下,什么包放什么类,清晰多了。
1.包util里的类DbUtils里封装的是Connection 数据库 的连接和关闭。
package priv.jdbc.util;
import java.sql.*;
public class DbUtils {
//与数据库连接
public static Connection getConnection() throws ClassNotFoundException {
String driver ="com.mysql.cj.jdbc.Driver";
Class.forName(driver);
String url ="jdbc:mysql://127.0.0.1:3306/helloJava?characterEncoding=UTF-8 && serverTimezone=GMT";
String user ="root";
String password = "123456";
Connection con=null;
try{
con = DriverManager.getConnection(url, user, password);
} catch (SQLException e) {
System.out.println("与数据库连接失败");
e.printStackTrace();
}
return con;
}
//与数据库连接关闭(增删改查方法里使用try-with-resources语句,会自动关闭连接,但是无法用于数据库连接池)
public static void close(Connection con, PreparedStatement ps) {
try{
if(ps!=null) {
ps.close();
}
if(con!=null) {
con.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
public static void close(Connection con, PreparedStatement ps, ResultSet rs) {
try {
if(rs!=null) {
rs.close();
}
if(ps!=null) {
ps.close();
}
if(con!=null) {
con.close();
}
} catch (SQLException e) {
System.out.println("关闭失败");
e.printStackTrace();
}
}
}
2.包model里放一张表一个类,比如Hero
package priv.jdbc.model;
public class Hero {
public int id;
public String name;
public float hp;
public int damage;
public Hero() {
}
public Hero(int id, String name, float hp, int damage) {
this.id = id;
this.name = name;
this.hp = hp;
this.damage = damage;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public float getHp() {
return hp;
}
public void setHp(float hp) {
this.hp = hp;
}
public int getDamage() {
return damage;
}
public void setDamage(int damage) {
this.damage = damage;
}
@Override
public String toString() {
return "Hero{" +
"id=" + id +
", name='" + name + ''' +
", hp=" + hp +
", damage=" + damage +
'}'+"n";
}
}
3.包dao里面放操作方法,HeroDao是实现类,去实现接口Dao
package priv.jdbc.dao;
import priv.jdbc.model.Hero;
import java.sql.Connection;
import java.util.List;
public interface Dao {
//增
public int add(Hero hero) ;
//批处理-增
public void adds(List<Hero> list);
//删
public int delete(int id);
//改(事务)
public int updateHp(Connection con,Hero hero, String sql);
//查
public Hero select(int id);
//分页查询
public List<Hero> list(int start,int count);
}
package priv.jdbc.dao;
import priv.jdbc.model.Hero;
import priv.jdbc.util.DbUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
public class HeroDao implements Dao {
/**
* 增
* @param hero
* @throws ClassNotFoundException
*/
@Override
public int add(Hero hero) {
String sql ="insert into hero values(?,?,?,?)";
int rows=0;
try(Connection con= DbUtils.getConnection();
PreparedStatement ps = con.prepareStatement(sql);) {
ps.setInt(1,hero.getId());
ps.setString(2,hero.getName());
ps.setFloat(3,hero.getHp());
ps.setInt(4,hero.getDamage());
rows = ps.executeUpdate();//rows>0,表示sql语句执行成功
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
}
return rows;
}
/**
* 批量增加
* @param list
*/
@Override
public void adds(List<Hero> list) {
String sql ="insert into hero values(?,?,?,?)";
try(Connection con= DbUtils.getConnection();
PreparedStatement ps = con.prepareStatement(sql);){
for (Hero h:list) {
ps.setInt(1,h.getId());
ps.setString(2,h.getName());
ps.setFloat(3,h.getHp());
ps.setInt(4,h.getDamage());
ps.addBatch();
}
int[] arr =ps.executeBatch();
System.out.println("批量增加:");
for(int i=0;i<arr.length;i++) {
System.out.print(arr[i]+" ");
}
System.out.println("");
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
/**
* 删
* @param id
* @return
*/
@Override
public int delete(int id) {
String sql = "delete from hero where id="+id;
int rows=0;
try (Connection con= DbUtils.getConnection();
PreparedStatement ps = con.prepareStatement(sql);){
rows = ps.executeUpdate();
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
}
return rows;
}
/**
* 改
* @param hero
* @return
*/
@Override
public int updateHp(Connection con,Hero hero,String sql) {
int rows=0;
try (
PreparedStatement ps = con.prepareStatement(sql)){
ps.setFloat(1, 100);
ps.setInt(2,hero.id);
rows = ps.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}
return rows;
}
/**
* 查询
* @param id
* @return
*/
@Override
public Hero select(int id) {
Hero hero =null;
String sql = "select * from hero where id="+id;
try(Connection con= DbUtils.getConnection();
PreparedStatement ps = con.prepareStatement(sql);) {
ResultSet rs = ps.executeQuery();
if (rs.next()) {
String name = rs.getString(2);
float hp = rs.getFloat(3);
int damage = rs.getInt(4);
hero = new Hero(id,name,hp,damage);
}
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
}
return hero;
}
/**
* 分页查询
* @param start
* @param count
* @return
*/
@Override
public List<Hero> list(int start, int count) {
List<Hero> heros = new ArrayList<Hero>();
String sql = "select * from hero order by id limit ?,?";
try(Connection con= DbUtils.getConnection();
PreparedStatement ps = con.prepareStatement(sql);) {
ps.setInt(1,start);
ps.setInt(2,count);
ResultSet rs = ps.executeQuery();
while(rs.next()){
int id = rs.getInt(1);
String name = rs.getString(2);
float hp = rs.getFloat(3);
int damage = rs.getInt(4);
Hero hero = new Hero(id,name,hp,damage);
heros.add(hero);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
return heros;
}
}
4.包service处理事务,比如UpdateService
package priv.jdbc.service;
import priv.jdbc.dao.HeroDao;
import priv.jdbc.model.Hero;
import priv.jdbc.util.DbUtils;
import java.sql.Connection;
import java.sql.SQLException;
public class UpdateService {
//指定id的hp分别减少和增加100
public void hpUpdate(Hero h1,Hero h2) {
HeroDao hd = new HeroDao();
Boolean OK = true;
try (Connection con = DbUtils.getConnection()){
//取消自动提交,事务开启
con.setAutoCommit(false);
try {
String sql1 = "update hero set hp = hp - ? where id = ?";
String sql2 = "update hero set hp = hp + ? where id = ?";
int row1 = hd.updateHp(con,h1, sql1);
int row2 = hd.updateHp(con,h2, sql2);
if (row1==0 || row2==0) {
OK = false;
System.out.println("roll back");
con.rollback();
}
if (OK) {
//提交事务
con.commit();
System.out.println("commit");
}
}catch (SQLException e){
OK=false;
System.out.println("roll back");
con.rollback();
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
5.包run放测试类
package priv.jdbc.run;
import priv.jdbc.dao.HeroDao;
import priv.jdbc.model.Hero;
import priv.jdbc.service.UpdateService;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
public class Test {
public static void main(String[] args) throws SQLException {
HeroDao heroDao =new HeroDao();
UpdateService us = new UpdateService();
List<Hero> l = new ArrayList<Hero>();
Hero hero1 = new Hero(100,"赫卡里姆",675,70);
Hero hero2 = new Hero(101,"嘉文四世",700,65);
Hero hero3 = new Hero(102,"沙漠玫瑰",590,75);
Hero hero4 = new Hero(103,"沙漠玫瑰",590,75);
Hero hero5 = new Hero(104,"沙漠玫瑰",590,75);
l.add(hero1);l.add(hero2);
l.add(hero3);l.add(hero4);
//批量新增
heroDao.adds(l);
//分页查询
if (heroDao.list(0,5)!=null) {
System.out.println("分页查询成功,结果如下:");
System.out.println(heroDao.list(0,5));
}
//Hp的增减事务
us.hpUpdate(hero1,hero2);
//分页查询
if (heroDao.list(0,5)!=null) {
System.out.println("分页查询成功,结果如下:");
System.out.println(heroDao.list(0,5));
}
}
}
还想了解更多:Java自学网站
今天学习分享的内容到此为止了,本是想要激励自己学下去,但发现快乐更是知识在于分享!
作为初学者对于Java的理解实在浅薄,如有错误请指正,万分感谢!