?概念:
Java Database Connectivity,是对数据库的连接。JDBC规范了接口,具体的实现类由数据库厂商来实现。
使用的包:
会使用到的包 | 说明 | java.sql | 所有与 JDBC 访问数据库相关的接口和类 | javax.sql ? | 数据库扩展包,提供数据库额外的功能。如:连接池 | 数据库的驱动 | 由各大数据库厂商提供,需要额外去下载,是对 JDBC 接口实现的类 |
JDBC的核心API:
接口或类 ? | 作用 | DriverManager类 | 1) 管理和注册数据库驱动 2)?得到数据库连接对象 | Connection ?接口 | 一个连接对象,可用于创建 Statement 和 PreparedStatement 对象 | Statement ?接口 | 一个 SQL 语句对象,用于将 SQL 语句发送给数据库服务器。 | PreparedStatement ?接口 | 一个 SQL 语句对象,是 Statement 的子接口 | ResultSet ?接口 | 用于封装数据库查询的结果集,返回给客户端 Java 程序 | CallableStatement?接口 | 一个 SQL 语句对象,是 Statement 的子接口 , 用于调用存储过程 | ResultSetMetaData | 获取关于 ResultSet 对象中列的类型和属性信息的对象 |
?JDBC的API打通数据库:
连接java连接数据库的步骤:
声明执行sql语句的对象:
Statement ?接口:
executeUpdate:使用Statement执行DDL和DML语句区别在于执行DDL语句返回值为0,执行DML语句后返回值为受影响的记录条数。
executeQuery:该方法会得到ResultSet对象, JDBC使用ResultSet对象封装数据库查询的结果集,通过移动ResultSet的记录指针来取出结果集的内容, 对结果集进行遍历。
ResultSet是个结果集,其中next()方法是判断是否有下一行,最开始的时候是指向第一行的前面的。
常见的数据转化:(相应的方法里面可以是索引(从1开始),也可以是字段名字)
SQL ?类型 | JDBC对应方法(resultset方法) | 返回类型 | int | getInt() | int | char , varchar | getString() | String | decimal | getDouble | double | date | getDate() | Java.sql.Date 只代表日期 | time | getTime() | Java.sql.Time 只表示时间 | timestamp | getTimestamp() | Java.sql.TimeStamp 日期和时间 |
注意:目前我们用的日期在数据库里面是用字符串表示的,所以,在jdbc里面获取的时候是getstring。?
import java.sql.*;
public class connection {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
String user = "root";
String password = "123456";
// URL:协议+主机+端口+路径+参数
String url = "jdbc:mysql://localhost:3306/focusone?useSSl=false&serverTimezone = Asia/Shanghai";
// 01:加载驱动类:驱动类由数据库厂家提供
Class.forName("com.mysql.cj.jdbc.Driver");
// 02:利用驱动管理类建立要连接的数据库的对象。
Connection connection = DriverManager.getConnection(url, user, password);
// System.out.println(connection);//调用tostring方法
// 03:创建执行sql语句的对象Statement:执行sql语句;
Statement statement = connection.createStatement();
// 04:
// executeUpdate()方法执行sql语句:
int i = statement.executeUpdate("create table 电磁感应(id int,name varchar(3))");//DDL
System.out.println("受影响的行:"+i);
int i1 = statement.executeUpdate("insert into 电磁感应 values (123,'di')");//DML
System.out.println("受影响的行:"+i1);
// executeQuery()方法执行sql语句:
ResultSet resultSet = statement.executeQuery("select * from 电磁感应");//DQL
while (resultSet.next()){//遍历结果集对象
System.out.print(resultSet.getInt(1)+"\t");
System.out.print(resultSet.getString(2)+"\t");
}
// 05:关闭结果集、声明对象和连接:
resultSet.close();
statement.close();
connection.close();
}
}
sql语句的注入问题:?
本质:sql语句要输入的地方有sql的关键字,在数据库执行的时候,被当成了关键字所造成的。
String sql = "select * from tab_user where user_name='newboy' and user_pass='a' or '1'='1
'?"
上述语句 where后面 变为 条件1 and 条件2 or true , 无论用户名和密码的条件1和条件2是否为true,最后都进行了逻辑或操作 ,'1'='1'?为true , 整个where就是true。(and的优先级大于or)。
所以我们常用PreparedStatement ?接口。
PreparedStatement ?接口:(Statement接口的子类)
优点:
- 对于相似的一个sql语句,只需编译一次,生成相应的模板,之后相似的sql'语句就可以套用模板,速度加快。
- 可以防止sql的注入的问题
?缺点:对于不相似的sql语句都要更具其创建预编译对象。
reparedStatement需要使用问号占位符来代替Statement中需要拼接进入sql的参数.
PreparedStatement中设置参数的方法 ?? | 描述 | void setDouble(int parameterIndex, double x) | 将指定参数设置为给定 Java double 值。 | void setFloat(int parameterIndex, float x) | 将指定参数设置为给定 Java float值。 | void setInt(int parameterIndex, int x) | 将指定参数设置为给定 Java int 值。 | void setLong(int parameterIndex, long x) ? | 将指定参数设置为给定 Java long 值。 | void setObject(int parameterIndex, Object x) ? | 使用给定对象设置指定参数的值。 | void setString(int parameterIndex, String x) | 将指定参数设置为给定 Java String 值。 |
import java.net.ConnectException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class preparestatement {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//连接数据库:
String user = "root";
String password = "123456";
String url = "jdbc:mysql://localhost:3306/focusone?useSSl=false&serverTimezone = Asia/Shanghai";
Class.forName("com.mysql.cj.jdbc.Driver");
Connection connection = DriverManager.getConnection(url, user, password);
//根据sql语句创建预编译对象:
String sql = "insert into 电磁感应 values (?,?)"; //?相当于占位符
PreparedStatement preparedStatement = connection.prepareStatement(sql);
//设置占位符的值;
preparedStatement.setInt(1, 124);
preparedStatement.setString(2, "lll");//注意这里必须是字符串类型==>双引号
//执行:
int i = preparedStatement.executeUpdate();
System.out.println("受影响的行:"+i);
// 关:
preparedStatement.close();
connection.close();
}
}
注意:占位符只能占列值,不能占字段的名字等等。?
封装工具类——连接和关闭:
import javax.swing.*;
import java.net.ConnectException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class javatool {
private static final String user = "root";
private static final String password = "123456";
private static final String url = "jdbc:mysql://localhost:3306/focusone?useSSl=false&serverTimezone = Asia/Shanghai";
private static final String driver = "co.mysql.cj.jdbc.Driver";
//加载驱动类:做工具类,编译器异常不能上抛。
static {
try {
Class.forName(driver);
}catch (ClassNotFoundException e) {
e.printStackTrace();
System.out.println("加载驱动类失败,请查看类名或者是否导入包");
}
}
//获取数据库连接:
public static Connection getcon(){
try {
Connection connection = DriverManager.getConnection(url, user, password);
return connection;
} catch (SQLException throwables) {
throwables.printStackTrace();
throw new RuntimeException("获取数据库连接失败");
//把编译期的异常转换成运行期异常,调用着不必声明或是处理这个异常,遇见这个异常就停了吧。
//目的,是为了让调)用者得到一个正确的连接(这是根本)
//需要声明的都是编译器异常(必须处理),所以抛出运行期异常一般不处理
}
}
//关闭声明对象和连接:
public static void release(Statement statement, Connection connection){
if(statement != null){
try {
statement.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(connection != null){
try {
connection.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
?封装工具类——查询
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
class singer {
private Integer sid;
private String sname;
private String sex;
private Double salary;
private String birthday;
private String display;
public singer() {
}
public singer(Integer sid, String sname, String sex, Double salary, String birthday, String display) {
this.sid = sid;
this.sname = sname;
this.sex = sex;
this.salary = salary;
this.birthday = birthday;
this.display = display;
}
public Integer getSid() {
return sid;
}
public String getSname() {
return sname;
}
public String getSex() {
return sex;
}
public Double getSalary() {
return salary;
}
public String getBirthday() {
return birthday;
}
public String getDisplay() {
return display;
}
@Override
public String toString() {
return "singer{" +
"sid=" + sid +
", sname='" + sname + '\'' +
", sex='" + sex + '\'' +
", salary=" + salary +
", birthday='" + birthday + '\'' +
", display='" + display + '\'' +
'}';
}
}
public class query {
public static List<singer> getinformation() throws SQLException {
Connection connection = javatool.getcon();
String sql = "select * from tsinger where sex = ?";
PreparedStatement preparedStatement = connection.prepareStatement(sql);
preparedStatement.setString(1, "女");//不能用单引号,也不能没有双引号
ResultSet resultSet = preparedStatement.executeQuery();//获得结果集对象
List<singer> list = new ArrayList<>();
while (resultSet.next()){
int anInt = resultSet.getInt(1);
String string = resultSet.getString(2);
String string1 = resultSet.getString(3);
double aDouble = resultSet.getDouble(4);
String string2 = resultSet.getString(5);
String string3 = resultSet.getString(6);
singer singer = new singer(anInt,string, string1, aDouble, string2,string3);
list.add(singer);
}
return list;
}
}
class test01{
public static void main(String[] args) throws SQLException {
List<singer> getinformation = query.getinformation();
for(singer i :getinformation){
System.out.println(i);
}
}
}
查看结果集的表结构ResultSetMetaData:
获取此对象:resultSet.getMetaData()
此对象常用的方法:
方法 | 作用 | int getColumnCount() | 返回该ResultSet的列数量。 | String getColumnName(int columnIndex) | 返回指定索引的列名。 | int getColumnType(int column) | 返回指定索引的列类型。 |
?演示:在不知道数据库查询表结构的时候,该如何查询表:
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
public class resultmetadate {
public static void main(String[] args) throws SQLException {
Connection getcon = javatool.getcon();
//执行sql对象
Statement statement = getcon.createStatement();
String sql = "select * from tsinger";
//获得结果集:
ResultSet resultSet = statement.executeQuery(sql);
ResultSetMetaData metaData = resultSet.getMetaData();
//获取列数:
int columnCount = metaData.getColumnCount();
for (int i = 1; i <= columnCount; i++) {//索引从1开始;
System.out.print(metaData.getColumnName(i)+"\t");
}
System.out.println();
while (resultSet.next()){//?:是一行
for (int i = 1; i <=columnCount ; i++){
System.out.print(resultSet.getObject(i));//获得一个单元格的内容
//获得的object对象属于上转型对象,在调用tostring方法的时候,是调用子类重写的。
}
System.out.println();
}
javatool.release(statement, resultSet, getcon);
}
}
JDBC处理存储过程:
CallableStatement接口:通过connection.prepareCall(sql模板)方法获得。(preparestatement的子类)
sql模板:
{call 存储过程名(?,?,?...)}
?为占位符
对于存储过程中的传入参数:使用其setXXX()方法;
对于传出参数:必须先注册,再获得:
存储过程传出参数相关的方法:
方法 | 描述 | registerOutParameter(int parameterIndex, int sqlType) | 注册此索引的占位符参数为传出参数 | getXXX(int parameterIndex) | 获得此索引处的传出数据 |
?演示:
基本流程:设置入参和注册返回值==>执行==>获取返回值
import java.lang.reflect.Type;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Types;
public class procedure {
public static void main(String[] args) throws SQLException {
Connection getcon = javatool.getcon();
// in sidp INT,in newdisplay VARCHAR(20),OUT sum INT
String sql = "call pro10(?,?,?)";
CallableStatement callableStatement = getcon.prepareCall(sql);
//设置入参:
callableStatement.setInt(1, 1001);
callableStatement.setString(2, "我真帅");
//注册返回值:
callableStatement.registerOutParameter(3, Types.INTEGER);
//执行
callableStatement.execute();//不清楚查询语句的类性的时候,用execute
//获得返回值:
int anInt = callableStatement.getInt(3);
System.out.println(anInt);
javatool.release(callableStatement, getcon);
}
}
?处理blob类型数据:
lob(Binary Long Object)是二进制长对象的意思,Blob列通常用于存储大文件,典型的Blob内容是一张图片或一个声音文件,由于他们的特殊性,必须使用特殊的方式来存储。使用Blob列可以把图片、声音等文件的二进制数据保存到数据库里,并可以从数据库里恢复指定文件。
如果需要将图片插入到数据库,显然不能直接通过普通的SQL语句来完成,因为有一个关键的问题——Blob常量无法表示。所以将Blob数据插入数据库需要使用PreparedStatement,该对象有一个方法:setBinaryStream(int parameterIndex,InputStream x),该方法可以为指定参数传入二进制输入流,从而可以实现将Blob数据保存到数据库的功能。
当我们需要从ResultSet里取出Blob数据时,可以调用ResultSet的getBlob(int columnIndex),该方法将返回一个Blob对象,Blob对象提供了getBinaryStream()方法来获取该Blob数据的输入流,也可以使用Blob对象提供的getByte()方法直接取出Blob对象封装的二进制数据。
binary | 定长二进制字符串类型,它以二进制形式保存字符串。 | varbinary | 可变长度的二进制字符串类型,它以二进制形式保存字符串。 | tinyblob/blob/ mediumtblob/ longblob | 1字节/2字节/3字节/4字节的二进制大对象,可以用于存储图片,音乐等二进制数据,分别可存储255B/64KB/16MB/4GB大小。 |
?演示:
数据库创建表:
create table tab_file(
file_id int PRIMARY key auto_increment,
file_name varchar(50),
file_data MEDIUMBLOB # MEDIUMBLOB 最大16MB
);
?
向数据库存入:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class blod {
public static void main(String[] args) throws FileNotFoundException, SQLException {
//获取文件:
File file = new File("C:\\Users\\Lenovo\\Desktop\\02.png");
String filename = file.getName();
FileInputStream fileInputStream = new FileInputStream(file);
Connection connection = javatool.getcon();
String sql = "insert into tab_file values (?,?,?)";
PreparedStatement preparedStatement = connection.prepareStatement(sql);
//设置值
preparedStatement.setInt(1, 111);
preparedStatement.setString(2, filename);
preparedStatement.setBinaryStream(3, fileInputStream);
//执行
int i = preparedStatement.executeUpdate();
System.out.println(i);
javatool.release(preparedStatement, connection);
}
}
向外输出BLOB:
import java.io.*;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class bolbin {
public static void main(String[] args) throws SQLException, IOException {
//字节流对于视频和图片的输入和输出
File file = new File("E:\\02.png");
Connection getcon = javatool.getcon();
String sql = "select * from tab_file where file_id = 11";
PreparedStatement preparedStatement = getcon.prepareStatement(sql);
ResultSet rs = preparedStatement.executeQuery();
if(rs.next()){
FileOutputStream fos = new FileOutputStream(file);//内存读取到外存
InputStream binaryStream = rs.getBinaryStream(3);//数据库到内存
byte[] b = new byte[100];
int len = -1;
while((len = binaryStream.read(b)) != -1){
fos.write(b, 0, len);
}
fos.close();
binaryStream.close();
}
javatool.release(preparedStatement, getcon);
}
}
JBDC处理事务:
JDBC连接也提供了事务支持,JDBC连接的事务支持由Connection提供,Connection默认打开自动提交,即关闭事务。在这种情况下,每条SQL语句一旦执行,便会立即提交到数据库,永久生效,无法对其进行回滚操作。(就是先不修改数据库)
可以调用Connection的setAutoCommit(boolean auto)方法来关闭自动提交,开始事务.如果所有的SQL语句都执行成功了,程序可以调用Connection的commit()方法来提交事务,如果任意一条SQL执行失败,则应该调用Connection的rollback()方法回滚事务.
?演示:
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class affair {
public static void main(String[] args) {
Connection getcon = javatool.getcon();
PreparedStatement preparestatement = null;
try{
//关闭事务的自动提交==>开启连接上的事务;
getcon.setAutoCommit(false);
//添加表格:
String sql = "insert into tsinger (sname,display) values(?,?)";
preparestatement = getcon.prepareStatement(sql);
preparestatement.setString(1, "kegcdceece");
preparestatement.setString(2,"udgcedcece");
int i = preparestatement.executeUpdate();
System.out.println(i);
//删除歌手:
sql = "delete from tsinger55 where sid = 1001";
preparestatement = getcon.prepareStatement(sql);
//这也就显示出来了这个对象的缺点:不同的sql语句都要编译;
int i1 = preparestatement.executeUpdate();
System.out.println(i1);
//提交:
getcon.commit();
} catch (SQLException throwables) {
throwables.printStackTrace();
//当出现异常的时候:
try {
System.out.println("事务回滚了");
//事务回滚后,就会回到原来的模样。
getcon.rollback();
} catch (SQLException e) {
e.printStackTrace();
}
} finally {
javatool.release(preparestatement, getcon);
}
}
}
连接池:解决频繁开启和关闭连接造成的数据库的性能下降:
使用Druid连接池制作工具类:
import com.alibaba.druid.pool.DruidDataSourceFactory;
import sun.plugin2.message.ReleaseRemoteObjectMessage;
import javax.print.attribute.standard.NumberUp;
import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
//每个连接池都要自己的配置文件
//每句话都加注释:
public class javatool {
private static DataSource dataSource;//连接池对象
static {
Properties properties = new Properties();
// Hashtable<Object,Object>的子类,map的后代类
InputStream resourceAsStream = javatool.class.getClassLoader().getResourceAsStream("druid.properties");//类路径
try {
//从输入流中读取键和元素对到集合
properties.load(resourceAsStream);
dataSource = DruidDataSourceFactory.createDataSource(properties);
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("e.getmessage");
}
}
public static DataSource gettool(){//获取连接池,可以在其他类中使用
return dataSource;
}
public static Connection getcon(){//连接池的一根连接
try {
return dataSource.getConnection();
} catch (Exception e) {
e.printStackTrace();throw new RuntimeException();
}
}
public static void release(Statement statement, ResultSet resultSet,Connection connection){
if(statement != null){
try {
statement.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(resultSet != null){
try { resultSet.close(); } catch (Exception e) { e.printStackTrace(); }
}
if(connection != null){
try { connection.close(); } catch (Exception e) { e.printStackTrace(); }
}
}
}
?注意:使用该连接池的时候,一定到先导入
?JDBCTemplate类:
Spring框架对JDBC的简单封装。提供了一个JDBCTemplate对象简化JDBC的开发.尤其是简化了JDBC查询操作把结果集封装为java对象的过程.
常用方法:
方法名 | 作用 | update() | 执行DML语句。增、删、改语句 | query() | 查询结果,将结果封装为JavaBean对象 | queryForObject() | 查询结果,将结果封装为对象一般用于聚合函数的查询 | queryForMap() | 查询结果将结果集封装为map集合,将列名作为key,将值作为value 将这条记录封装为一个map集合(适合查一行) | queryForList() | 查询结果将结果集封装为list集合,将每一条记录封装为一个Map集合,再将Map集合装载到List集合中(适合查多行) |
注: query()方法的参数一般我们使用BeanPropertyRowMapper实现类。可以完成数据到JavaBean的自动封装.
增、删、改:
import org.junit.Test;
import org.springframework.jdbc.core.JdbcTemplate;
import java.sql.Connection;
import java.util.List;
public class unin {
//junit单元测试:每个实例方法既可以当作main方法一样去执行,又具有实例方法的特性
//根据连接池对象创建JdbcTemplate对象
JdbcTemplate jdbcTemplate = new JdbcTemplate(javatool.gettool());
@Test
//新增:
public void test() throws Exception{
String sql ="insert into tsinger (sname,display) values (?,?)";
Object[] args = {"lwcnnw5kj5","wkkbbbbcs"};//给占位符赋值的。
int update = jdbcTemplate.update(sql, args);
System.out.println(update);
}
//删除:
@Test
public void test02() throws Exception{
String sql = "delete from tsinger where display is null";
int update = jdbcTemplate.update(sql);
System.out.println(update);
}
}
查询:
?封装对象:
成员变量必须有setXXX()方法且这个类必须含有无参构造(模板是根据这两个方法封装)
public class singer {
private Integer sid;
private String sname;
private String sex;
private Double salary;
private String birthday;
private String display;
public singer() {
}
public Integer getSid() {
return sid;
}
public void setSid(Integer sid) {
this.sid = sid;
}
public String getSname() {
return sname;
}
public void setSname(String sname) {
this.sname = sname;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Double getSalary() {
return salary;
}
public void setSalary(Double salary) {
this.salary = salary;
}
public String getBirthday() {
return birthday;
}
public void setBirthday(String birthday) {
this.birthday = birthday;
}
public String getDisplay() {
return display;
}
public void setDisplay(String display) {
this.display = display;
}
@Override
public String toString() {
return "singer{" +
"sid=" + sid +
", sname='" + sname + '\'' +
", sex='" + sex + '\'' +
", salary=" + salary +
", birthday='" + birthday + '\'' +
", display='" + display + '\'' +
'}';
}
}
当查询结构只有一行的时候:queryForObject()
import org.junit.Test;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import java.sql.Connection;
import java.util.List;
public class unin {
//junit单元测试:每个实例方法既可以当作main方法一样去执行,又具有实例方法的特性
//根据连接池对象创建JdbcTemplate对象
JdbcTemplate jdbcTemplate = new JdbcTemplate(javatool.gettool());
//查询O:
// 当查询结构只有一行的时候:
@Test
public void test() throws Exception{
String sql = "select * from tsinger where sid = ?";
Object[] args = {1004};
//注意:new BeanPropertyRowMapper<singer>(singer.class)这里写要要封装成那个类
//使用此模板的好处就在于我们不用自己去遍历结果集去一个个的再添加到集合当中
//要封装成的类的成员遍历或是构造方法,要和查询得出的表的结构一样。
singer singer = jdbcTemplate.queryForbject(sql, new BeanPropertyRowMapper<singer>(singer.class), args);
System.out.println(singer);
}
}
当查询结构有多行的时候:query()
import org.junit.Test;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceUtils;
import java.sql.Connection;
import java.util.List;
public class unin {
//junit单元测试:每个实例方法既可以当作main方法一样去执行,又具有实例方法的特性
//根据连接池对象创建JdbcTemplate对象
JdbcTemplate jdbcTemplate = new JdbcTemplate(javatool.gettool());
//查询O:
// 当查询多行的时候:
@Test
public void test() throws Exception{
String sql = "select * from tsinger where sex = ?";
Object[] args = {"女"};
//注意:new BeanPropertyRowMapper<singer>(singer.class)这里写要要封装成那个类
//使用此模板的好处就在于我们不用自己去遍历结果集去一个个的再添加到集合当中
//要封装成的类的成员遍历或是构造方法,要和查询得出的表的结构一样。
List<singer> query = jdbcTemplate.query(sql, args, new BeanPropertyRowMapper<singer>(singer.class));
//封装成什么对象,就加载什么类
for(singer singer : query){
System.out.println(singer);
}
}
}
以上两种查询都是封装成对象的:
查询聚合函数:queryForObject()(一行)
import org.junit.Test;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceUtils;
import java.sql.Connection;
import java.util.List;
public class unin {
//junit单元测试:每个实例方法既可以当作main方法一样去执行,又具有实例方法的特性
//根据连接池对象创建JdbcTemplate对象
JdbcTemplate jdbcTemplate = new JdbcTemplate(javatool.gettool());
//查询O:
// 当查询多行的时候:
@Test
public void test() throws Exception{
String sql = "select count(*) from tsinger where sex = ?";
Object[] args = {"女"};
//注意:new BeanPropertyRowMapper<singer>(singer.class)这里写要要封装成那个类
//使用此模板的好处就在于我们不用自己去遍历结果集去一个个的再添加到集合当中
//要封装成的类的成员遍历或是构造方法,要和查询得出的表的结构一样。
Integer integer = jdbcTemplate.queryForObject(sql, args, Integer.class);//想返回什么对象,就加载什么对象
System.out.println(integer);
}
}
当我们没有设置相对应的javabean和查询表格相对应的时候,·我们可以尝试利用键值对:
此时,每一个map集合就相当于上面的封装对象。
queryForMap和queryForList:
import org.junit.Test;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceUtils;
import java.sql.Connection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.AbstractQueuedLongSynchronizer;
public class unin {
//junit单元测试:每个实例方法既可以当作main方法一样去执行,又具有实例方法的特性
//根据连接池对象创建JdbcTemplate对象
JdbcTemplate jdbcTemplate = new JdbcTemplate(javatool.gettool());
@Test
//只有一行时候:
public void test() throws Exception{
String sql = "select * from tsinger where sid = ?";
Object[] args = {1002};
//注意:new BeanPropertyRowMapper<singer>(singer.class)这里写要要封装成那个类
//使用此模板的好处就在于我们不用自己去遍历结果集去一个个的再添加到集合当中
//要封装成的类的成员遍历或是构造方法,要和查询得出的表的结构一样。
Map<String, Object> stringObjectMap = jdbcTemplate.queryForMap(sql, args);
System.out.println(stringObjectMap);
}
@Test
public void test02() throws Exception{
String sql = "select * from tsinger where sex = ?";
Object[] args = {"女"};
List<Map<String, Object>> maps = jdbcTemplate.queryForList(sql, args);
for(Map<String,Object> map :maps){
System.out.println(map);
}
}
}
|