//1.创建数据源DataSource
DataSource dataSource = DataSourceUtils.getDataSource();
//2.创建JdbcTemplate,new JdbcTemplate(dataSource)
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
//3.调用JdbcTemplate的方法操作db,如增删改查
List<Map<String, Object>> maps = jdbcTemplate.queryForList(“select * from t_user”);
System.out.println(maps);
}
输出
[{id=114, name=路人}, {id=115, name=java高并发}, {id=116, name=spring系列}]
t_user表数据
mysql> select id,name from t_user;
±----±--------------+
| id | name |
±----±--------------+
| 114 | 路人 |
| 115 | java高并发 |
| 116 | spring系列 |
±----±--------------+
3 rows in set (0.00 sec)
上面查询返回了t_user
表所有的记录,返回了一个集合,集合中是一个Map,Map表示一行记录,key为列名,value为列对应的值。
有没有感觉到特别的方便,只需要jdbcTemplate.queryForList("select * from t_user")
这么简单的一行代码,数据就被获取到了。
下面我们继续探索更强大更好用的功能。
增加、删除、修改操作
JdbcTemplate中以update开头的方法,用来执行增、删、改操作,下面来看几个常用的。
无参情况
Api
int update(final String sql)
案例
@Test
public void test1() {
DataSource dataSource = DataSourceUtils.getDataSource();
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
int updateRows = jdbcTemplate.update(“INSERT INTO t_user (name) VALUE (‘maven系列’)”);
System.out.println(“影响行数:” + updateRows);
}
有参情况1
Api
int update(String sql, Object… args)
案例
sql中使用?作为占位符。
@Test
public void test2() {
DataSource dataSource = DataSourceUtils.getDataSource();
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
int updateRows = jdbcTemplate.update(“INSERT INTO t_user (name) VALUE (?)”, “mybatis系列”);
System.out.println(“影响行数:” + updateRows);
}
有参情况2
Api
int update(String sql, PreparedStatementSetter pss)
通过PreparedStatementSetter来设置参数,是个函数式接口,内部有个setValues方法会传递一个PreparedStatement参数,我们可以通这个参数手动的设置参数的值。
案例
@Test
public void test3() {
DataSource dataSource = DataSourceUtils.getDataSource();
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
int updateRows = jdbcTemplate.update(“INSERT INTO t_user (name) VALUE (?)”, new PreparedStatementSetter() {
@Override
public void setValues(PreparedStatement ps) throws SQLException {
ps.setString(1, “mysql系列”);
}
});
System.out.println(“影响行数:” + updateRows);
}
获取自增列的值
Api
public int update(final PreparedStatementCreator psc, final KeyHolder generatedKeyHolder)
案例
@Test
public void test4() {
DataSource dataSource = DataSourceUtils.getDataSource();
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
String sql = “INSERT INTO t_user (name) VALUE (?)”;
KeyHolder keyHolder = new GeneratedKeyHolder();
int rowCount = jdbcTemplate.update(new PreparedStatementCreator() {
@Override
public PreparedStatement createPreparedStatement(Connection con) throws SQLException {
//手动创建PreparedStatement,注意第二个参数:Statement.RETURN_GENERATED_KEYS
PreparedStatement ps = con.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
ps.setString(1, “获取自增列的值”);
return ps;
}
}, keyHolder);
System.out.println(“新记录id:” + keyHolder.getKey().intValue());
}
输出
新记录id:122
mysql> select id,name from t_user;
±----±----------------------+
| id | name |
±----±----------------------+
| 114 | 路人 |
| 115 | java高并发 |
| 116 | spring系列 |
| 117 | maven系列 |
| 118 | mysql系列 |
| 122 | 获取自增列的值 |
±----±----------------------+
6 rows in set (0.00 sec)
批量增删改操作
Api
int[] batchUpdate(final String[] sql);
int[] batchUpdate(String sql, List<Object[]> batchArgs);
int[] batchUpdate(String sql, List<Object[]> batchArgs, int[] argTypes);
案例
@Test
public void test5() {
DataSource dataSource = DataSourceUtils.getDataSource();
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
List<Object[]> list = Arrays.asList(
new Object[]{“刘德华”},
new Object[]{“郭富城”},
new Object[]{“张学友”},
new Object[]{“黎明”});
int[] updateRows = jdbcTemplate.batchUpdate(“INSERT INTO t_user (name) VALUE (?)”, list);
for (int updateRow : updateRows) {
System.out.println(updateRow);
}
}
查询操作
查询一列单行
Api
/**
-
sql:执行的sql,如果有参数,参数占位符?
-
requiredType:返回的一列数据对应的java类型,如String
-
args:?占位符对应的参数列表
**/
T queryForObject(String sql, Class requiredType, @Nullable Object… args)
案例
@Test
public void test6() {
DataSource dataSource = DataSourceUtils.getDataSource();
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
String name = jdbcTemplate.queryForObject(“select name from t_user where id = ?”, String.class, 114);
System.out.println(name);
}
输出
路人
db中对应数据
mysql> select name from t_user where id = 114;
±-------+
| name |
±-------+
| 路人 |
±-------+
1 row in set (0.00 sec)
使用注意
若queryForObject中sql查询无结果时,会报错
如id为0的记录不存在
mysql> select name from t_user where id = 0;
Empty set (0.00 sec)
@Test
public void test7() {
DataSource dataSource = DataSourceUtils.getDataSource();
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
String name = jdbcTemplate.queryForObject(“select name from t_user where id = ?”, String.class, 0);
System.out.println(name);
}
运行,会弹出一个异常EmptyResultDataAccessException
,期望返回一条记录,但实际上却没有找到记录,和期望结果不符,所以报错了
org.springframework.dao.EmptyResultDataAccessException: Incorrect result size: expected 1, actual 0
at org.springframework.dao.support.DataAccessUtils.nullableSingleResult(DataAccessUtils.java:97)
at org.springframework.jdbc.core.JdbcTemplate.queryForObject(JdbcTemplate.java:784)
这种如何解决呢,需要用到查询多行的方式来解决了,即下面要说到的queryForList
相关的方法,无结果的时候会返回一个空的List,我们可以在这个空的List上面做文章。
查询一列多行
Api
以queryForList开头的方法。
List queryForList(String sql, Class elementType);
List queryForList(String sql, Class elementType, @Nullable Object… args);
List queryForList(String sql, Object[] args, Class elementType);
List queryForList(String sql, Object[] args, int[] argTypes, Class elementType);
注意:
上面这个T虽然是泛型,但是只支持Integer.class String.class 这种单数据类型的,自己定义的Bean不支持。(所以用来查询单列数据)
elementType:查询结果需要转换为哪种类型?如String、Integer、Double。
案例
@Test
public void test8() {
DataSource dataSource = DataSourceUtils.getDataSource();
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
// List queryForList(String sql, Class elementType);
List list1 = jdbcTemplate.queryForList(“select name from t_user where id>131”, String.class);
System.out.println(“list1:” + list1);
// List queryForList(String sql, Class elementType, @Nullable Object… args);
List list2 = jdbcTemplate.queryForList(“select name from t_user where id>?”, String.class, 131);
System.out.println(“list2:” + list2);
// List queryForList(String sql, Object[] args, Class elementType);
List list3 = jdbcTemplate.queryForList(“select name from t_user where id>?”, new Object[]{131}, String.class);
System.out.println(“list3:” + list3);
// List queryForList(String sql, Object[] args, int[] argTypes, Class elementType);
List list4 = jdbcTemplate.queryForList(“select name from t_user where id>?”, new Object[]{131}, new int[]{java.sql.Types.INTEGER}, String.class);
System.out.println(“list4:” + list4);
}
输出
list1:[郭富城, 张学友, 黎明]
list2:[郭富城, 张学友, 黎明]
list3:[郭富城, 张学友, 黎明]
list4:[郭富城, 张学友, 黎明]
sql结果:
mysql> select name from t_user where id>131;
±----------+
| name |
±----------+
| 郭富城 |
| 张学友 |
| 黎明 |
±----------+
3 rows in set (0.00 sec)
查询单行记录,将记录转换成一个对象
Api
T queryForObject(String sql, RowMapper rowMapper);
T queryForObject(String sql, Object[] args, RowMapper rowMapper);
T queryForObject(String sql, Object[] args, int[] argTypes, RowMapper rowMapper);
T queryForObject(String sql, RowMapper rowMapper, Object… args);
上面这些方法的参数中都有一个rowMapper参数,行映射器,可以将当前行的结果映射为一个自定义的对象。
@FunctionalInterface
public interface RowMapper {
/**
* @param ResultSet 结果集
* @param 当前结果集的第几行
* @return 当前行的结果对象,将当前行的结果映射为一个自定义的对象返回
*/
@Nullable
T mapRow(ResultSet rs, int rowNum) throws SQLException;
}
JdbcTemplate内部会遍历ResultSet,然后循环调用RowMapper#mapRow,得到当前行的结果,将其丢到List中返回,如下:
List results = new ArrayList<>();
int rowNum = 0;
while (rs.next()) {
results.add(this.rowMapper.mapRow(rs, rowNum++));
}
return results;
案例
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class User {
private Integer id;
private String name;
}
@Test
public void test9() {
DataSource dataSource = DataSourceUtils.getDataSource();
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
String sql = “select id,name from t_user where id = ?”;
//查询id为34的用户信息
User user = jdbcTemplate.queryForObject(sql, new RowMapper() {
@Nullable
@Override
public User mapRow(ResultSet rs, int rowNum) throws SQLException {
User user = new User();
user.setId(rs.getInt(1));
user.setName(rs.getString(1));
return user;
}
}, 134);
System.out.println(user);
}
输出
User(id=134, name=134)
使用注意
当queryForObject中sql查询无结果的时候,会报错,必须要返回一行记录
查询单行记录,返回指定的javabean
RowMapper 有个实现了类 BeanPropertyRowMapper,可以将结果映射为javabean。
@Test
public void test10() {
DataSource dataSource = DataSourceUtils.getDataSource();
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
String sql = “select id,name from t_user where id = ?”;
//查询id为34的用户信息
RowMapper rowMapper = new BeanPropertyRowMapper<>(User.class);
User user = jdbcTemplate.queryForObject(sql, rowMapper, 134);
System.out.println(user);
}
查询多列多行,每行结果为一个Map
Api
List<Map<String, Object>> queryForList(String sql);
List<Map<String, Object>> queryForList(String sql, Object… args);
每行结果为一个Map,key为列名小写,value为列对应的值。
案例
@Test
public void test11() {
DataSource dataSource = DataSourceUtils.getDataSource();
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
String sql = “select id,name from t_user where id>?”;
List<Map<String, Object>> maps = jdbcTemplate.queryForList(sql, 130);
System.out.println(maps);
}
输出
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)
总结
面试前的“练手”还是很重要的,所以开始面试之前一定要准备好啊,不然也是耽搁面试官和自己的时间。
我自己是刷了不少面试题的,所以在面试过程中才能够做到心中有数,基本上会清楚面试过程中会问到哪些知识点,高频题又有哪些,所以刷题是面试前期准备过程中非常重要的一点。
面试题及解析总结
大厂面试场景
知识点总结
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!**
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。[外链图片转存中…(img-BmTEO54s-1713339003023)]
[外链图片转存中…(img-vJbkmxl3-1713339003023)]
[外链图片转存中…(img-ysPavFWq-1713339003024)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)
总结
面试前的“练手”还是很重要的,所以开始面试之前一定要准备好啊,不然也是耽搁面试官和自己的时间。
我自己是刷了不少面试题的,所以在面试过程中才能够做到心中有数,基本上会清楚面试过程中会问到哪些知识点,高频题又有哪些,所以刷题是面试前期准备过程中非常重要的一点。
面试题及解析总结
[外链图片转存中…(img-NbljaiVH-1713339003024)]
大厂面试场景
[外链图片转存中…(img-E0pBT1i0-1713339003025)]
知识点总结
[外链图片转存中…(img-82Oh4VeC-1713339003025)]
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!