private static String driver;
private static String url;
private static String username;
private static String password; static{
ResourceBundle bundle = ResourceBundle.getBundle("db");
driver = bundle.getString("driver");
url = bundle.getString("url");
username = bundle.getString("username");
password = bundle.getString("password");
}
private static String driver;
private static String url;
private static String username;
private static String password; static {
try {
// 1.通过当前类获取类加载器
ClassLoader classLoader = JDBCUtils_V3.class.getClassLoader();
// 2.通过类加载器的方法获得一个输入流
InputStream is = classLoader.getResourceAsStream("db.properties");
// 3.创建一个properties对象
Properties props = new Properties();
// 4.加载输入流
props.load(is);
// 5.获取相关参数的值
driver = props.getProperty("driver");
url = props.getProperty("url");
username = props.getProperty("username");
password = props.getProperty("password");
} catch (IOException e) {
e.printStackTrace();
}
}

主从表数据更新问题

当两张表没有建立任何关系的时候,那么可以随意删除其中任何一张表中的任何记录,但是一旦把两张表建立了关系(主外键约束)之后,那么不能删除主表

中的数据(这些数据内容在从表中有关联关系的数据),只想执行删除(更新操作)。

要想删除主表中与从表有关联关系的数据,可以这么做:

  1. 解除主从表的约束关系
  2. 先删除从表中与主表有关系的数据,再删除主表中的数据。

关于子查询问题

一般子查询会存在于两张关联的表中,那么我们可以先把带有条件的那张表与另外一张表的关联关系字段查出来,并作为另外一张表查询的条件值,然后再次进行查询。

select * from product where category_id=( select cid  from category where cname=’化妆品’);

关于mysql编码问题

查看MySQL编码       SHOW VARIABLES LIKE 'char%';

l  character_set_client:你发送的数据必须与client指定的编码一致!!!服务器会使用该编码来解读客户端发送过来的数据;

l  character_set_connection:通过该编码与client一致!该编码不会导致乱码!当执行的是查询语句时,客户端发送过来的数据会先转换成connection指定的编码。但只要客户端发送过来的数据与client指定的编码一致,那么转换就不会出现问题;

l  character_set_database:数据库默认编码,在创建数据库时,如果没有指定编码,那么默认使用database编码;

l  character_set_server:MySQL服务器默认编码;

l  character_set_results:响应的编码,即查询结果返回给客户端的编码。这说明客户端必须使用result指定的编码来解码;

修改character_set_client、character_set_results、character_set_connection为GBK,就不会出现乱码了。但其实只需要修改character_set_client和character_set_results。

控制台的编码只能是GBK,而不能修改为UTF8,这就出现一个问题。客户端发送的数据是GBK,而character_set_client为UTF8,这就说明客户端数据到了服务器端后一定会出现乱码。既然不能修改控制台的编码,那么只能修改character_set_client为GBK了。

服务器发送给客户端的数据编码为character_set_result,它如果是UTF8,那么控制台使用GBK解码也一定会出现乱码。因为无法修改控制台编码,所以只能把character_set_result修改为GBK。

l  修改character_set_client变量:set character_set_client=gbk;

l  修改character_set_results变量:set character_set_results=gbk;

自定义连接池

* SUN公司提供了一个连接池的接口.(javax.sql.DataSource).

* 定义一个连接池:实现这个接口.

* 使用List集合存放多个连接的对象.

public class MyDataSource implements DataSource{
// 创建一个List集合用于存放多个连接对象.
private List<Connection> list = new ArrayList<Connection>();
// 在程序开始的时候,初始化几个连接,将连接存放到list中.
public MyDataSource() {
// 初始化3个连接:
for(int i=1;i<=3;i++){
Connection conn = JDBCUtils.getConnection();
list.add(conn);
}
} @Override
// 获得连接的方法:
public Connection getConnection() throws SQLException {
if(list.size() <= 0){
for(int i=1;i<=3;i++){
Connection conn = JDBCUtils.getConnection();
list.add(conn);
}
}
Connection conn = list.remove(0);
return conn;
} // 归还连接的方法:
public void addBack(Connection conn){
list.add(conn);
}
...
}

自定义连接池中问题及如何解决

问题?

1.如果使用自定义连接池,那么需要额外记住自定义连接池中的API.

2.能不能使用面向接口的编程方式.

如何增强Connectionclose方法:  放到连接池中

增强一个Java类中的某个方法有几种方式

继承的方式  能够控制这个类的构造的时候,才可以使用继承

继承的方式增强一个类中某个方法:
class Man{
public void run(){
System.out.println("跑....");
}
} class SuperMan extends Man{
public void run(){
// super.run();
System.out.println("飞....");
}
}

装饰者模式方式.

包装对象和被包装的对象都要实现相同的接口.

包装的对象中需要获得到被包装对象的引用.

缺点:如果接口的方法比较多,增强其中的某个方法.其他的功能的方法需要原有调用.

使用装饰者的方式完成类的方法的增强
interface Waiter{
public void server();
} class Waiteress implements Waiter{ @Override
public void server() {
System.out.println("服务...");
}
}
class WaiteressWrapper implements Waiter{
private Waiter waiter; public WaiteressWrapper(Waiter waiter) {
this.waiter = waiter;
} @Override
public void server() {
System.out.println("微笑...");
// this.waiter.server();
}
}
public class MyConnection implements Connection{
private Connection conn;
private List<Connection> list; public MyConnection(Connection conn,List<Connection> list) {
this.conn = conn;
this.list = list;
}
@Override
public void close() throws SQLException {
list.add(conn);
}
...
} 连接池的getConnection方法:
@Override
// 获得连接的方法:
public Connection getConnection() throws SQLException {
if(list.size() <= 0){
for(int i=1;i<=3;i++){
Connection conn = JDBCUtils.getConnection();
list.add(conn);
}
}
Connection conn = list.remove(0);
MyConnection myConn = new MyConnection(conn, list);
return myConn;
}

动态代理的方式.

被增强的对象实现接口就可以.

DBCP

DBCP(DataBase connection pool),数据库连接池。是 apache 上的一个 java 连接池项目,也是 tomcat 使用的连接池组件。

单独使用dbcp需要2个包:commons-dbcp.jar,commons-pool.jar由于建立数据库连接是一个非常耗时耗资源的行为,所以通常连

接池都是预先建立一些连接,放在内存中,应用程序需要建立数据库连接时直接到连接池中申请一个就行,用完后再放回去。

第一步:引入DBCP连接池的jar包.

第二步:编写DBCP代码:

* 手动设置参数:

* 配置文件设置参数

@Test
public void demo1(){
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql:///web_07");
dataSource.setUsername("root");
dataSource.setPassword("123");
try{
// 获得连接:
conn = dataSource.getConnection();
// 编写SQL:
String sql = "select * from category";
// 预编译SQL:
stmt = conn.prepareStatement(sql);
// 执行SQL:
rs = stmt.executeQuery();
while(rs.next()){
System.out.println(rs.getInt("cid")+" "+rs.getString("cname"));
}
}catch(Exception e){
e.printStackTrace();
}finally{
JDBCUtils.release(rs,stmt, conn);
}
} @Test
/**
* 配置文件方式:
*/
public void demo2(){
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
Properties properties = new Properties(); try{
properties.load(new FileInputStream("src/dbcpconfig.properties"));
DataSource dataSource = BasicDataSourceFactory.createDataSource(properties);
// 获得连接:
conn = dataSource.getConnection();
// 编写SQL:
String sql = "select * from category";
// 预编译SQL:
stmt = conn.prepareStatement(sql);
// 执行SQL:
rs = stmt.executeQuery();
while(rs.next()){
System.out.println(rs.getInt("cid")+" "+rs.getString("cname"));
}
}catch(Exception e){
e.printStackTrace();
}finally{
JDBCUtils.release(rs,stmt, conn);
}
}

C3P0

C3P0是一个开源的JDBC连接池,它实现了数据源和JNDI绑定,支持JDBC3规范和JDBC2的标准扩展。目前使用它的开源项目有Hibernate,Spring等。

第一步:引入C3P0连接池的jar包.

第二步:编写代码:

* 手动设置参数:

* 配置文件设置参数:

public class JDBCUtils2 {
private static final ComboPooledDataSource DATA_SOURCE =new ComboPooledDataSource();
public static Connection getConnection(){
Connection conn = null;
try {
conn = DATA_SOURCE.getConnection();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return conn;
}

ResultSetHandler

我们知道在执行select语句之后得到的是ResultSet,然后我们还需要对ResultSet进行转换,得到最终我们想要的数据。你可以希望把ResultSet的数据放到一个List中,

也可能想把数据放到一个Map中,或是一个Bean中。

DBUtils提供了一个接口ResultSetHandler,它就是用来ResultSet转换成目标类型的工具。你可以自己去实现这个接口,把ResultSet转换成你想要的类型。

DBUtils提供了很多个ResultSetHandler接口的实现,这些实现已经基本够用了,我们通常不用自己去实现ResultSet接口了

l  MapHandler:单行处理器!把结果集转换成Map<String,Object>,其中列名为键!

l  MapListHandler:多行处理器!把结果集转换成List<Map<String,Object>>;

l  BeanHandler:单行处理器!把结果集转换成Bean,该处理器需要Class参数,即Bean的类型;

l  BeanListHandler:多行处理器!把结果集转换成List<Bean>;

l  ColumnListHandler:多行单列处理器!把结果集转换成List<Object>,使用ColumnListHandler时需要指定某一列的名称或编号,例如:new ColumListHandler(“name”)表示把name列的数据放到List中。

l  ScalarHandler:单行单列处理器!把结果集转换成Object。一般用于聚集查询,例如select count(*) from tab_student。

QueryRunner之查询

QueryRunner的查询方法是:

  public <T> T query(String sql, ResultSetHandler<T> rh, Object… params)

  public <T> T query(Connection con, String sql, ResultSetHandler<T> rh, Object… params)

query()方法会通过sql语句和params查询出ResultSet,然后通过rh把ResultSet转换成对应的类型再返回。

   public void fun1() throws SQLException {
DataSource ds = JdbcUtils.getDataSource();
QueryRunner qr = new QueryRunner(ds);
String sql = "select * from tab_student where number=?";
Map<String,Object> map = qr.query(sql, new MapHandler() , "S_2000");
System.out.println(map);
}
public void fun2() throws SQLException {
DataSource ds = JdbcUtils.getDataSource();
QueryRunner qr = new QueryRunner(ds);
String sql = "select * from tab_student";
List<Map<String,Object>> list = qr.query(sql, new MapListHandler() );
for(Map<String,Object> map : list) {
System.out.println(map);
}
}
public void fun3() throws SQLException {
DataSource ds = JdbcUtils.getDataSource();
QueryRunner qr = new QueryRunner(ds);
String sql = "select * from tab_student where number=?";
Student stu = qr.query(sql, new BeanHandler<Student>(Student.class) , "S_2000");
System.out.println(stu);
}
public void fun4() throws SQLException {
DataSource ds = JdbcUtils.getDataSource();
QueryRunner qr = new QueryRunner(ds);
String sql = "select * from tab_student";
List<Student> list = qr.query(sql, new BeanListHandler<Student>(Student.class));
for(Student stu : list) {
System.out.println(stu);
}
}
public void fun5() throws SQLException {
DataSource ds = JdbcUtils.getDataSource();
QueryRunner qr = new QueryRunner(ds);
String sql = "select * from tab_student";
List<Object> list = qr.query(sql, new ColumnListHandler("name") );
for(Object s : list) {
System.out.println(s);
}
}
public void fun6() throws SQLException {
DataSource ds = JdbcUtils.getDataSource();
QueryRunner qr = new QueryRunner(ds);
String sql = "select count(*) from tab_student";
Number number = (Number)qr.query(sql, new ScalarHandler() );
int cnt = number.intValue();
System.out.println(cnt);
}
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config> <default-config>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql:///web_07</property>
<property name="user">root</property>
<property name="password">123</property>
<property name="initialPoolSize">5</property>
<property name="maxPoolSize">20</property>
</default-config> <named-config name="oracle">
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql:///web_07</property>
<property name="user">root</property>
<property name="password">123</property>
</named-config> </c3p0-config>

c3p0-config.xml 配置文件

#连接设置
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/jdbc
username=root
password= #<!-- 初始化连接 -->
initialSize=10 #最大连接数量
maxActive=50 #<!-- 最大空闲连接 -->
maxIdle=20 #<!-- 最小空闲连接 -->
minIdle=5 #<!-- 超时等待时间以毫秒为单位 6000毫秒/1000等于60秒 -->
maxWait=60000 #JDBC驱动建立连接时附带的连接属性属性的格式必须为这样:[属性名=property;]
#注意:"user" 与 "password" 两个属性会被明确地传递,因此这里不需要包含他们。
connectionProperties=useUnicode=true;characterEncoding=gbk #指定由连接池所创建的连接的自动提交(auto-commit)状态。
defaultAutoCommit=true #driver default 指定由连接池所创建的连接的事务级别(TransactionIsolation)。
#可用值为下列之一:(详情可见javadoc。)NONE,READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE
defaultTransactionIsolation=READ_UNCOMMITTED

jdbc笔记2的更多相关文章

  1. 【JDBC 笔记】

    JDBC 笔记 作者:晨钟暮鼓c个人微信公众号:程序猿的月光宝盒 对应pdf版:https://download.csdn.net/download/qq_22430159/10754554 没有积分 ...

  2. JDBC笔记总结[申明:来源于网络]

    JDBC笔记总结[申明:来源于网络] 地址:http://blog.csdn.net/Summer_YuXia/article/details/53676386?ref=myread

  3. JDBC笔记

    简介 JDBC是Java规定的访问数据库的API,目前主流的数据库都支持JDBC.使用JDBC访问不同的数据库时需要安装不同的驱动. JDBC定义了数据库的链接,SQL语句的执行以及查询结果集的遍历等 ...

  4. spring jdbc 笔记3

    spring JDBC 加入对commons-dbcp  spring-jdbc  spring-tx的依赖 1.数据源的配置 获取数据源在spring中的Bean管理默认已经是单例模式 关闭数据源d ...

  5. jdbc笔记(二) 使用PreparedStatement对单表的CRUD操作

    首先声明,本文只给出代码,并不是做教程用,如有不便之处,还请各位见谅. PreparedStatement相较于Statement,概括来说,共有三个优势: 1. 代码的可读性和易维护性:Prepar ...

  6. jdbc笔记(一) 使用Statement对单表的CRUD操作

    jdbc连接mysql并执行简单的CRUD的步骤: 1.注册驱动(需要抛出/捕获异常) Class.forName("com.mysql.jdbc.Driver"); 2.建立连接 ...

  7. JDBC笔记一

    连接池原理 数据库连接池:1.提前创建好多个连接对象,放到缓存中(集合),客户端用时直接从缓存中获取连接 ,用完连接后一定要还回来. 目的:提高数据库访问效率.  模拟代码: package com. ...

  8. JDBC 笔记3 通过PreparedStatement 对数据库进行增删改查 (转载)

    之前MVC时一直用它,学了框架后就没怎么用了.这里转载一位同学的博客,以后可能也会用到的. 转自:https://www.cnblogs.com/zilong882008/archive/2011/1 ...

  9. JDBC的简单笔记

    JDBC笔记: JDBC:java database connectivity SUN公司提供的一套操作数据库的标准规范. JDBC与数据库驱动的关系:接口与实现的关系. JDBC规范(掌握四个核心对 ...

随机推荐

  1. 下载工具系列——Aria2 (几乎全能的下载神器)

    一.介绍 说完了前面一堆BT/PT客户端,现在终于轮到Aria2了,关于这个我就不介绍太多了,自从百度限速以来我觉得这个快变成众所周知的了,我平时也收集了各种和Aria2相关的插件或者是辅助软件之类的 ...

  2. 用友U8根据客户简称/供应商简称的拼音首字母生成助记码

    用友U8+中,客户档案和供应商档案可以设置自动生成助记码,但软件只能自动根据客户全称/供应商全称生成助记码,而无法选择按简称生成助记码,这显然十分不方便,可以通过如下方式解决: 修改步骤 1.往数据库 ...

  3. OpenCV vs. Armadillo vs. Eigen on Linux

    OpenCV vs. Armadillo vs. Eigen on Linux From:http://nghiaho.com/?p=936 In this post I’ll be comparin ...

  4. IntelliJ IDEA 创建java application

    1.打开IntelliJ IDEA,选择File——New——Project... 2.选择左侧的java,然后在右侧的Project SDK 中添加 java 环境目录,点击Next 3. 在下面的 ...

  5. [转帖]springboot+k8s+抛弃springcloud.eureka

    springboot+k8s+抛弃springcloud.eureka https://www.cnblogs.com/lori/p/12048743.html springboot开发微服务框架一般 ...

  6. OCC与MVCC 的区别

    一.前言 在数据库中,并发控制是指在多个用户/进程/线程同时对数据库进行操作时,如何保证事务的一致性和隔离性的,同时最大程度地并发. 当多个用户/进程/线程同时对数据库进行操作时,会出现3种冲突情形: ...

  7. keyword:react native bridge

    js engine native react native bridge https://cn.bing.com/images/search?view=detailV2&id=AAF39636 ...

  8. python--线程和进程的初识

    一.进程与线程之间的关系 1.线程是属于进程的,线程运行在进程空间内,同一进程所产生的线程共享同一内存空间,当进程退出时该进程所产生的线程都会被强制退出并清除. 2.线程可与属于同一进程的其它线程共享 ...

  9. 转:Windows系统环境下安装dlib

    原文链接 因为今天安装Face Recognition,需要先按照 dlib .需要在windows环境下做一些图片处理,所以需要在pycharm中配置环境,而其中需要的主要是dlib的安装: 下面说 ...

  10. linux 忘记mysql用户root密码 解决方案

    1.vim /etc/my.cnf[mysqld]skip-grant-tables ##追加此行,跳过权限表, 2.重启mysqlsystemctl restart mysqld 3.mysql 登 ...