您的位置:首页 > 编程语言 > Java开发

Spring里配置的JDBC-Template最详细讲解

2020-05-05 11:10 99 查看

为什么要用JDBC-Template

可以简化持久代码,在持久层有很大用处,什么叫持久层,就是实现增删改除等功能的一个抽象层面,是和数据库直接打交道的层。为什么说可以简化持久代码呢,大家都知道JAVA传统JDBC的流程

首先创建加载驱动,通过加载驱动取得与数据库的连接,通过连接创建语句来实现增删改除。通过下面对比可以看出Template的具体简化作用

比如来一个查询结果

//传统 JDBC API查询
Statement stmt=conn.createStatement();
ResultSet rs =stmt.executeQuery("select * from user1");
while(rs.next())                             //获得每行数据
{
int id=rs.getint("id");
String name=rs.getString("name");
}

//JDBC Template查询
List<Map<String,Object>> list=jt.queryForObjec("select * from user1 where sex=?","男")

可见Template实现了简化代码操作。

JDBC Template将JDBC API全部封装起来,不像传统的,你要是实现增删改那么只需要用Statement,或者PreparedStatement,查询使用ResultSet方法来接收查询的结果集。JDBCTemplate只需要要定义一个对象,直接就可以调用JDBC里面的增删该处查询的功能。所以说JDBCTemplate将JDBC API进行了封装,不像上面那么麻烦。

如何使用Template

传统JDBC的使用就在这里就不多说了,如何使用Template(模板)?因为它是建立在Spring上的对数据库操作。所以需要导入相应的jar包,
1.连接Mysql的包
2.Spring 四兄弟包
3.Spring tx和jdbc包

<!--配置数据源-->
<bean id="datesource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/denglu?serverTimezone=UTC"/>
<property name="username" value="root"/>
<property name="password" value="705619"/>
</bean>

<!--配置Template-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dateSource" ref="datasource"/>
</bean>

使用DriverManagerDataSource数据源加载器类创建连接,下面输入参数即可,加载器,连接名称,用户名,密码。然后配置Template,获得数据源配置,那么就可以通过Template对象来实现增删改除的功能了。

JDBC Template基本语法

execute

execute语法:

jdbcTemplate.execute(String sql);    //里面执行 sql 语句

execute实现创建或者删除表

public void test()
{
ApplicationContext context=new ClassPathXmlApplicationContext("Application.xml");
JdbcTemplate jdbcTemplate=(JdbcTemplate) context.getBean("jdbcTemplate");    //从Spring配置中实例化
jdbcTemplate.execute("create table user1(id int,name varchar(20))");     //实现execute语句创建表
}

或者用Resource属性注入也可以

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:Application.xml")   //使用确定的配置文件,为什么这么用前面文章有介绍
public class Test {
@Resource(name = "jdbcTemplate")
private JdbcTemplate jdbcTemplate;   //属性注入,相当于创建工厂获得bean

@org.junit.Test
public void test()
{
jdbcTemplate.execute("create table user1(id int,name varchar(20))");  //前面属性注入了实例化,所以可以直接使用
}
}

以上就是execute语句,很简单,通过配置文件已经配置好的JDBCTemplate来在类中实例化JDBCTemplate对象,然后通过对象来调用相应的方法

update 和 batchupdate

update负责往表里增删改的功能,那么它和 batchupdate 有什么区别,当批量进行多条 sql 操作时候使用batchupdate,当一次性往进加多条数据的时候使用batchupdate。

update语法:
int update(String sql,Object[] args)
int update(String sql,Object... args)

为什么返回 int 类型,因为我们进行增删改的时候总会返回一个值,对几行进行了修改

所以使用update的时候就会返回一个值,第一个参数为执行的sql语句,第二个参数为要输入前面参数问号的值,相当于JDBC API 里面的 PreparedStatement 预处理语句。

例如向表中插入数据

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:Application.xml")
public class Test {
@Resource(name = "jdbcTemplate")
private JdbcTemplate jdbcTemplate;
@org.junit.Test
public void test()
{
jdbcTemplate.update("insert into user1(id,name) value(?,?)","7","xiaoming");  //此句为sql语句
}
}

第一个参数中为sql执行语句,?代表的是值的参数,由后面次序一 一对应进去,就是前面有几个?参数,后面的值就有几个。
上面的是update语法中的第二个,也可以用第一个,用Object进行封装一下

jdbcTemplate.update("insert into user1(id,name) value(?,?)",new Object[]{7,"xiaog"});

用Object比较容易理解,一 一对应。

batchupdate语法:
int batchupdate(String[] sql);
int batchupdate(String sql,List<Object[]> arge);

第一个用法是当需要执行多条sql语句的时候

String[] sql={"insert into user1(id,name) value(5,'xiaol')
insert into user1(id,name) value(6,'xiaozhang')
update user1 set name='xaioming' where id=5;
"}

例如上面执行多条语句的时候就得使用 batchupdate,先定义一个String数组,再将数组放入batchupdate的参数里面

jdbcTemplate.batchupdate(sql);           //jdbcTemplate定义就不写了,和上面一样

第一个用法比较简单,容易理解。第二个用法,可见参数不为一个数组了,说明是同一个sql执行操作,执行多组数据的时候用。比如插入多组数据,将多组数据封装为Object数组,然后放到List集合里面即可。

List<Object[]> list=new ArrayList<Object[]>();
//创建一个list集合,里面放Object数组,因为每次输入的数据都是一组一组的,用Object数组封装,然后又是一次性输入多组,所以用List集合
list.add(new Object[]{1,"xiaoming"});
list.add(new Object[]{2,"xiaoming"});
list.add(new Object[]{3,"xiaoming"});

jdbcTemplate.batchupdate("insert into user1(id,name) vallue(?,?)",list);

将list传到第二个参数就将list里面的数据传入数据库了。

上面是增加,那么删除和改就简单了
删除:

jdbcTemplate.update("delete from user1 where id=1"); //直接写,或者写上不定参

修改

jdbcTemplate.update("update user1 set name='xiaoming' where id=1");   //直接写,也可以写上不定参

query xxxxx

这是查询语句,为什么后面用xxxxx代替,因为JDBCTemplate 的查询语句比较灵活,什么意思,就是你查询数据,然后根据你查询出来的数据来将query语句进行了分别。

1.获取单个数据(queryForObject)

这里的单个数据是指例如每个用户的具体 id 或者名称,并且只有一个

queryForObject语法:
T queryForObject(String sql,Class<T> type);
T queryForObject(String sql,Object[] arge,Class<T> type);
T queryForObject(String sql,Class<T> type,Object... arge);

这里用了泛型,就是用T代表数据类型,Class type 表示返回T的类Class,那么这三个有什么区别,第一个没有不定参,第二三个有不定参(就是sql语句中有 ?)那么第二三个Object的位置不同,第二个意思是将参数封装到了Object数组里面了,第三个就是分散开了,就是上面说的一 一对应,问号的位置对应后面参数的位置。

举个例子:查询名字为xiaoming的 ID

int id=jdbcTemplate.queryForObject("select id from user1 where name='xiaoming'",int.class);       //这是第一种形式 第二个参数就为返回参数类型的class

int id=jdbcTemplate.queryForObject("select id from user1 where name=?",new Object[]{"xiaoming"},int.class); //第二种

int id=jdbcTemplate.queryForObject("select id from user1 where name=?",int.class,"xiaoming");  //第三种

仔细看便可以区分出来了,前面sql语句有几个问号,后面就跟几个参数,第二种将参数用Object数组封装起来,就放到第二个位置,第三种将参数分散了,放到最后,前面有几个不定参(就是问号),后面就跟几个参数。
如果你将参数不使用Object封装放在中间,一堆两三个,然后返回的类型放在最后,函数无法识别哪个是返回的Class 像下面这样会导致识别混乱,所以只能用Object封装

//识别错误
int id=jdbcTemplate.queryForObject("select ? from user1 where name=?","id","xiaoming",int.class);
//实现封装
int id=jdbcTemplate.queryForObject("select ? from user1 where name=?",new Object[]{"id","xiaoming"},int.class);

上面这两种表达方式必须记住,虽然有点麻烦,但是理解简单,使用高逼格。

2.获取多个相同类型的数据(queryForList)

这个是上面的加强版,例如获得多个用户的 ID,我们可以想到,获得一堆类型相同的数据,肯定定义一个集合,放到集合里面。

queryForList语法:
List<T> queryForList(String sql,Class<T> type)
List<T> queryForList(String sql,Object[] arge,Class<T> type)
List<T> queryForList(String sql,Class<T> type,Object... arge)

参数和上面一样,可以看上面理解就可以了,只是返回的不同,返回的是一个 List 集合,例如从用户性别获得用户名称

//第二种表示方式,不定参在最后,没有使用 Object封装
List<String> name=jdbcTemplate.queryForList("select name from user1 where sex=?",String.class,"女");

//第三种表达方式,不定参数在中间,使用 Object封装
List<String> name=jdbcTemplate.queryForList("select name from user1 where sex=?",new Object[]{"女"},String.class);

那么输出name就可以看到选出来的数据了

3.获取一组数据,一行(queryForMap)

这个更牛逼了,就是和普通JDBC查询一样,查询复杂对象,获得一个结果

queryForMap语法:
Map queryForMap(String sql);
Map queryForMap(String sql,Object[] args);
Map queryForMap(String sql,Object... args);

这里为什么要用map集合呢,因为这里返回的是一行的数据,有各种数据类型,你要明确返回的是字段名称和其相对应的数据一 一对应,所以List不适合,所以就要用Map集合,Map的属性是键-值对集合,所以用map封装后,可以明确分清返回的数据关系。因为返回的都为Map类型,所以参数里不用写返回Class,Object的原理和上面的一样,只不过这里没有位置的区分,写法不同而已了。

这里假设返回名称为 xiaoming 的所有信息,用Map封装

Map<String,Object> map=jdbcTemplate.queryForMap("select * from user1 where name=?" ,"xiaoming");

因为返回的是Map集合,所以创建一个Map集合,键设为String类型,因为数据库字段名称都为String,值设置为Object,因为返回的数值可能有int,varchar数据类型,所以只能用Object封装了。输出 map 得出结果如下

{id=1, name=xiaoming, sex=男}   //这就是map的键值对
4.获取多组数据,对象(queryForList)

但上面这只是返回一个对象,但你要是要看数据库种多个对象,显然上面Map不能接受多个(多组)对象的数据,所以这里想到了List集合,在List集合里面放Map集合就可以了 :List<Map<String,Object>> ,先将每个对象的所有数据封装到Map集合里面,再将多个封装后的Map集合(里面放的每个对象的数据)都放到List集合里。

所以这里返回的是一个List集合,所以还是用queryForList,这里和上面的那个区别就是这里返回的是一个Map封装后的List集合。

queryForList语法:
List <Map<String,Object>> queryForList(String sql);
List <Map<String,Object>> queryForList(String sql Object[] args);
List <Map<String,Object>> queryForList(String sql Object... aegs);

例如返回性别为男的全部数据

//第二种用法
List<Map<String,Object>> list=jdbcTemplate.queryForList("select * from user1 where sex=?", "男");    //返回一个List集合
//第三种用法
List<Map<String,Object>> list=jdbcTemplate.queryForList("select * from user1 where sex=?", new Object[]{"男"});

得到结果如下

[{id=1, name=xiaoming, sex=男}, {id=2, name=xiaohei, sex=男}]

可得 List 集合,里面又是一个一个的Map集合

Tip(一个没用的提示):List集合得出的结果用 [ ]来包含,Map集合得出的结果用 { } 包含

5.查询复杂对象,封装类的对象

都知道Java再进行对用户区块化管理的时候,先定义一个用户类(User)将数据全部放到里面进行管理,那么在查询时候返回对象类型数据,如何使用查询语句?
看下面文章,这里篇幅太长

JDBC Template查询复杂对象(封装为实体对象)

总结

Template 是一种简单灵活的持久代码,虽然内容繁琐,但是执行起来比较简单,一句话就可以返回出来结果。在持久层实现比较容易,但是缺点是sql语句和java语句混淆,不去了解sql语句实现比较麻烦。一切事物都有利有弊。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: