总结
我是最棒的!基础不牢,地动山摇!
JDBC增强
预编译对象PrepareStatement
在创建对象时就已经指定了模板(sql语句),使用占位符表示参数
例入插入语句
String sql = "insert into table values (?,?)";
//conn为连接对象,传入sql语句创建预编译对象
PreparedStatement pst = conn.prepareStatement(sql);
优点
- 提高代码可读性和可维护性
- 预编译的sql语句效率更高(需要数据库支持,但是mysql不支持),缓存机制
- 避免sql注入(非法sql语句)
预编译实现CRUD
package cn.itsource.preparedstatement.dao.impl;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import cn.itsource.preparedstatement.dao.UserDao;
import cn.itsource.preparedstatement.domain.User;
import cn.itsource.util.JDBCUtil;
public class UserDaoImpl implements UserDao {
//增
@Override
public void add(User user) {
Connection connection = null;
PreparedStatement pst = null;
try {
connection = JDBCUtil.getConnection();
String sql = "insert into user values (null,?,?)";
pst = connection.prepareStatement(sql);
pst.setString(1, "byd");
pst.setString(2, "hmp");
pst.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}finally {
JDBCUtil.close(connection, pst, null);
}
}
//删
@Override
public void remove(Long id) {
Connection conn = null;
PreparedStatement pst = null;
try {
conn = JDBCUtil.getConnection();
String sql = "delete from user where id = ?";
pst = conn.prepareStatement(sql);
pst.setLong(1, id);
pst.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}finally {
JDBCUtil.close(conn, pst, null);
}
}
//改
@Override
public void update(User user) {
Connection conn = null;
PreparedStatement pst = null;
try {
conn = JDBCUtil.getConnection();
String sql = "update user set username = ?,password = ? where id = ?";
pst = conn.prepareStatement(sql);
pst.setString(1, user.getUsername());
pst.setString(2, user.getPassword());
pst.setLong(3, user.getId());
pst.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}finally {
JDBCUtil.close(conn, pst, null);
}
}
//查一个
@Override
public User getOne(Long id) {
User user = null;
Connection conn = null;
PreparedStatement pst = null;
ResultSet rs = null;
try {
conn = JDBCUtil.getConnection();
String sql = "select * from user where id = ?";
pst = conn.prepareStatement(sql);
pst.setLong(1, id);
rs = pst.executeQuery();
if(rs.next()) {
user = new User();
user.setId(rs.getLong(1));
user.setUsername(rs.getString(2));
user.setPassword(rs.getString(3));
// System.out.println(rs.getLong(1));
// System.out.println(rs.getString(2));
// System.out.println(rs.getInt(3));
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
JDBCUtil.close(conn, pst, rs);
}
return user;
}
//查所有
@Override
public List<User> getAll() {
List<User> list = new ArrayList<User>();
Connection conn = null;
PreparedStatement pst= null;
ResultSet rs = null;
try {
conn = JDBCUtil.getConnection();
String sql = "select * from user";
pst = conn.prepareStatement(sql);
rs = pst.executeQuery();
while(rs.next()){
User user = new User();
user.setId(rs.getLong(1));
user.setUsername(rs.getString(2));
user.setPassword(rs.getString(3));
list.add(user);
}
} catch (SQLException e) {
e.printStackTrace();
}
return list;
}
}
事务
事务在数据库中是指一组逻辑操作单元,为了保证数据中数据的一致性。就是一组相关的操作,他们必须同时成功,才算是成功。
Connection中的相关方法
//关闭自动提交,conn为Connection对象
Conn.setAutoCommit(false);
//手动提交
commit();
//如果在事务中发生异常,使用回滚,取消当前事务的所有操作
rollback();
转账事务
package cn.itsource.trancation;
import static org.junit.Assert.*;
import java.sql.Connection;
import java.sql.PreparedStatement;
import org.junit.Test;
import cn.itsource.util.JDBCUtil;
public class TxTest {
@Test
public void testTx() throws Exception {
Connection conn = null;
try {
conn = JDBCUtil.getConnection();
//关闭自动提交
conn.setAutoCommit(false);
String sql = "update account set money = money - 5000 where id = ?";
PreparedStatement pst = conn.prepareStatement(sql);
pst.setLong(1, 1L);
pst.executeUpdate();
//除0异常,模拟断电
int i = 1/0;
String sql2 = "update account set money = money + 5000 where id = ?";
PreparedStatement pst2 = conn.prepareStatement(sql2);
pst2.setLong(1, 2L);
pst2.executeUpdate();
//手动提交
conn.commit();
} catch (Exception e) {
//发生异常,回滚
conn.rollback();
}
}
}
事务的四大特性(ACID)
- 原子性(Atomic)最小单位,一组事务是一个整体
- 一致性(Consistency)事务执行前,和执行后数据是守恒的,增加的和减少的一样多
- 隔离性(Isolation)多个不同的事务同时执行,相互之间不影响
- 持久性(Dirability)数据的修改或者更新必须同步保存到数据库中
我们通过修改事务的提交方式setAutoCommit(false)为手动来保证事务的原子性,一致性和持久性
获取主键
statement中的getGeneratedKeys()方法,在使用prepareStatement方法的时候将statement.RETURN_GENERATE_KEYS作为参数传入
连接池
反复地创建和销毁连接导致效率低下,资源利用率低
配置连接池的属性
- min最小连接数
- 新增连接数
- 超时时间
- max最大连接数
常见的连接池
JDK中有一个规范,DataSource接口(该接口用于从连接池获取连接对象),里面有getConnection()方法
DBCP
看官自行百度
C3P0
看官自行百度
Druid
重点掌握Druid,阿里巴巴开源的连接池,基于DBCP,性能最优
效率最高,最好的连接池,不接受反驳。
package cn.itsource.druid;
import static org.junit.Assert.*;
import java.sql.Connection;
import java.util.Properties;
import javax.sql.DataSource;
import org.junit.Test;
import com.alibaba.druid.pool.DruidDataSourceFactory;
public class DruidTest {
@Test
public void testDruid(){
Properties p = new Properties();
try {
p.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("jdbc.properties"));
DataSource dataSource = DruidDataSourceFactory.createDataSource(p);
Connection conn = dataSource.getConnection();
} catch (Exception e) {
e.printStackTrace();
}
}
}
抽取相同部分的代码
将代码重复的部分抽取写一个模板类,类中有模板方法
package cn.itsource.template;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import cn.itsource.template.UserDaoImpl.UserHandler;
import cn.itsource.util.JDBCPoolUtil;
/**
* 抽取DML与DQL的共同部分
*/
public class JDBCTemplate {
/**
* DML的抽取
*/
public static void templateUpdate(String sql,Object... obj){
Connection conn = JDBCPoolUtil.getConnection();
PreparedStatement pst = null;
try {
pst = conn.prepareStatement(sql);
for (int i = 0; i < obj.length; i++) {
pst.setObject(i+1, obj[i]);
}
pst.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}finally {
JDBCPoolUtil.close(conn, pst, null);
}
}
/**
* DQL的抽取
*/
public static<T> T templateQuery(String sql,IResultSetHandler<T> handler,Object... objs){
Connection conn = JDBCPoolUtil.getConnection();
PreparedStatement pst = null;
ResultSet rs = null;
try {
pst = conn.prepareStatement(sql);
for (int i = 0; i < objs.length; i++) {
pst.setObject(i+1, objs[i]);
}
rs = pst.executeQuery();
return handler.handler(rs);
} catch (SQLException e) {
e.printStackTrace();
}finally {
JDBCPoolUtil.close(conn, pst, rs);
}
return null;
}
}
自定义接口解决类型写死的问题
package cn.itsource.template;
import java.sql.ResultSet;
public interface IResultSetHandler <T>{
T handler(ResultSet rs);
}
实现类
package cn.itsource.template;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import cn.itsource.preparedstatement.dao.UserDao;
import cn.itsource.preparedstatement.domain.User;
/**
* 通过模板类,大大减少了我们的代码量
*/
public class UserDaoImpl implements UserDao {
@Override
public void add(User user) {
String sql = "insert into user values (null,?,?)";
JDBCTemplate.templateUpdate(sql, user.getUsername(),user.getPassword());
}
@Override
public void remove(Long id) {
String sql = "delete from user where id = ?";
JDBCTemplate.templateUpdate(sql, id);
}
@Override
public void update(User user) {
String sql = "update user set username = ?,password = ? where id = ?";
JDBCTemplate.templateUpdate(sql, user.getUsername(),user.getPassword(),user.getId());
}
@Override
public User getOne(Long id) {
String sql = "select * from user where id = ?";
List<User> list = JDBCTemplate.templateQuery(sql, new UserHandler(),id);
if(list != null){
return list.get(0);
}
return null;
}
@Override
public List<User> getAll() {
String sql = "select * from user";
List<User> list = JDBCTemplate.templateQuery(sql, new UserHandler());
if(list != null){
return list;
}
return null;
}
/**
* 内部类实现了自定义接口,用来处理User的结果集
* @author tyx666
*
*/
class UserHandler implements IResultSetHandler<List<User>>{
@Override
public List<User> handler(ResultSet rs) {
List<User> list = new ArrayList<User>();
try {
while(rs.next()){
User user = new User();
user.setId(rs.getLong(1));
user.setUsername(rs.getString(2));
user.setPassword(rs.getString(3));
list.add(user);
}
} catch (SQLException e) {
e.printStackTrace();
}
return list;
}
}
}