大家可以关注一下我的博客 我的博客所有随笔都是我从基础开始学习java的所有知识点
1. Jdbc概述
问题:实际开发中,不可能用工具或者命令行操作数据库,数据库表中的数据最终要使用Java程序来操作,那么Java中如何操作数据库中的数据呢?
答 : 在Java语言中,有一个专门连接数据库的规范(JDBC),专门负责连接数据库进行数据操作的规范
JDBC只是SUN编写的一堆接口(规范的体现),SUN公司自己并没有实现
问题 : 为什么SUN只定义一个JDBC规范,而不实现呢?
答 : 因为市面上的数据库很多,每个数据库内部接口不会向外暴露,而且即便是暴露让SUN去实现,市面上很多数据库全部要SUN来实现不现实
实际中哪个数据库需要支持JAVA语言,就需要自己实现Java的JDBC规范,因为实现了JDBC很多接口,那么就会有很多实现类,而很多实现类在java中会使用一个专门的包封装起来,叫做jar包(在JDBC中叫做驱动包),各大数据库产商实现JDBC规范以后都会把他们jar包放在官网上以供开发者下载使用
JDBC:(Java DataBase Connectivity):
是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口组成。
JDBC规范对应的api包
案例使用JDBC操作MySQL数据库:
1. 创建普通java项目
2. 在项目下面新建一个lib目录(new键--》folder)
3. 将MySQL驱动包拷贝到项目中并添加依赖(build path--》add to build path)
4. 开始写代码
DDL创建表:
package jdbc;
//连接使用oracle数据库
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
import org.junit.Test;
public class Test01 {
/**
* Java中单元测试方法的 创建
*
* 在空白处 写 test,使用快捷键 alt+/ 提示,选择 junit4
* 会自动补全 junit4单元测试的方法
* 在方法上面有一个注解,默认报错的
* 因为:单元测试是一个框架,默认eclipse以及集成了,用户把鼠标放置在 注解上面,按提示导入junit4 依赖即可
* 单元测试方法和main方法区别
* junit单元测试方法在一个类中可以有多个方法,每个一个方法可以独立运行
* main 主方法一个类中只能有一个方法,不太方便多个功能的测试
*
* 单元测试方法的运行,光标放置在单元测试方法上面,点击数据右键 【run as ->junit test】
* 绿条:表示成功
* 红条:表示程序可能异常
*/
@Test
public void testName1() throws Exception {
//创建表操作:要执行的sql代码
String sql="create table t_student(sid number(4) constraint pk_sid primary key,name varchar2(20))";
//1,加载注册驱动
Class.forName("oracle.jdbc.OracleDriver");
/*加载注册驱动.(mysql的)
就是把驱动中的Driver字节码加载到JVM中.
Class.forName("com.mysql.jdbc.Driver");
为什么这句话就可以加载注册驱动?
第一步:把com.mysql.jdbc.Driver.class这份字节码加载到JVM中.
第二步:当一份字节码被加载进JVM,马上就会执行该字节码中的静态代码块.
第三步:该静态代码中,就在完成,先创建驱动对象,再注册.
* */
//2,获取数据库连接("jdbc:oracle:thin:@127.0.0.1:1521:数据库名","账号","密码")
Connection conn= DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:orcl","scott","tiger");
/*jdbc:mysql://localhost:3306/dbName
jdbc:mysql:// :连接MySQL数据库的协议,不同数据库协议不一样
localhost:3306 :数据库软件的主机和端口
dbName : 具体要连接数据库
验证已经获取连接:可以在MySQL控制台,使用命令:show processlist; 查看MySQL运行进程.
* */
//3,创建语句对象(用于执行SQL语句的对象)
Statement c = conn.createStatement();
//4, 执行SQL语句
c.executeUpdate(sql);
//5,释放资源(先开后关)
c.close();
conn.close();
}
}
package jdbc;
//连接使用mysql数据库
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
import org.junit.Test;
public class Test02 {
@Test
public void testName1() throws Exception {
//创建一个学生表
//创建表的mysql操作:要执行的sql代码
String sql="create table t_student(id int primary key auto_increment,name varchar(50),age int)";
//1.加载注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2.获取数据库连接对象
Connection conn= DriverManager.getConnection("jdbc:mysql://localhost:3306/lin01", "root", "root");
//3.创建语句对象(用于执行SQL语句)
Statement st=conn.createStatement();
//4.执行SQL语句
st.executeUpdate(sql);
//5.释放资源(先开后关)
st.close();
conn.close();
}
}
DML:表的增删改:
package jdbc;
//连接使用mysql数据库
import static org.junit.Assert.*;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
import org.junit.Test;
public class Test02 {
@Test
public void testName1() throws Exception {
//DML 增:
//创建表的mysql操作:要执行的sql代码
String sql=("insert into t_student(name,age) values ('张三',20)");
//1.加载注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2.获取数据库连接对象
Connection conn= DriverManager.getConnection("jdbc:mysql://localhost:3306/lin01", "root", "root");
//3.创建语句对象(用于执行SQL语句)
Statement st=conn.createStatement();
//4.执行SQL语句
st.executeUpdate(sql);
//5.释放资源(先开后关)
st.close();
conn.close();
}
public void testName2() throws Exception{
//DML 删:
String sql=("delete from t_student where id=2");
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/lin01", "root", "root");
Statement st=conn.createStatement();
st.executeUpdate(sql);
st.close();
conn.close();
}
@Test
public void testName3() throws Exception {
//DML 改:
String st="update t_student set name='李四',age=15 where id=1";
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/lin01", "root", "root");
Statement cr= conn.createStatement();
cr.executeUpdate(st);
cr.close();
conn.close();
}
}
DQL表的查询:
package jdbc;
//学生类
public class Student {
private int id ;
private String name;
private Integer age;
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 Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Student(int id, String name, Integer age) {
super();
this.id = id;
this.name = name;
this.age = age;
}
public Student() {
super();
}
@Override
public String toString() {
return "Student [id=" + id + ", name=" + name + ", age=" + age + "]";
}
}
package jdbc;
//连接使用mysql数据库
import static org.junit.Assert.*;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
public class Test02 {
@Test
public void testName1() throws Exception {
//多行查询
String str="select * from t_student";
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/lin01", "root", "root");
Statement cr = conn.createStatement();
ResultSet ex = cr.executeQuery(str);
//创建一个学生类
//申明一个list集合,封装一个个学生对象
List<Student> stu = new ArrayList<Student>();
while(ex.next()){
//1.通过列的位置获取对应的数据 从1开始(如果不知道类型就用Object)
Object id = ex.getObject(1);
Object name = ex.getObject(2);
Object age = ex.getObject(3);
System.out.println(id+"\t"+name+"\t"+age);
cr.close();
conn.close();
//2.通过列的名称获取对应的数据((知道类型就用相应的类型)
int id1 = ex.getInt("id");
String name1 = ex.getString("name");
int age1 = ex.getInt("age");
System.out.println(id1+"\t"+name1+"\t"+age1);
cr.close();
conn.close();
//3.将每一行数据封装成一个个Student对象
////快速生成变量,光标放在 代码末尾, ctrl+1 提示
int id2 = ex.getInt("id");
String name2 = ex.getString("name");
int age2 = ex.getInt("age");
Student student = new Student(id2,name2,age2);
stu.add(student);
}
for (Student student : stu){
System.out.println(student);
}
ex.close();
cr.close();
conn.close();
}
}
package jdbc;
//连接使用mysql数据库
import static org.junit.Assert.*;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
public class Test02 {
@Test
public void testName1() throws Exception {
//单行查询
String str="select * from t_student where id=7";
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/lin01", "root", "root");
Statement cr = conn.createStatement();
ResultSet ex = cr.executeQuery(str);
List<Student> stu=new ArrayList<Student>();
if(ex.next()){
int id = ex.getInt("id");
String name = ex.getString("name");
int age = ex.getInt("age");
Student stud=new Student(id,name,age);
stu.add(stud);
}
System.out.println(stu);
}
}
预编译语句对象PreparedStatment
问题 : 我们有了Statment对象可以执行SQL,为什么还要使用PreparedStatment?
优势
- SQL语句结构清晰,参数的设置和SQL语句分离
- 性能更高
- 防止SQL注入
Statement: 表示静态SQL语句对象.
PreparedStatement:Statement的子接口,表示预编译SQL语句对象. 通过占位符(?)来拼SQL.
package jdbc;
//连接使用mysql数据库
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import org.junit.Test;
public class Test02 {
@Test
public void testName1() throws Exception {
//使用预编译语句对象执行DML操作
//模板sql语句(增加数据)
String sql="insert into t_student(name,age) values(?,?) ";
/**删除:String sql = "delete from t_student where id = ?";
* 修改:String sql = "update t_student set name = ?,age=? where id = ?";
*/
// 1.加载注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 2.获取数据库连接对象
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/lin01", "root", "root");
// 3.创建预编译语句对象
PreparedStatement pr = conn.prepareStatement(sql);
//3.1设置预编译语句对象占位符对应的参数值
pr.setString(1, "maxysh");
pr.setInt(2, 99);
// 4.执行SQL语句 (注意:方法不能带sql参数)
pr.executeUpdate();
// 5.释放资源
pr.close();
conn.close();
}
}
package jdbc;
//连接使用mysql数据库
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
public class Test02 {
@Test
public void testName1() throws Exception {
//使用预编译语句对象执行DML操作
//模板sql语句(查询数据)
String sql="select * from t_student ";
// 1.加载注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 2.获取数据库连接对象
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/lin01", "root", "root");
// 3.创建预编译语句对象
PreparedStatement pr = conn.prepareStatement(sql);
// 4.执行SQL语句 (注意:方法不能带sql参数)
ResultSet ex = pr.executeQuery();
//申明一个list集合,封装一个个学生对象
List<Student> students = new ArrayList<Student>();
while(ex.next()){
int id = ex.getInt("id");
String name = ex.getString("name");
int age = ex.getInt("age");
Student stu=new Student(id,name,age);
students.add(stu);
}
System.out.println(students);
// 5.释放资源
ex.close();
pr.close();
conn.close();
}
}
JavaWeb开发的分层设计-三层架构
DAO层设计
实际开发中,JavaWeb开发代码一般分为三层,分层结构是JavaWeb开发中的一种设计思想,这样会让我们开发层次分明,每一层只要完成对应的功能即可,使得项目便于开发和维护
1 . Web层/表现层 : 主要接受前台浏览器用户的参数,给浏览器响应数据等等
2.Service层/业务成/服务层:主要处理业务功能,日志,权限,事物,等等
3.DAO层/持久层 :专门负责和数据库交互,数据处理相关代码
DAO : Data Access Object 数据访问对象
实际开发中 : 用户请求到-Web层--->Service层-->DAO层
使用DAO以后代码的以及包的设计结构
开发中如果使用的分层,编写的包和类名接口名等等都是有固定规则,不能随便瞎写
DAO层接口包命名
公司域名倒写+项目名称/模块名称+dao 如 : cn.sxt.crm.dao
DAO层实现类包命名
公司域名倒写+项目名称/模块名称+dao+impl 如 : cn.sxt.crm.dao.impl
DAO层操作对应表的接口命名
对应表的名称 + Dao/DAO 如 : StudentDao/DAO , TeacherDao/DAO
DAO层操作对应表的实现类命名
对应表的名称 + Dao/DAOImpl 如 : StudentDaoImpl/DAOImpl , TeacherDaoImpl/DAOImpl
数据表对应的Java类domain/pojo包命名
POJO(Plain Ordinary Java Object)简单的Java对象
domian : 域对象
公司域名倒写+项目名称/模块名称+domain/pojo 如 : cn.sxt.crm.domain
对应的测试包命名
公司域名倒写+项目名称/模块名称+test 如 : cn.sxt.crm.test
项目的工具类包命名
公司域名倒写+项目名称/模块名称+util/utils 如 : cn.sxt.crm.util/utils
package cn.sxt.crm.test;
import java.io.InputStream;
import java.util.Properties;
import org.junit.Test;
/*new --->file
* ClassLoader 类加载器
* ClassLoader :可以从项目的类路径下面读取对应的配置文件返回一个输入流
* ClassLoader 在程序运行的时候JVM已经为每一个项目都创建了一个,我们开发者只需要获取即可
* 获取类加载器方式
* 1、使用当前线程
* ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
* 2、通过某一类的字节码实例也可以获取
* ClassLoader classLoader = PropertiesTest.class.getClassLoader();
*/
//ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
//使用类加载器获取项目 类路径下面的文件
//InputStream inputStream = classLoader.getResourceAsStream("db.properties");
/*
* Properties 是Map集合下面的一个 专门用于读取配置文件的对象
* 可以读取当前类路径下面的 xxx.properites类型的配置文件
*
* xxx.properites的内容必须是key=value 键值对的数据
*/
public class PropertiesTest {
@Test
public void test1() throws Exception {
//1.使用当前线程可以获取类加载器
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
//2.使用类加载器读取db.properties配置文件
InputStream in = classLoader.getResourceAsStream("dp.properties");
//3.创建Properties对象(专门读取xxx.properties配置文件中的内容,本质就是Map集合,数据结构key--->value)
Properties p = new Properties();
//4.加载配置文件
p.load(in);
System.out.println(p);
//5.获取单个指定key的值
String str1=p.getProperty("str1");
String str2=p.getProperty("str2");
String str3=p.getProperty("str3");
String str4=p.getProperty("str4");
System.out.println(str1);
}
}
package cn.sxt.crm.test;
import static org.junit.Assert.*;
import java.io.InputStream;
import java.sql.Connection;
import java.util.Properties;
import javax.sql.DataSource;
import org.junit.Test;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;
//Druid连接池的使用
public class DateSourceTest {
@Test//直接手动创建连接池对象
public void testName1() throws Exception {
//1.创建druid连接池对象
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost:3306/lin01");
ds.setUsername("root");
ds.setPassword("root");
//设置最大连接数
ds.setMaxActive(10);
Connection conn = ds.getConnection();
System.out.println(conn);
}
//使用Druid工厂对象读取配置文件来创建连接池对象
@Test
public void testName() throws Exception {
//获取类加载器
ClassLoader classLoader=Thread.currentThread().getContextClassLoader();
InputStream in=classLoader.getResourceAsStream("dp.properties");
Properties properties=new Properties();
properties.load(in);
//使用工厂创建连接池对象
DataSource ds=DruidDataSourceFactory.createDataSource(properties );
Connection conn = ds.getConnection();
System.out.println(conn);
}
}
str1=com.mysql.jdbc.Driver
str2=jdbc:mysql://localhost:3306/lin01
str3=root
str4=root
maxActive=10
-----------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------
package cn.sxt.crm.dao;
import java.util.List;
import cn.sxt.crm.pojo.Student;
public interface StudentDao {
/**
* 插入方法
* @param stu 封装有学生信息的Student对象(数据库自增id,开发者不需要传id)
* @return 受影响的行数
*/
int insert(Student stu);//增方法
/**
* 根据主键删除数据
* @param id 主键id的值
* @return 受影响的行数
*/
int delete(Integer id);
/**
* 修改操作
* @param stu 带有id值的Student对象(修改根据主键id值修改)
* @return 受影响的行数
*/
int update(Student stu);
/**
* 单行查询
* @param id 主键id
* @return 单行数据封装的对象
*/
Student selectByPrimaryKey(Integer id);
/**
* 多行查询
* @return 封装有一个个Student对象的集合
*/
List<Student> selectList();
}
package cn.sxt.crm.dao.impl;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
import cn.sxt.crm.dao.StudentDao;
import cn.sxt.crm.pojo.Student;
import cn.sxt.crm.util.utils;
public class StudentDaoImpl implements StudentDao {
@Override
public int insert(Student stu) {
String sql="insert into t_student(name,age)values(?,?)";
Connection conn=null;
PreparedStatement pr=null;
try {
conn =utils.getConnection();
pr = conn.prepareStatement(sql);
pr.setString(1,stu.getName());
pr.setInt(2, stu.getAge());
int row=pr.executeUpdate();
return row;
} catch (Exception e) {
e.printStackTrace();
}finally{
utils.close(conn, pr, null);
}
return 0;
}
@Override
public int delete(Integer id) {
String sql="delete from t_student where id=?";
Connection conn=null;
PreparedStatement pr=null;
try {
conn = utils.getConnection();
pr = conn.prepareStatement(sql);
pr.setInt(1,id);
int row=pr.executeUpdate();
return row;
} catch (Exception e) {
e.printStackTrace();
}finally{
utils.close(conn, pr, null);
}
return 0;
}
@Override
public int update(Student stu) {
String sql="update t_student set name=?,age=? where id=?";
Connection conn=null;
PreparedStatement pr=null;
try {
conn =utils.getConnection();
pr = conn.prepareStatement(sql);
pr.setString(1,stu.getName());
pr.setInt(2, stu.getAge());
pr.setInt(3, stu.getId());
int row=pr.executeUpdate();
return row;
} catch (Exception e) {
e.printStackTrace();
}finally{
utils.close(conn, pr, null);
}
return 0;
}
@Override
public Student selectByPrimaryKey(Integer id) {
String sql="select * from t_student where id=?";
Connection conn=null;
PreparedStatement pr=null;
ResultSet ex=null;
try {
conn = utils.getConnection();
pr = conn.prepareStatement(sql);
pr.setInt(1,id);
ex = pr.executeQuery();
while(ex.next()){
String name=ex.getString("name");
int age=ex.getInt("age");
// 封装Student对象
Student stu = new Student(id, name, age);
//返回Student对象
return stu;
}
} catch (Exception e) {
e.printStackTrace();
}finally{
utils.close(conn, pr, ex);
}
return null;
}
@Override
public List<Student> selectList() {
List<Student> student= new ArrayList<Student>();
String sql="select * from t_student";
Connection conn=null;
PreparedStatement pr=null;
ResultSet ex=null;
try {
conn =utils.getConnection();
pr = conn.prepareStatement(sql);
ex = pr.executeQuery();
while(ex.next()){
int id=ex.getInt("id");
String name=ex.getString("name");
int age=ex.getInt("age");
// 封装Student对象
Student stu = new Student(id, name, age);
// 学生对象添加到集合中
student.add(stu);
}
} catch (Exception e) {
e.printStackTrace();
}finally{
utils.close(conn, pr, ex);
}
return student;
}
}
package cn.sxt.crm.pojo;
public class Student {
private Integer id;
private String name;
private Integer age;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Student(Integer id, String name, Integer age) {
super();
this.id = id;
this.name = name;
this.age = age;
}
public Student() {
super();
}
@Override
public String toString() {
return "Student [id=" + id + ", name=" + name + ", age=" + age + "]";
}
}
package cn.sxt.crm.test;
import java.util.List;
import org.junit.Test;
import cn.sxt.crm.dao.StudentDao;
import cn.sxt.crm.dao.impl.StudentDaoImpl;
import cn.sxt.crm.pojo.Student;
public class StudentDaoTest {
private StudentDao dao=new StudentDaoImpl();
@Test
public void testInsert() {
Student stu=new Student(null, "叶孤城", 30);
int row=dao.insert(stu);
System.out.println(row);
}
@Test
public void testDelete() {
int row=dao.delete(10);
System.out.println(row);
}
@Test
public void testUpdate() {
Student stu=new Student(9, "叶孤城", 30);
int row=dao.update(stu);
System.out.println(row);
}
@Test
public void testSelectByPrimaryKey() {
Student stu = dao.selectByPrimaryKey(3);
System.out.println(stu);
}
@Test
public void testSelectList() {
List<Student> students = dao.selectList();
System.out.println(students);
}
}
package cn.sxt.crm.util;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;
import javax.sql.DataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;
public class utils {
// 创建读取配置文件的配置对象
private static Properties p=new Properties();
//连接池对象
private static DataSource da;
static {
try {
ClassLoader classLoader=Thread.currentThread().getContextClassLoader();
InputStream inputStream=classLoader.getResourceAsStream("dp.properties");
p.load(inputStream);
//创建连接池对象
da= DruidDataSourceFactory.createDataSource(p);
} catch (Exception e) {
e.printStackTrace();
}
}
public static Connection getConnection(){
try {
Connection conn = da.getConnection();
return conn;
} catch (Exception e) {
throw new RuntimeException("连接失败");
}
}
public static void close(Connection conn,PreparedStatement pr,ResultSet ex){
try {
if(ex!=null){ex.close();}
} catch (SQLException e1) {
e1.printStackTrace();
}finally{
try {
if(pr!=null){
pr.close();
}
} catch (SQLException e) {
e.printStackTrace();
}finally{
try {
if(conn!=null){
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}}
}
}
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/lin01
username=root
password=root
maxActive=1
配置必须按规定命名,
来源:oschina
链接:https://my.oschina.net/u/4276314/blog/3532910