JDBC(java DataBase Connectivity,数据库连接)是一种用于执行SQL语句的JavaAPI,JDBC是java访问的数据库标准规范,可以为不同的关系型数据库提供统一访问,它由一组用java语言编写的接口和类组成
JDBC需要连接驱动,驱动是两个设备要进行通信,满足一定的通信数据格式,数据格式由设备提供商规定,设备提供商为设备提供驱动软件,通过软件可以与该设备进行通信
核心:3个接口和一个类:
JDBC是接口,驱动是接口的实现,没有驱动无法完成数据库连接,从而不能操作数据库,每一个数据库厂商都需要提供自己的驱动,用来连接数据,驱动一般是由数据库生成厂商提供
步骤:
package java学习.jdbc_mysql;
import com.mysql.jdbc.Driver;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
public class JDBCDemo {
public static void main(String[] args) throws Exception{
//1.register driver ,use DriverManger to register
com.mysql.jdbc.Driver drive = new com.mysql.jdbc.Driver();
DriverManager.registerDriver(drive);
//2.get the connection object with the database:the implementation class object of the connection interface
String url = "jdbc:mysql://localhost:3306/firstdb?useSSL=false";//固定语法: jdbc:数据库厂商://localhost:3306/数据库名
Connection conn = DriverManager.getConnection(url,"root","666");
//3.get the executor object of the SQL statement,which is the implementation class object of the Statement
Statement st = conn.createStatement();
//4.get the result object of the SQL statement,which is the implementation class object of the ResultSet
ResultSet rs = st.executeQuery("select * from employee");//excute有很多方式,增删该查等
//5. process the result set,using an iterator
while (rs.next()){
Object a1 = rs.getObject("id");
Object a2 = rs.getObject("name");
System.out.println(a1+"\t"+ a2);
}
//6. close resource,只有执行查询,才有结果集对象,增删改没有结果集对象
rs.close();
st.close();
conn.close();
}
}
案例:通过工具类,进行简化:
package java学习.jdbc_mysql;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
public class JDBCUtils {
//自己设计一个工具类获取数据库连接
private static String driverName = "com.mysql.jdbc.Driver";
private static String url = "jdbc:mysql://localhost:3306/firstdb?useSSL=false";
private static String username = "root";
private static String password = "666";
//静态代码块,以后不再加载
static {
try{
//1.load driver
Class.forName(driverName);
}catch (Exception e){
System.out.println("驱动加载失败`");
throw new RuntimeException();
}
}
public static Connection getConnection() throws Exception{
//2.get connection with mysql
Connection conn = DriverManager.getConnection(url,username,password);
//return object
return conn;
}
//关闭资源
public static void closeAll(Connection conn, Statement st, ResultSet rs){
if (conn == null) {
try{
conn.close();
}
catch (Exception e){
e.printStackTrace();
}
}
if (st == null) {
try{
st.close();
}
catch (Exception e){
e.printStackTrace();
}
}
if (rs == null) {
try{
rs.close();
}
catch (Exception e){
e.printStackTrace();
}
}
}
}
package java学习.jdbc_mysql;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
public class TestDemo1 {
public static void main(String[] args) {
insert();
delete();
update();
query();
}
//插入
public static void insert(){
//1.
Connection conn = null;
Statement st = null;
ResultSet rs = null;
try{
conn = JDBCUtils.getConnection();
st = conn.createStatement();
int rows = st.executeUpdate("insert into employee(id,name) values (1005,'咸鱼')");
System.out.println("成功插入"+ rows+"行");
}catch (Exception e){
e.printStackTrace();
}finally {
JDBCUtils.closeAll(conn,st,null);
}
}
//删除
public static void delete(){
//1.
Connection conn = null;
Statement st = null;
ResultSet rs = null;
try{
conn = JDBCUtils.getConnection();
st = conn.createStatement();
int rows = st.executeUpdate("delete from employee where id = 1003");
System.out.println("成功删除"+ rows+"行");
}catch (Exception e){
e.printStackTrace();
}finally {
JDBCUtils.closeAll(conn,st,null);
}
}
//修改
public static void update(){
//1.
Connection conn = null;
Statement st = null;
ResultSet rs = null;
try{
conn = JDBCUtils.getConnection();
st = conn.createStatement();
int rows = st.executeUpdate("update employee set name='艾春辉' where id = 1001");
System.out.println("成功修改"+ rows+"行");
}catch (Exception e){
e.printStackTrace();
}finally {
JDBCUtils.closeAll(conn,st,null);
}
}
//查询
public static void query(){
//1.
Connection conn = null;
Statement st = null;
ResultSet rs = null;
try{
conn = JDBCUtils.getConnection();
st = conn.createStatement();
rs = st.executeQuery("select * from employee");
while (rs.next()){
Object cid = rs.getObject("id");
Object cname = rs.getObject("name");
System.out.println(cid+" "+cname);
}
}catch (Exception e){
e.printStackTrace();
}finally {
JDBCUtils.closeAll(conn,st,null);
}
}
}
JDBC:java语言操作各种数据库的技术
步骤:
注册驱动:DriverManger.register(new com.mysql.jdbc.Driver()) 或者Class.forName(“com.mysql.jdbc.Driver”)
获取链接:驱动连接串 用户名 密码
Connection conn = DriverManager.getConnection(“jdbc:mysql://ip地址:3306/数据库名”,用户名,密码)
获取sql语句执行对象
Statement st = conn.createStatement();或者PreparedStatement pst = conn.prepareStarement(String sql) pst.setObject(序号,参数)
使用执行对象执行sql语句,获取到结果集
处理结果集: rs.next()//判断有没有下一条记录 rs.getObject(属性名)
SQL注入问题:用户输入的内容作为了SQL语句语法的一部分,改变了SQL真正的意义
假设有登录案例如下:select * from 用户表 where name = username and password = password
此时,当用户输入正确的账号和密码后,查询到了信息则让用户登录,但是当用户输入账号为XXX 密码为XXX’ OR ‘a’ = 'a真正的执行代码为
select * from 用户表 where name = ‘xxx’ and password =’ xxx’ or ‘a’=’ a’;
此时,上述查询语句`永远都是可以查询出结果的,那么用户和就直接登入成功了,显然我们不希望看到这样的结果这就是sql注入问题
解决方法:使用preparedStatement:预编译对象是Statement 对象的子类,让这个sql语句中
package java学习.jdbc_mysql;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
//防注入方法
public class TestDemo2 {
public static void main(String[] args) {
insert();
delete();
update();
query();
}
//insert
public static void insert(){
Connection conn = null;
PreparedStatement pst = null;
try{
conn = JDBCUtils.getConnection();
String sql = "insert into employee(id,name) values (?,?)";
pst = conn.prepareStatement(sql);
pst.setObject(1,1006);
pst.setObject(2,"咸鱼");
pst.executeUpdate();
System.out.println("成功修改");
}catch (Exception e){
e.printStackTrace();
}finally {
JDBCUtils.closeAll(conn,pst,null);
}
}
//delete
public static void delete(){
Connection conn = null;
PreparedStatement pst = null;
try{
conn = JDBCUtils.getConnection();
String sql = "delete from empolyee where id=?";
pst = conn.prepareStatement(sql);
pst.setObject(1,1006);
pst.executeUpdate();
System.out.println("成功修改");
}catch (Exception e){
e.printStackTrace();
}finally {
JDBCUtils.closeAll(conn,pst,null);
}
}
//update
public static void update(){
Connection conn = null;
PreparedStatement pst = null;
try{
conn = JDBCUtils.getConnection();
String sql = "update employee set name=? where id = ?";
pst = conn.prepareStatement(sql);
pst.setObject(1,"艾春辉");
pst.setObject(2,"1006");
pst.executeUpdate();
System.out.println("成功修改");
}catch (Exception e){
e.printStackTrace();
}finally {
JDBCUtils.closeAll(conn,pst,null);
}
}
//query
public static void query(){
Connection conn = null;
PreparedStatement pst = null;
ResultSet rs = null;
try{
conn = JDBCUtils.getConnection();
String sql = "select * from employee where name like ?";
pst = conn.prepareStatement(sql);
pst.setObject(1,"%春%");
rs = pst.executeQuery();
while(rs.next()){
Object uid = rs.getObject("id");
System.out.println(uid);
}
System.out.println("成功修改");
}catch (Exception e){
e.printStackTrace();
}finally {
JDBCUtils.closeAll(conn,pst,null);
}
}
}
解决数据库连接耗费资源和时间很多的问题,提高性能
connection对象在JDBC使用的时候,使用的时候就会去创建一个对象,使用结束以后就会将这个对象给销毁了,每次创建和销毁对象都是耗时操作,需要使用连接词对其进行优化,程序初始化的时候,初始化多个连接,将多个连接放入到池中,每次获取的时候,都可以直接从连接池中进行获取,使用结束以后,将连接归还到池中
javax.sql.DataSource数据源:初始化多个连接,将多个连接放入到内存中,将连接对象放回到内存中
常见连接池:DBCP
在dbcp连接池中,实现javax.sql.DataSource
带有配置文件的DBCP的使用,核心类:BasicDataSourceFactory(工厂) public static DataSource createDataSource(new FileInputStream…){}
package java学习.jdbc_mysql;
import org.apache.commons.dbcp.BasicDataSource;
import org.apache.commons.dbcp.BasicDataSourceFactory;
import javax.sql.DataSource;
import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
public class DBCPUtils {
// public static String driverName = "com.mysql.jdbc.Driver";
// public static String url = "jdbc:mysql://localhost:3306/firstdb?useSSL=false";
// public static String username = "root";
// public static String password = "666";
// public static BasicDataSource ds = new BasicDataSource();
private static DataSource ds = null;
// Static code block sets the 4 major elements of ds
static {
try {
Properties ps = new Properties();
ps.load(DBCPUtils.class.getClassLoader().getResourceAsStream("dbcpconfig.properties"));
ds = BasicDataSourceFactory.createDataSource(ps);
// ds.setDriverClassName(driverName);
// ds.setUrl(url);
// ds.setUsername(username);
// ds.setPassword(password);
} catch (Exception e) {
}
}
public static Connection getConnection() throws SQLException {
//return connection object ,not from Drivermanager but from DBCPUtils
return ds.getConnection();
}
//关闭资源
public static void closeAll(Connection conn, Statement st, ResultSet rs) {
if (conn == null) {
try {
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
if (st == null) {
try {
st.close();
} catch (Exception e) {
e.printStackTrace();
}
}
if (rs == null) {
try {
rs.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
DBUtils:主要负责关闭连接,释放资源,开启事物等操作
QueryRunner:负责我们对象的数据库增删改查操作(核心类)
ResultSetHandler:结果集处理类,帮助我们处理结果集,帮助我们封装数据的
QueryRunner:类的使用
构造:public QueryRunner(DataSource ds)需要一个连接池
方法:update(String sql, Object …params)//主要执行增删改 query(String sql, ResultSetHandler,Object …params)//主要执行查询操作
ResultSetHandler是一个接口:实现类
ArrayHandler:将结果集中的第一条记录封装到一个Object数组中,数组中每一个元素就是这条记录,就是将数据库中的目标内容拿出来,但是只会处理第一条
ArrayListHandler:同上,但是会把所有的相关内容打出来,而不是只打印一条
//create QueryRunner Object
QueryRunner qr = new QueryRunner(C3P0Utils.getDataSource());
//query
String sql = "select * from employee";
List
BeanHandler处理类:会把对象按照一个类的格式存储,只处理一个
//create QueryRunner Object
QueryRunner qr = new QueryRunner(C3P0Utils.getDataSource());
//query
String sql = "select * from employee";
Category c = qr.query(sql,new BeanHandler(Category.class));
System.out.println(c);
package com.itheima.domain;
/**
* 标准的javabean
* @author yingpeng
*
*/
public class Category {
private String cid;
private String cname;
public String getCid() {
return cid;
}
public void setCid(String cid) {
this.cid = cid;
}
public String getCname() {
return cname;
}
public void setCname(String cname) {
this.cname = cname;
}
@Override
public String toString() {
return "Category [cid=" + cid + ", cname=" + cname + "]";
}
public Category() {
super();
// TODO Auto-generated constructor stub
}
public Category(String cid, String cname) {
super();
this.cid = cid;
this.cname = cname;
}
}
BeanListHandler处理类:会把对象按照一个类的格式存储,存储全部事件
ClumnListHandler,将结果指定的列字段值,封装在list中
//create QueryRunner Object
QueryRunner qr = new QueryRunner(C3P0Utils.getDataSource());
//query
String sql = "select * from employee";
List c = qr.query(sql,new ColumnListHandler("id"));
System.out.println(c);
MapHandler:键值对,储存两列,但是只返回第一组数据,key就是字段名称,value就是字段值
MapListHandler:键值对,能返回全部组数据
ScalarHandler:它是用于单个数据,一般是聚合函数的操作: select count(*) from 表操作
//create QueryRunner Object
QueryRunner qr = new QueryRunner(C3P0Utils.getDataSource());
//query
String sql = "select * from employee";
Integer count = qr.query(sql,new ScalarHandler());
System.out.println(count);
C3P0是一个开源的JDBC连接池,它实现了数据源和JND绑定,支持JDBC3规范和JDBC2的扩展,对于后面要学的框架有很大帮助
在连接池中,遵循了javax.sql.DataSource接口的实现类:ComboPooledDataSource
package java学习.jdbc_mysql;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import java.sql.Connection;
import java.sql.SQLException;
public class C3P0Utils {
// public static String driverName = "com.mysql.jdbc.Driver";
// public static String url = "jdbc:mysql://localhost:3306/firstdb?useSSL=false";
// public static String username = "root";
// public static String password = "666";
public static ComboPooledDataSource ds = new ComboPooledDataSource();
// Static code block sets the 4 major elements of ds
static {
try {
// ds.setDriverClass(driverName);
// ds.setJdbcUrl(url);
// ds.setUser(username);
// ds.setPassword(password);
}catch (Exception e){
}
}
public static Connection getConnection() throws SQLException {
//return connection object ,not from Drivermanager but from DBCPUtils
return ds.getConnection();
}
}
c3p0配置:
com.mysql.jdbc.Driver
jdbc:mysql://localhost:3306/firstdb?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=UTC
root
666
10
需求:设计一个界面,输入三个值,一个收款人,一个收款人,一个转账的金额,不嗯给你出现付款人的钱被扣除而收款人的钱为到账
事务的概述:什么是事务:事务指的是逻辑上的一组操作,组成这组操作的各个单元要么全都成功,要么全都失败.事务作用:保证在一个事务中多次操作要么全都成功,要么全都失败.实例:
update account set money=money-100 where name='tom'//tom转出100块
update account set money=money+100 where name='jerry'//jerry收到100块
以上两个sql语句,我们需要把他们看成一个事务
sql语句
package java学习.jdbc案例;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
//模拟jack给tom转帐1000元
//update account set money=money-1000 where name = 'jack'
//update account set money=money+1000 where name = 'tom'
public class AccountDemo {
public static void main(String[] args) throws Exception{
Statement st = null;
Connection conn = null;
try {
//注册驱动
Class.forName("com.mysql.jdbc.Driver");
//获取连接
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/day06?useSSL=false","root","***");
//在所有操作之前开启事务
conn.setAutoCommit(false);//设置自动提交事务,就是开启事务
//获取sql执行对象
st = conn.createStatement();
//1.jack减少1000
int row1 = st.executeUpdate("update account set money=money-1000 where name = 'jack'");
System.out.println(1 / 0);
//2 tom收入1000元
int row2 = st.executeUpdate("update account set money=money+1000 where name = 'tom'");
//所有操作之后 提交事务
conn.commit();
if (row1 > 0 && row2 > 0)
System.out.println("转账成功");
}catch (Exception e)
{
System.out.println("出现事故,进行回滚");
conn.rollback();
//auto-generated catch block
e.printStackTrace();
}
//释放资源
st.close();
// conn.close();
}
}
为了支持事务,不能传递连接池//QueryRunner qr = new QueryRunner
package java学习.jdbc案例;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
public class C3P0Utils {
public static String driverName = "com.mysql.jdbc.Driver";
public static String url = "jdbc:mysql://localhost:3306/day06?useSSL=false";
public static String username = "root";
public static String password = "***";
public static ComboPooledDataSource ds = new ComboPooledDataSource();
// Static code block sets the 4 major elements of ds
static {
try {
ds.setDriverClass(driverName);
ds.setJdbcUrl(url);
ds.setUser(username);
ds.setPassword(password);
}catch (Exception e){
}
}
public static Connection getConnection() throws SQLException {
//return connection object ,not from Drivermanager but from DBCPUtils
return ds.getConnection();
}
public static DataSource getDataSource(){
return ds;
}
}
package java学习.jdbc案例;
import org.apache.commons.dbutils.QueryRunner;
import java.sql.Connection;
import java.sql.SQLException;
public class AccountDemo2 {
public static void main(String[] args) throws SQLException {
//创建一个QueryRunner对象
QueryRunner qr = new QueryRunner();//为了使用事务,不能使用带参数的构造函数
Connection conn = null;
try {
conn = C3P0Utils.getConnection();
System.out.println(qr);
//开启事务
conn.setAutoCommit(false);
//执行转账功能
//减钱
int row1 = qr.update(conn, "update account set money=money-? where name = ?", 1000, "jack");
//加钱
int row2 = qr.update(conn, "update account set money=money+? where name = ?", 1000, "tom");
//提交事务
conn.commit();
if (row1 > 0 && row2 < 0)
System.out.println("转账成功");
}catch (Exception e)
{
conn.rollback();
System.out.println("转账出现问题,程序失败");
e.printStackTrace();
}
}
}
数据库操作底层
package java学习.jdbc案例.dao;
import java学习.jdbc案例.utils.C3P0Utils;
import java学习.jdbc案例.utils.ConnectionManager;
import org.apache.commons.dbutils.QueryRunner;
import java.sql.Connection;
import java.sql.SQLException;
//转账的dao层,主要操作数据库
public class AccountDAO {
//转账出去
public void fromAccount(String fromName, double money)throws SQLException{
Connection conn = ConnectionManager.getConnection();
//创建query对象
QueryRunner qr = new QueryRunner();
//执行减钱操作
qr.update(conn,"update account set money=money-? where name=?",money,fromName);
}
//收钱
public void toAccount(String toName,double money)throws SQLException{
Connection conn = ConnectionManager.getConnection();
//创建一个QueryRunner对象
QueryRunner qr = new QueryRunner(C3P0Utils.getDataSource());
//加钱操作
qr.update(conn,"update account set money=money+? where name=?",money,toName);
}
}
转账功能的业务层
package java学习.jdbc案例.service;
import java学习.jdbc案例.C3P0Utils;
import java学习.jdbc案例.dao.AccountDAO;
import java学习.jdbc案例.utils.ConnectionManager;
import java.sql.Connection;
public class AccountService {
//转账业务
public void transfer(String fromName,String toName,double money){
//直接调用业务层
AccountDAO dao = new AccountDAO();
Connection conn = null;
try {
conn = ConnectionManager.getConnection();
//开启事务
ConnectionManager.start();
//转出去
dao.fromAccount(fromName, money);
//拿回来
dao.toAccount(toName, money);
//提交事务
conn.commit();
System.out.println("成功");
}catch (Exception e){
e.printStackTrace();
System.out.println("程序失败,事务回滚");
try {
conn.rollback();
}catch (Exception e1)
{
e1.printStackTrace();
}
}finally {
try {
conn.close();
}catch (Exception e2)
{
e2.printStackTrace();
}
}
}
}
工具类层:
两个工具类:
package java学习.jdbc案例.utils;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
public class C3P0Utils {
public static String driverName = "com.mysql.jdbc.Driver";
public static String url = "jdbc:mysql://localhost:3306/day06?useSSL=false";
public static String username = "root";
public static String password = "666";
public static ComboPooledDataSource ds = new ComboPooledDataSource();
// Static code block sets the 4 major elements of ds
static {
try {
ds.setDriverClass(driverName);
ds.setJdbcUrl(url);
ds.setUser(username);
ds.setPassword(password);
}catch (Exception e){
}
}
public static Connection getConnection() throws SQLException {
//return connection object ,not from Drivermanager but from DBCPUtils
return ds.getConnection();
}
public static DataSource getDataSource(){
return ds;
}
}
package java学习.jdbc案例.utils;
import java.sql.Connection;
import java.sql.SQLException;
//连接管理类,主要负责获取连接,开启事务,提交事务,回滚事务
public class ConnectionManager {
//定义一个集合ThreadLocal对象来保存当前线程连接
private static ThreadLocal tl = new ThreadLocal();
//获取连接
public static Connection getConnection() throws SQLException {
//从tl中获取连接
Connection conn = tl.get();
if(conn == null){
conn = C3P0Utils.getConnection();
tl.set(conn);
}
return conn;
}
//开启事务
public static void start() throws SQLException{
ConnectionManager.getConnection().setAutoCommit(false);
}
//提交事务
public static void commit() throws SQLException{
ConnectionManager.getConnection().commit();
}
//回滚事务
public static void rollback() throws SQLException{
ConnectionManager.getConnection().rollback();
}
//关闭连接
public static void close() throws SQLException{
ConnectionManager.getConnection().close();
}
}
事务特性解释:
原子性:强调事务的不可分割.
一致性:事务的执行的前后,数据的完整性保持一致.
隔离性:一个事务在执行的过程中,不应该受到其他事务的干扰.
持久性:事务一旦结束,数据就持久到数据库中
如果不考虑事务的隔离性,引发一些安全问题
脏读 :一个事务读到了另一个事务未提交的数据.
不可重复读 :一个事务读到了另一个事务已经提交(update)的数据.引发一个事务中的多次查询结果不一致.
虚读/幻读 :一个事务读到了另一个事务已经提交的(insert)数据.导致多次查询的结果不一致
设置事务的隔离级别:
read uncommitted :脏读,不可重复读,虚读都可能发生.
read committed :避免脏读,但是不可重复读和虚读有可能发生.(Oracle默认)
repeatable read :避免脏读和不可重复读,但是虚读有可能发生的(MySql默认)
serializable :避免脏读,不可重复读和虚读.(串行化的-不可能出现事务并发访问)
使用JDBC进行隔离级别的设置
首先使用mvc思想进行设计,我设计的内容框架是这样的
productDao:实际操作数据库
package java学习.jdbc案例.demo2.service;
//商品service层
import java学习.jdbc案例.demo2.dao.ProductDao;
import java学习.jdbc案例.demo2.domain.Product;
import java学习.jdbc案例.demo2.utils.C3P0Utils;
import java学习.jdbc案例.demo2.utils.ConnectionManager;
import org.apache.commons.dbutils.QueryRunner;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
public class ProductService {
//添加商品
public void addProduct(Product p){
ProductDao dao = new ProductDao();
try{
dao.addProduct(p);
}catch (Exception e)
{
e.printStackTrace();
}
}
public Product findById(int id)throws SQLException {
ProductDao dao = new ProductDao();
Product p = null;
try {
p = dao.findById(id);
}catch (Exception e){
e.printStackTrace();
}
return p;
}
//修改商品
public void updateProduct(Product p){
ProductDao dao = new ProductDao();
try{
dao.updateProduct(p);
}catch (Exception e){
e.printStackTrace();
}
}
//查询所有商品
public List findAll() throws SQLException{
ProductDao dao = new ProductDao();
List ps = null;
try{
ps = dao.findAll();
}catch (SQLException e){
e.printStackTrace();
}
return ps;
}
//根据id删除商品
public void deleteById(int id)throws SQLException{
ProductDao dao = new ProductDao();
try{
dao.deleteByOneId(id);
}catch (SQLException e){
e.printStackTrace();
}
}
//批量删除商品
public void deleteAll(List ids)throws SQLException{
//循环调用deleteById方法
ProductDao dao = new ProductDao();
try{
ConnectionManager.start();
for (int id:ids) {
dao.deleteById(id);
System.out.println(1/0);
}
ConnectionManager.commit();
}catch(Exception e){
e.printStackTrace();
ConnectionManager.rollback();
}
}
}
Product:结构层,主要对应的是数据库里面的一个表的字段
package java学习.jdbc案例.demo2.domain;
public class Product {
private int pid;
private String pname;
private int price;
private String flag;
private String category_id;
public int getPid() {
return pid;
}
public void setPid(int pid) {
this.pid = pid;
}
public String getPname() {
return pname;
}
public void setPname(String pname) {
this.pname = pname;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public String getFlag() {
return flag;
}
public void setFlag(String flag) {
this.flag = flag;
}
public String getCategory_id() {
return category_id;
}
public void setCategory_id(String category_id) {
this.category_id = category_id;
}
@Override
public String toString() {
return "Product [pid=" + pid + ", pname=" + pname + ", price=" + price + ", flag=" + flag + ", category_id="
+ category_id + "]";
}
public Product() {
super();
// TODO Auto-generated constructor stub
}
public Product(int pid, String pname, int price, String flag, String category_id) {
super();
this.pid = pid;
this.pname = pname;
this.price = price;
this.flag = flag;
this.category_id = category_id;
}
public Product(String pname, int price) {
super();
this.pname = pname;
this.price = price;
}
}
ProductService :服务层,上接视图层,下接数据库操作层
package java学习.jdbc案例.demo2.service;
//商品service层
import java学习.jdbc案例.demo2.dao.ProductDao;
import java学习.jdbc案例.demo2.domain.Product;
import java学习.jdbc案例.demo2.utils.C3P0Utils;
import java学习.jdbc案例.demo2.utils.ConnectionManager;
import org.apache.commons.dbutils.QueryRunner;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
public class ProductService {
//添加商品
public void addProduct(Product p){
ProductDao dao = new ProductDao();
try{
dao.addProduct(p);
}catch (Exception e)
{
e.printStackTrace();
}
}
public Product findById(int id)throws SQLException {
ProductDao dao = new ProductDao();
Product p = null;
try {
p = dao.findById(id);
}catch (Exception e){
e.printStackTrace();
}
return p;
}
//修改商品
public void updateProduct(Product p){
ProductDao dao = new ProductDao();
try{
dao.updateProduct(p);
}catch (Exception e){
e.printStackTrace();
}
}
//查询所有商品
public List findAll() throws SQLException{
ProductDao dao = new ProductDao();
List ps = null;
try{
ps = dao.findAll();
}catch (SQLException e){
e.printStackTrace();
}
return ps;
}
//根据id删除商品
public void deleteById(int id)throws SQLException{
ProductDao dao = new ProductDao();
try{
dao.deleteByOneId(id);
}catch (SQLException e){
e.printStackTrace();
}
}
//批量删除商品
public void deleteAll(List ids)throws SQLException{
//循环调用deleteById方法
ProductDao dao = new ProductDao();
try{
ConnectionManager.start();
for (int id:ids) {
dao.deleteById(id);
System.out.println(1/0);
}
ConnectionManager.commit();
}catch(Exception e){
e.printStackTrace();
ConnectionManager.rollback();
}
}
}
C3P0Utils和ConnectionManager:工具类集合,两个工具类,一个是配置数据库连接,一个是管理数据库连接
package java学习.jdbc案例.demo2.utils;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
public class C3P0Utils {
public static String driverName = "com.mysql.jdbc.Driver";
public static String url = "jdbc:mysql://localhost:3306/day07?useSSL=false";
public static String username = "root";
public static String password = "***";
public static ComboPooledDataSource ds = new ComboPooledDataSource();
// Static code block sets the 4 major elements of ds
static {
try {
ds.setDriverClass(driverName);
ds.setJdbcUrl(url);
ds.setUser(username);
ds.setPassword(password);
}catch (Exception e){
}
}
public static Connection getConnection() throws SQLException {
//return connection object ,not from Drivermanager but from DBCPUtils
return ds.getConnection();
}
public static DataSource getDataSource(){
return ds;
}
}
package java学习.jdbc案例.demo2.utils;
import java学习.jdbc案例.demo2.utils.C3P0Utils;
import java.sql.Connection;
import java.sql.SQLException;
//连接管理类,主要负责获取连接,开启事务,提交事务,回滚事务
public class ConnectionManager {
//定义一个集合ThreadLocal对象来保存当前线程连接
private static ThreadLocal tl = new ThreadLocal();
//获取连接
public static Connection getConnection() throws SQLException {
//从tl中获取连接
Connection conn = tl.get();
if(conn == null){
conn = C3P0Utils.getConnection();
tl.set(conn);
}
return conn;
}
//开启事务
public static void start() throws SQLException{
ConnectionManager.getConnection().setAutoCommit(false);
}
//提交事务
public static void commit() throws SQLException{
ConnectionManager.getConnection().commit();
}
//回滚事务
public static void rollback() throws SQLException{
ConnectionManager.getConnection().rollback();
}
//关闭连接
public static void close() throws SQLException{
ConnectionManager.getConnection().close();
}
}
ProductView:视图层
package java学习.jdbc案例.demo2.view;
import java学习.jdbc案例.demo2.domain.Product;
import java学习.jdbc案例.demo2.service.ProductService;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class ProductView {
public static void main(String[] args) throws SQLException{
//显示菜单
System.out.println("欢迎来到商品管理系统,请输入命令进行操作:");
while (true) {
System.out.println("C:新增 U:修改 D:删除 DA:批量删除 FI:查询 FA:查询所有 Q:退出");
//获取用户输入
Scanner sc = new Scanner(System.in);
String userSelect = sc.nextLine();
//判断用户输入的到底是哪一个命令
switch (userSelect.toUpperCase()) {
case "C":
//新增商品
addProduct();
break;
case "U":
//修改商品
editProduct();
break;
case "D":
//删除商品
deleteProduct();
break;
case "DA":
//删除全部商品
deleteAllProduct();
break;
case "FI":
//根据id查询
findById();
break;
case "FA":
//查询所有商品
findAll();
break;
case "Q":
//退出
System.out.println("退出");
System.exit(0);//结束正在执行的jvm虚拟机
break;
default:
System.out.println("请重新输入");
break;
}
}
}
//添加商品功能
private static void addProduct(){
Scanner sc = new Scanner(System.in);
System.out.println("您选择了新增商品功能");
//请输入新的商品名字
System.out.println("请输入新增商品名字:");
String name = sc.nextLine();
//请输入新的商品价格
System.out.println("请输入新的商品价格:");
int price = Integer.parseInt(sc.nextLine());
//封装成商品对象
Product p = new Product(name,price);
//调用service层的添加商品方法
ProductService service = new ProductService();
service.addProduct(p);
System.out.println("新增商品成功");
}
private static void editProduct()throws SQLException{
Scanner sc = new Scanner(System.in);
System.out.println("您选择了修改商品功能");
//请输入需要修改的商品编号
System.out.println("请输入需要修改的商品编号:");
int id = Integer.parseInt(sc.nextLine());
//查询数据库,如果有就告诉用户选择商品是什么信息
ProductService service = new ProductService();
Product p = service.findById(id);
if(p==null)
System.out.println("您要修改的商品不存在,商品编号是"+id);
else{
//商品存在
System.out.println("您要修改的商品信息如下:");
System.out.println(p);
//请输入商品新的名字
System.out.println("请输入商品新的名字:");
String newName = sc.nextLine();
//请输入新的商品价格
System.out.println("请输入商品新的价格:");
int newprice = Integer.parseInt(sc.nextLine());
//设置新的名字和价格
p.setPname(newName);
p.setPrice(newprice);
//调用service层
service.updateProduct(p);
System.out.println("修改商品成功");
}
}
private static void deleteProduct()throws SQLException{
Scanner sc = new Scanner(System.in);
System.out.println("您选择了删除商品功能");
System.out.println("请输入要删除的商品编号:");
int id = Integer.parseInt(sc.nextLine());
//如果有则告诉此id商品的具体信息
ProductService service = new ProductService();
Product p = service.findById(id);
if(p == null)
{
System.out.println("查无此商品");
}else {
System.out.println("您要删除的商品如下");
System.out.println(p);
System.out.println("是否删除此商品?:Y/N");
String isOrNot = sc.nextLine();
if("Y".equals(isOrNot.toUpperCase()))
{
service.deleteById(id);
System.out.println("删除商品成功");
}else {
System.out.println("操作取消");
}
}
}
private static void deleteAllProduct()throws SQLException{
Scanner sc = new Scanner(System.in);
ProductService service = new ProductService();
System.out.println("您选择了批量删除商品功能");
//创建一个集合
List ids = new ArrayList<>();
while (true) {
System.out.println("请输入您要删除的商品编号,(-1表示结束)");
int deleteId = Integer.parseInt(sc.nextLine());
if(deleteId == -1){
break;
}
Product p = service.findById(deleteId);
if (p != null) {
ids.add(deleteId);
System.out.println("已经标记此商品...");
} else {
System.out.println("此商品不存在,请重新输入");
}
}
if (ids.isEmpty()){
System.out.println("批量删除操作已经取消");
}else{
System.out.println("您一共标记了"+ids.size()+"个商品");
System.out.println("您确定都要删除吗? y/n");
String isOrNot = sc.nextLine();
if ("Y".equals(isOrNot.toUpperCase())){
service.deleteAll(ids);
System.out.println("删除商品成功");
}else
System.out.println("删除取消");
}
}
private static void findById()throws SQLException{
Scanner sc = new Scanner(System.in);
System.out.println("您选择了查询商品功能");
//请输入您要查询的商品编号
System.out.println("请输入您要查询的商品编号:");
int id = Integer.parseInt(sc.nextLine());
//查询数据库,查看是否有此方法,调用service方法
ProductService service = new ProductService();
Product p = service.findById(id);
//展示并进行判断
if (p==null)
System.out.println("查询商品不存在,请确认后输入");
else {
System.out.println("查询商品---"+ p);
System.out.println("查询商品成功");
}
}
private static void findAll()throws SQLException{
System.out.println("您选择了查询全部商品功能");
ProductService service = new ProductService();
List ps = service.findAll();
if (ps == null)
System.out.println("您的仓库里面没有商品");
else {
for (Product p : ps) {
System.out.println(p);
}
System.out.println("查询商品成功");
}
}
}
SQL语句:
DDL:数据库定义语言:数据库定义语言,主要对数据库,表,列进行增删改查
DCL:数据库控制语言
DML:数据库操作语言:
DQL:数据库查询语言
单表查询: select * from 表名 where 条件:> < >= <= = != <>
区间: berween .. and .. 只能判断数值和日期
like '表达式' ,符号_表示任意一个字符,符号%表示任意个任意字符
排序查询:select * from 表名 order by 字段 ASC(默认升序 |DESC(降序;)
聚合查询:select count(*)|max(数值字段)|min(数值字段)|sum(数值字段)|avg(数值字段) from 表名 注意事项:聚合函数查询出来的只有一个值,会忽略null
分组查询: 字段1,字段2,from 表名 group by 某个字段;在分组查询中,要查询的字段必须是分组字段,也可以是聚合函数
分页查询:select * from 表名 limit 第几条记录,要查询第三条记录:比如我要查询第m页,每页有n条记录 第一页:limit (1-1)*n,n; 第二页: limit n,n;
去重复: select distinct 字段...from 表
多表查询:
一对多:必须两张表,一张主表,一张从表;
原则:从表必须有一个外键,这个外间引用主表的主键
添加外检约束:alter table 从表 add constraint 主表_从表_fk foreign key (从表外键名) references 主表(主键名);
多对多: 必须有三张表:两张正常表,一张中间表
原则;中间表,至少有两个字段,分别是外键,引用两张表的主键
多表查询语句:
1. 交叉查询:本身错误,实际上是一种笛卡尔积的东西: select * from 表1,表2;
2. 内连接:在交叉连接的基础上,添加条件
隐式内连接:不写inner join 后面的条件用where判断
显示内连接:写上inner join 后面用on 来表示
3. 外连接:关键字 outer join
左外连接:left outer join
右外连接:right outer join