架构时——没有什么是加一层解决不了的,若是有,就再加一层。html
如tomcat集群上面的Nginx,Nginx集群上面的LVS.java
JDBC是数据库驱动的接口规范,是SUN公司将来简化开发人员对数据库的统一操做而提供的一个规范。即Java数据库链接,(Java Database Connectivity,简称JDBC)。mysql
这些规范有具体的数据库厂商去实现,而开发人员只须要掌握JDBC接口操做便可。sql
没有JDBC时:数据库
经过JDBC时:apache
口诀:贾琏欲执事——加连预执释tomcat
url键值对 | 描述 |
---|---|
useUnicode=true | 支持中文编码 |
characterEncoding=utf8 | 设置字符集编码为utf8 |
useSSL=true | 使用安全链接 |
oracle没有数据库概念,一个模式就是一个库安全
public class JDBCTest { public static void main(String[] args) { //查询、插入展现 select(); insert(); } public static void select() { Connection conn = null; Statement st = null; ResultSet rs = null; try { conn = JDBCUtil.getConnection(); st = conn.createStatement(); String sql = "select * from user where 1=1"; rs = st.executeQuery(sql); while (rs.next()) { //参数为字段名 System.out.println(rs.getString("name")); } } catch (Exception throwables) { throwables.printStackTrace(); } finally { JDBCUtil.release(rs, st, conn); } } public static void insert() { Connection conn = null; Statement st = null; ResultSet rs = null; try { conn = JDBCUtil.getConnection(); st = conn.createStatement(); String sql = "insert into user(`name`,age)values ('安安',1)"; int i = st.executeUpdate(sql); if (i > 0) { System.out.println("插入成功"); } } catch (Exception throwables) { throwables.printStackTrace(); } finally { JDBCUtil.release(rs, st, conn); } } } //JDBC工具类,返回的Connection至关于一个数据库操做对象,能够用于事务等处理 public class JDBCUtil { private static String URL = null; private static String USERNAME = null; private static String PASSWORD = null; private static String DIRVIER = null; static { //经过classloader去获取配置文件的输入流 InputStream is = JDBCUtil.class.getClassLoader().getResourceAsStream("db.properties"); //再建立properties对象去load输入流 Properties properties = new Properties(); try { properties.load(is); } catch (IOException e) { e.printStackTrace(); } URL = properties.getProperty("roy.mysql.url"); USERNAME = properties.getProperty("roy.mysql.username"); PASSWORD = properties.getProperty("roy.mysql.password"); DIRVIER = properties.getProperty("roy.mysql.driver"); try { Class.forName(DIRVIER); } catch (ClassNotFoundException e) { e.printStackTrace(); } } public static Connection getConnection() throws SQLException { return DriverManager.getConnection(URL, USERNAME, PASSWORD); } public static void release(ResultSet rs, Statement st, Connection conn) { try { if (rs != null) { rs.close(); } if (st != null) { st.close(); } if (conn != null) { conn.close(); } } catch (Exception e) { e.printStackTrace(); } } }
roy.mysql.url=jdbc:mysql://localhost:3306/mybatis_plus?useSSL=true&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8 roy.mysql.username=root roy.mysql.password=123456 roy.mysql.driver=com.mysql.cj.jdbc.Driver #注意properties文件就是String类型的键值对,所以不须要再加""双引号
所谓SQL注入,就是经过把SQL命令插入到Web表单递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。服务器
咱们永远不要信任用户的输入,咱们必须认定用户输入的数据都是不安全的,咱们都须要对用户输入的数据进行过滤处理。mybatis
PreparedStatement能够防止sql注入,其防止sql注入的本质是PreparedStatement会把传进来的参数当作字符,假如其中存在转义符如''
引号这种,会被直接转义处理;且由于预编译因此效率更高。
DB中执行的SQL为
select file from file where name = '\'test\' or 1=1'
把整个参数用引号包起来,并把参数中的引号做为转义字符,从而避免了参数也做为条件的一部分
public class PreparedStatementTest { public static void main(String[] args) { select(); insert("白衣阿风",28); } public static void select() { Connection conn = null; PreparedStatement st = null; ResultSet rs = null; try { conn = JDBCUtil.getConnection(); String sql = "select * from user where 1=1 and `name` =?"; st = conn.prepareStatement(sql); st.setString(1,"艾米"); rs = st.executeQuery(); while (rs.next()) { //参数为字段名 System.out.println(rs.getString("email")); } } catch (Exception throwables) { throwables.printStackTrace(); } finally { JDBCUtil.release(rs, st, conn); } } public static void insert(String name,Integer age) { Connection conn = null; PreparedStatement st = null; ResultSet rs = null; try { conn = JDBCUtil.getConnection(); String sql = "insert into user(`name`,age)values (?,?)"; st = conn.prepareStatement(sql); st.setString(1,name); st.setInt(2,age); int i = st.executeUpdate(); if (i > 0) { System.out.println("插入成功"); } } catch (Exception throwables) { throwables.printStackTrace(); } finally { JDBCUtil.release(rs, st, conn); } } }
public class TranscationTest { public static void main(String[] args) { transcation("艾米哈珀","哈米国王",new BigDecimal("1500000")); } public static void transcation(String seller,String buyer, BigDecimal money) { Connection conn = null; PreparedStatement st = null; ResultSet rs = null; try { conn = JDBCUtil.getConnection(); //关闭事务自动提交,这时候表示自动开启事务 conn.setAutoCommit(false); String sql1 = "update t_bank_account set money=money+? where `name`=?"; st = conn.prepareStatement(sql1); st.setBigDecimal(1,money); st.setString(2,seller); int i = st.executeUpdate(); //测试事务异常 // System.out.println(1/0); String sql2 = "update t_bank_account set money=money -? where `name`=?"; st = conn.prepareStatement(sql2); st.setBigDecimal(1,money); st.setString(2,buyer); int j = st.executeUpdate(); if (j > 0 && i > 0) { System.out.println("交易成功"); } conn.commit(); } catch (Exception throwables) { try { conn.rollback(); } catch (SQLException e) { e.printStackTrace(); } throwables.printStackTrace(); } finally { JDBCUtil.release(rs, st, conn); } } }
池化技术的出如今与每次建立链接和释放链接都很是的耗费资源,现实场景中,咱们更好的处理方法是经过池化技术来优化和提升这种每次都要建立释放资源的事情,就像咱们的工厂生产产品或者银行对外提供服务,工厂不能有产品要生产才招一个临时工,生产完就解雇掉;银行不能每次要处理业务就开个门或者说开个窗口,处理好了就把处理窗口关闭了,二者在现实中咱们都能观察到:工厂是有必定数量的稳定工人的,而银行的对外业务窗口也是稳定的,这就是池化技术。
数据库链接池的本质是实现一个DataSource接口。
使用了这些数据库链接池后,咱们在项目开发中就不须要编写链接数据库的代码了。
maven依赖
<!-- dbcp链接池依赖,commons-dbcp内部已经依赖了commons-pool--> <dependency> <groupId>commons-dbcp</groupId> <artifactId>commons-dbcp</artifactId> <version>1.4</version> </dependency> <dependency> <groupId>commons-pool</groupId> <artifactId>commons-pool</artifactId> <version>1.5.4</version> </dependency> <!-- c3p0链接依赖,c3p0内部已经依赖了mchange-commons-java--> <dependency> <groupId>com.mchange</groupId> <artifactId>c3p0</artifactId> <version>0.9.5.2</version> </dependency>
dbcp配置文件——dbcp.properties
driverClassName=com.mysql.cj.jdbc.Driver #url url=jdbc:mysql://localhost:3306/mybatis_plus?useSSL=true&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8 #用户名 username=root #密码 password=123456 #初试链接数 initialSize=30 #最大活跃数 maxTotal=30 #最大idle数 maxIdle=10 #最小idle数 minIdle=5 #最长等待时间(毫秒) maxWaitMillis=1000 #程序中的链接不使用后是否被链接池回收(该版本要使用removeAbandonedOnMaintenance和removeAbandonedOnBorrow) #removeAbandoned=true removeAbandonedOnMaintenance=true removeAbandonedOnBorrow=true #链接在所指定的秒数内未使用才会被删除(秒)(为配合测试程序才配置为1秒) removeAbandonedTimeout=1
c3p0配置文件——c3p0-config.xml
<c3p0-config> <!-- 使用默认的配置读取链接池对象 --> <default-config> <!-- 链接参数 --> <property name="driverClass">com.mysql.cj.jdbc.Driver</property> <property name="jdbcUrl">jdbc:mysql://localhost:3306/mybatis_plus?useSSL=true&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8</property> <property name="user">root</property> <property name="password">123456</property> <!-- 链接池参数 --> <!--初始化申请的链接数量--> <property name="initialPoolSize">5</property> <!--最大的链接数量--> <property name="maxPoolSize">10</property> <!--超时时间--> <property name="checkoutTimeout">3000</property> </default-config> <!-- 其余如oracle、mysql等的配置,要使用时只须要指定要加载的配置名问参数,不传则使用默认配置--> <named-config name="mysql"> <!-- 链接参数 --> <property name="driverClass">com.mysql.jdbc.Driver</property> <property name="jdbcUrl">jdbc:mysql://localhost:3306/test</property> <property name="user">root</property> <property name="password">root</property> <!-- 链接池参数 --> <property name="initialPoolSize">5</property> <property name="maxPoolSize">8</property> <property name="checkoutTimeout">1000</property> </named-config> </c3p0-config>
public class C3P0Util { private static DataSource dataSource = null; static { //经过classloader去获取配置文件的输入流 try { dataSource = new ComboPooledDataSource(); //不指定配置名称则读取默认的c3p0配置 //xml文件不须要读取成流便能读取文件 // dataSource = new ComboPooledDataSource("mysql"); } catch (Exception e) { e.printStackTrace(); } } public static Connection getConnection() throws SQLException { return dataSource.getConnection(); } public static void release(ResultSet rs, Statement st, Connection conn) { try { if (rs != null) { rs.close(); } if (st != null) { st.close(); } if (conn != null) { conn.close(); } } catch (Exception e) { e.printStackTrace(); } } } public class DBCPUtil { private static DataSource dataSource = null; static { //经过classloader去获取配置文件的输入流 InputStream is = DBCPUtil.class.getClassLoader().getResourceAsStream("dbcp.properties"); //再建立properties对象去load输入流 Properties properties = new Properties(); //Properties文件注意要加载流,不然读不到文件会报错以下 //org.apache.commons.dbcp.SQLNestedException: Cannot create JDBC driver of class '' for connect URL 'null' try { properties.load(is); } catch (IOException e) { e.printStackTrace(); } try { dataSource = BasicDataSourceFactory.createDataSource(properties); } catch (Exception e) { e.printStackTrace(); } } public static Connection getConnection() throws SQLException { return dataSource.getConnection(); } public static void release(ResultSet rs, Statement st, Connection conn) { try { if (rs != null) { rs.close(); } if (st != null) { st.close(); } if (conn != null) { conn.close(); } } catch (Exception e) { e.printStackTrace(); } } } public class ConnectionPoolTest { public static void main(String[] args) { c3p0(); dbcp(); } public static void c3p0() { Connection conn = null; Statement st = null; ResultSet rs = null; try { conn = C3P0Util.getConnection(); st = conn.createStatement(); String sql = "select * from user where 1=1"; rs = st.executeQuery(sql); while (rs.next()) { //参数为字段名 System.out.println(rs.getString("name")); } } catch (Exception throwables) { throwables.printStackTrace(); } finally { JDBCUtil.release(rs, st, conn); } } public static void dbcp() { Connection conn = null; Statement st = null; ResultSet rs = null; try { conn = DBCPUtil.getConnection(); st = conn.createStatement(); String sql = "insert into user(`name`,age)values ('安安啊',1)"; int i = st.executeUpdate(sql); if (i > 0) { System.out.println("插入成功"); } } catch (Exception throwables) { throwables.printStackTrace(); } finally { JDBCUtil.release(rs, st, conn); } } }
[狂神MySQL基础](