您的位置:首页 > 其它

JDBC及配置文件的使用。测试类(@Test和@Before依旧没解决)。DBCP。事务

2017-09-23 10:37 465 查看
2018.2.27  19:33 第二次修改。

JDBC:是java程序与数据库系统通信的标准API,定义在JDK的API中,通过JDBC,Java可以很方便的与各种数据库进行交互。
前面是具体代码例子,总结在例子后面。
组成包:java.sql.* 和javax.sql.*这两个包都包含在JDK当中
注意:引入的都是java.sql.connection而不是com.mysql.jdbc.connection
JDBC工程建立过程public class JdbcDemo {

public static void main(String[] args) throws Exception {
/*
* 1.创建一个java项目
* 2.倒入jar包
* 3.注册驱动
* 4.获取连接 对象
* 5.获取执行sql语句的对象
* 6.如果是查询 应该有结果集 封装结果集
* 7.关系资源 有顺序 对象自下而上关闭
*/
// 注册数据库驱动
DriverManager.registerDriver(new Driver());
// Class.forName("com.mysql.jdbc.Driver");
// 获取数据库连接
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb1", "root", "123456");
// 获取执行sql语句的对象 执行sql语句
Statement st = conn.createStatement();
String sql = "select *from products";
// 执行 返回 结果集对象 set集合去重
ResultSet resultSet = st.executeQuery(sql);
while (resultSet.next()) {
// int id =resultSet.getInt(1);
String id = resultSet.getString(1);
String name = resultSet.getString("name");
// 可输入列数,也可以说输入列的名称
// 当我去封装结果集的时候再去转换products
System.out.println(id + ":" + name);
}
}

}注意点:new Driver 包是com.mysql.jdbc.Driver
导入的jar包为:mysql-connector-java-5.0.8-bin.jar包,一定要buildpath一下。作用为连接mysql数据库
除executeQuery外还有String sql ="insert into products values(null,'高数之四角函数',100,'计算机',1000,'简单')";
int i = statement.executeUpdate(sql); 注册驱动的三种方法 //第一种方式
Driver driver = new Driver() ;
DriverManager.registerDriver(driver) ;

//第二种方式
Driver d = (Driver)Class.forName("com.mysql.jdbc.Driver").newInstance() ;
DriverManager.registerDriver(d) ;

//第三种方式
Class.forName("com.mysql.jdbc.Driver") ; //自动进行注册获取配置文件的三种方法
public class ReadProperties {

public static void main(String[] args) throws Exception {
//		第一种方法获取文件配置
//		FileInputStream in = new FileInputStream("src/db.properties");
//第二种方法获取类加载器 来获取文件的输入流
//		InputStream in = ReadProperties.class.getClassLoader().getResourceAsStream("config/db.properties");
//		第三种方法
ResourceBundle bundle = ResourceBundle.getBundle("config/db");
String name = bundle.getString("username");
/*Properties p = new Properties();
p.load(in);
String url = p.getProperty("url");一二种方法需要,使用一二种方法相应的修改输出语句参数为url。*/
System.out.println(name);
}

}

JDBC和配置文件结合
public class Demo3 {
static String driverClass=null;
static String url=null;
static String username=null;
static String password=null;
static {
//		读取配置文件
InputStream in = Demo2.class.getClassLoader().getResourceAsStream("config/db.properties");
//		创建properties工具类
Properties p = new Properties();
try {
p.load(in);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
driverClass =p.getProperty("driverClass");
url =p.getProperty("url");
username =p.getProperty("username");
password =p.getProperty("password");
try {
Class.forName(driverClass);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}

}
public static void main(String[] args) {
Connection conn =null;
Statement st =null;
ResultSet set=null;
try {
conn =DriverManager.getConnection(url,username,password);
//		获取执行sql语句的对象
st = conn.createStatement();
String sql ="select * from products where id<8";
//		执行
set = st.executeQuery(sql);
while(set.next()){
String name = set.getString("name");
System.out.println(name);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
try {
if(null!=set){
set.close();
set=null;//经验操作,为空之后马上垃圾回收
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
if(null!=st){
st.close();
st=null;//经验操作
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
if(null!=conn){
conn.close();
conn=null;//经验操作
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

}

preparedStatement接口替代Statement的原因及preparedStatement用法:

https://www.cnblogs.com/ysw-go/p/5459330.html

preparedStatement将数据使用setString(int,String),Setint()等方法放进去,要及时executeUpdate()更新一下,并关闭ps,conn,result。
工作经验:关闭之后赋值为null是因为这样可以运用垃圾回收机制。
封装的工具类public class MyDbutils {
//读取配置文件 注册驱动
static String driverClass=null;
static String url=null;
static String username=null;
static String password=null;
static {
// 读取配置文件
InputStream in = Demo2.class.getClassLoader().getResourceAsStream("config/db.properties");
// 创建properties工具类
Properties p = new Properties();
try {
p.load(in);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
driverClass =p.getProperty("driverClass");
url =p.getProperty("url");
username =p.getProperty("username");
password =p.getProperty("password");
try {
Class.forName(driverClass);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}
/**
* 获取链接
* @throws SQLException
*/
public static Connection getConnection() throws SQLException{
return DriverManager.getConnection(url, username, password);
}

/**
* 关闭资源
*/
public static void release(Connection conn,Statement st,ResultSet set){
try {
if(null!=set){
set.close();
set=null;//经验操作
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
if(null!=st){
st.close();
st=null;//经验操作
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
if(null!=conn){
conn.close();
conn=null;//经验操作
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

}


测试类
public class TestUtil {
Connection conn = null;
Statement st = null;
@Before
/**
* 在单元测试的每个方法执行前执行此方法
* @throws SQLException
*/
public void init() throws SQLException {
conn = MyDbUtils.getConnection();
st = conn.createStatement();
}

@Test
/**
* 测试完成添加商品
* @throws SQLException
*/
public void add() throws SQLException {
// sql语句
String sql = "insert into products values(null,'六角函数',12.00,'数学',100,'不难')";
// 执行插入操作
int i = st.executeUpdate(sql);
System.out.println(i);
}
@Test
/**
* 测试完成添加商品
* @throws SQLException
*/
public void delete() throws SQLException {
// sql语句
String sql = "delete from products where id=11";
// 执行插入操作
int i = st.executeUpdate(sql);
System.out.println(i);
}
@Test
/**
* 测试完成添加商品
* @throws SQLException
*/
public void update() throws SQLException {
// sql语句
String sql = "update products set name='七角函数' where id=11 ";
// 执行插入操作
int i = st.executeUpdate(sql);
System.out.println(i);
}

@Test
/**
* 测试完成添加商品
* @throws SQLException
*/
public void select() throws SQLException {
// sql语句
String sql = "select * from products";
// 执行插入操作
ResultSet executeQuery = st.executeQuery(sql);
while(executeQuery.next()){
String id = executeQuery.getString("id");
String name = executeQuery.getString(2);
System.out.println(id+":"+name);
}
MyDbUtils.release(conn, st, executeQuery);
}

}


@Before和@Test的导入方法,前面博文有,如果报错No tests found matching,首先记住加@Test。mac系统下如果多次报错:not match类的,删除Junit4多删除多导入几遍
测试对象
public class TestObject {
Connection conn=null;
@Before
public void init() throws SQLException{
// 获取数据库连接
conn= MyDbUtils.getConnection();
}
@Test
public void test1(String username,String password) throws SQLException{
String sql="select * from user1 where username= ? and password = ?";
PreparedStatement ps = conn.
f56a
prepareStatement(sql);
// 执行sql语句之前,对sql语句进行检查
ps.setString(1, "zhangsan");
ps.setString(2, "123");
ResultSet set = ps.executeQuery(sql);
while(set.next()){
String name = set.getString("username");
System.out.println(name);
}

}

JDBC常用类的总结
DriverManager类主要作用于用户及驱动程序之间,它是JDBC中的管理层,通过DriverManager类可以管理数据库的驱动程序。
Connection接口位于java.sql包中,相当于与特定数据库的连接会话。
Statement接口接口封装了对数据库的操作,提供了执行语句和获取查询结果的基本方法。

DriverMangerDriverManager.registerDriver()缺点:会导致驱动被创建两次替代方案:Class.forName("com.mysql.jdbc.Driver")
statement作用:向数据库发送并执行具体的sql语句常用方法:ResultSet executeQuery(String sql):只适合查询,返回查询的结果集。Set集合可以去除重复int executeUpdate(String sql):只适合适合增删改,返回影响的记录行数boolean execute(String sql):执行任何sql语句。有结果集的返回1,没有结果集的返回0
ResultSet用于存放结果集注意:Connection要尽量晚的创建,尽量早的释放。确保一定释放,所以要放在finally中
数据库连接池优点:节省创建连接和释放连接 性能消耗连接池中连接起到复用的作用,提高程序性能运行机制:(1)程序初始化时创建连接池(2)使用时向连接池申请可用连接(3)使用完毕,将连接返还给连接池(4)
public class MyDataPool {
// 创建一个池子,里面是Connection对象
List<Connection> list = new LinkedList<Connection>();

public MyDataPool() throws Exception {
for (int i = 0; i < 5; i++) {
Connection conn = MyDbUtils.getConnection();
list.add(conn);
}
}

/**
* 从池子中获取链接
*
* @throws SQLException
*/
public Connection getConnection() throws SQLException {
if (list.size() == 0) {// 池子中没有东西
for (int i = 0; i < 5; i++) {
Connection conn = MyDbUtils.getConnection();
list.add(conn);
}

}
Connection connection = list.remove(0);
return connection;

}

/**
* 将连接归还到池子当中
*
* @throws Exception
*/
public void addBack(Connection conn) throws Exception {
if (list.size() > 8) {
conn.close();
}
list.add(conn);

}
}
测试
public class TestMyPool {

public static void main(String[] args) throws Exception {
MyDataPool pool = new MyDataPool();
// 获取数据库连接池中的连接
Connection conn = pool.getConnection();
String sql = "insert into account values(null,?,?,?)";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setString(1, "lisi");
ps.setString(2, "234");
ps.setString(2, "yzp");
int update = ps.executeUpdate();
System.out.println(update);
// 将连接返回给连接池
pool.addBack(conn);
}

}


手动DBCP(DataBase ConnectionPool)数据库连接池public class Demo1 {

public static void main(String[] args) throws SQLException {
// 创建数据库连接池
BasicDataSource dataSource = new BasicDataSource();
// 设置四大参数 读取配置文件
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql:///mydb1?characterEncoding=UTF-8");
dataSource.setUsername("root");
dataSource.setPassword("123456");
// 获取连接
Connection conn = dataSource.getConnection();
String sql = "update user set username = ? where id=? ";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setString(1, "吕布");
ps.setString(2, "3");
int i = ps.executeUpdate();
System.out.println(i);
ps.close();
conn.close();
}

}需要事先导入jar包commons-dbcp-1.4jar和commons-pool-1.5.6jar。不然无法创建数据库连接池,也无法调用相关方法配置文件的JDBCdriverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mydb1?characterEncoding=UTF-8
username =root
password=123456
测试代码
public class Demo2 {

public static void main(String[] args) throws Exception {
//		创建新的配置文件并加载
Properties p = new Properties();
p.load(new FileInputStream("src/dbcp.properties"));

//		创建新的JDBC工厂
BasicDataSourceFactory basicDataSourceFactory = new BasicDataSourceFactory();
DataSource dataSource = basicDataSourceFactory.createDataSource(p);
//		获取连接
Connection conn = dataSource.getConnection();
String sql = "update user set username = ?  where id=? ";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setString(1, "张飞");
ps.setString(2, "6");
int i = ps.executeUpdate();
System.out.println(i);
ps.close();
conn.close();
}

}


c3p0数据库连接池:配置文件如下c3p0.driverClass=com.mysql.jdbc.Driver
c3p0.jdbcUrl=jdbc:mysql:///mydb1?characterEncoding=UTF-8
c3p0.user=root
c3p0.password=123456
测试代码如下public class Demo {

public static void main(String[] args) throws Exception {
// 获取c3p0的数据库原数据
ComboPooledDataSource dataSource = new ComboPooledDataSource();
// 获取数据库连接
Connection conn = dataSource.getConnection();
// 获取执行sql语句的对象
String sql = "select * from products ";
PreparedStatement ps = conn.prepareStatement(sql);
ResultSet resultSet = ps.executeQuery();
List<Product> list = new ArrayList<>();
while (resultSet.next()) {
Product product = new Product();
// 封装结果集
String id = resultSet.getString(1);
String name = resultSet.getString(2);
String price = resultSet.getString(3);
String category = resultSet.getString(4);
String pnum = resultSet.getString(5);
String description = resultSet.getString(6);
product.setId(Integer.parseInt(id));
product.setName(name);
product.setPrice(Double.parseDouble(price));
product.setCategory(category);
product.setPnum(Integer.parseInt(pnum));
product.setDescription(description);
list.add(product);
}
System.out.println(list.size());
MyDbUtils.release(conn, ps, resultSet);
}

}是的。。及其麻烦,所以引入apache的工具类jar包commons-dbutils-1.4jar

现在,用c3p0和刚才的工具类完成功能public class Demo2 {

public static void main(String[] args) throws SQLException {
// 创建数据库连接池的原数据
ComboPooledDataSource dataSource = new ComboPooledDataSource();
// 使用apache的工具类
QueryRunner runner = new QueryRunner(dataSource);
// 操作sql语句
// 查询操作,返回一条结果
String sql = "select * from products where id=?";
Product product = runner.query(sql, new BeanHandler<Product>(Product.class), 1);
System.out.println(product);
// 不需要关闭资源
}

}
注意,不用关闭资源。。。c3p0具有自动回收空闲连接的功能,还可以断线自动连接。query(sql,new BeanHandler<封装的实体类>(类名.class),参数可以多个)多条数据的话用 new BeanListHandler<>()

事务:单个逻辑工作单元执行的一系列操作,要么完全的执行,要么完全的不执行
事务的特性原子性:强调事务不可分割的特性,是执行的最小单位一致性:强调事务执行前后的数据保持一致隔离性:强调多个事务同时操作同一条数据的时候,保证事务事件互不干扰持久性:事务一旦结束,数据应该全部保存在数据库中设置事务的隔离级别Read uncommitted 相当于没有隔离级别Read committed 解决脏读问题Repeatable read(mysql默认隔离级别) 解决脏读和不可重复读Serializable 解决任何问题,但是效率最低不考虑隔离级别可能产生的问题脏读:一个事务读取到另一个事务未提交的数据不可重复读:事务中,两次读取到的数据不一致,其他事务有更新操作幻读:食物中两次事务读取到的数据不一致,另一事务存在插入操作mysql操作事务:mysql中的事务默认是开启的,一条sql语句一个事务1.开启事务 start transaction2.提交事务 commit(事务已经结束了,数据也永久的保存在数据库中了)3.回滚事务 rollback(代表事务已经结束了,回滚到了初始化状态)jdbc操作事务Connection接口管理事务void setAutoCommit(boolean auto commit)方法void commit()事务提交void rollback()事务回滚

事务的演示public class TestShiWu {

public static void main(String[] args) throws Exception {
Class.forName("com.mysql.jdbc.Driver");
//获取链接
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb1?characterEncoding=UTF-8","root","123456");
//获取执行sql语句的对象
// 西门庆花钱操作
Statement statement = conn.createStatement();
conn.setAutoCommit(false);
String sql ="update user1 set money = money - 100 where name='西门庆'";
int i = statement.executeUpdate(sql);
int h=i/0;
// 武大郎挣钱操作
String sql2 ="update user1 set money = money + 100 where name='武大郎'";
int j = statement.executeUpdate(sql2);
conn.commit();
//释放资源
statement.close();
conn.close();
}

}
这段代码精髓在于。。conn.setAutoCommit(false)和conn.commit();如果不设置为false,默认的是AutoCommit,对,自动提交,这个时候可能会发生西门庆花了钱,h处报错,然后武大郎没有收到钱的情况。但是加了事务的提交后,虽然依旧报错,但是只要扣了钱,另一个操作该数据的操作依旧会执行。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐