欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

template标签是什么意思(vue的template用法)

程序员文章站 2023-11-27 15:32:04
jdbctemplate.queryforobject方法入参不支持以map的形式传递参数,需要按照sql语句中参数的顺序组织入参的list。jdbctemplate.queryforobject方法...

jdbctemplate.queryforobject方法入参不支持以map的形式传递参数,需要按照sql语句中参数的顺序组织入参的list。jdbctemplate.queryforobject方法直接不支持的in查询。只支持integer.class string.class 这种单数据类型的入参。

  • 例如:
list<long> idlist = ...;
string name = ...;
stringbuilder idlistsb = new stringbuilder();
for(long id : idlist){
  idlistsb.append(id + ",");
}
string sql = "select count(*) from user where id in (?) and name = ?";
list<object> objects = new arraylist<>();
objects.add(idlistsb.tostring().rtrim(','));
object.add (name);
jdbctemplate.queryforobject(sb.tostring(),objects,long.class);


namedparameterjdbctemplate时,其本来就支持in查询和map类型的入参。

list<long> idlist = ...;
string name = ...;
string sql = "select * from user where id in (:ids) and name = :name";
map<string, object> param  = new hashmap<>();
param.put("ids", idlist);
param.put("name", name);
namedparameterjdbctemplate.queryforobject(sb.tostring(),param,long.class);

一、jdbctemplate

spring对数据库的操作在jdbc上面做了深层次的封装,提供了一个 jdbc template 类,我们可以直接使用。只需要把datasource注册到jdbctemplate之中,其全限定命名为
org.springframework.jdbc.core.jdbctemplate。要使用jdbctemlate一般还需要事务和异常的控制。

jdbctemplate的几类方法

  • execute方法:可以用于执行任何sql语句,一般用于执行ddl语句;
  • update方法及batchupdate方法:update方法用于执行新增、修改、删除等语句;batchupdate方法用于执行批处理相关语句;
  • query方法及queryforxxx方法:用于执行查询相关语句;
  • call方法:用于执行存储过程、函数相关语句。

jdbctemplate的常用方法

//update操作单个增删改
int update(string sql,object[] args)
int update(string sql,objcet... args)

//batchupdate批量增删改
int[] batchupdate(string[] sql)
int[] batchupdate(string sql,list<object[]>)

//单个简单查询
t queryforobjcet(string sql,class<t> type)
t queryforobjcet(string sql,object[] args,class<t> type)
t queryforobjcet(string sql,class<t> type,object... arg)

//获取多个
list<t> queryforlist(string sql,class<t> type)
list<t> queryforlist(string sql,object[] args,class<t> type)
list<t> queryforlist(string sql,class<t> type,object... arg)

查询复杂对象(封装为map)

//获取单个
map queryformap(string sql)
map queryformap(string sql,objcet[] args)
map queryformap(string sql,object... arg)

//获取多个
list<map<string,object>> queryforlist(string sql)
list<map<string,object>> queryforlist(string sql,obgject[] args)
list<map<string,object>> queryforlist(string sql,obgject... arg)

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

spring jdbctemplate是通过实现
org.springframework.jdbc.core.rowmapper这个接口来完成对entity对象映射。

//获取单个
t queryforobject(string sql,rowmapper<t> mapper)
t queryforobject(string sql,object[] args,rowmapper<t> mapper)
t queryforobject(string sql,rowmapper<t> mapper,object... arg)

//获取多个
list<t> query(string sql,rowmapper<t> mapper)
list<t> query(string sql,object[] args,rowmapper<t> mapper)
list<t> query(string sql,rowmapper<t> mapper,object... arg)

spring jdbc中目前有两个主要的rowmapper实现,使用它们应该能解决大部分的场景了:singlecolumnrowmapper和beanpropertyrowmapper。
singlecolumnrowmapper:返回单列数据
beanpropertyrowmapper:当查询数据库返回的是多列数据,且需要将这些多列数据映射到某个具体的实体类上。

//示例:
string sql = "select name from test_student where id = ?";
jdbctemplate.queryforobject(sql, new object[]{id}, new singlecolumnrowmapper<>(string.class));

string sql = "select name, gender from test_student where name = ?";
jdbctemplate.queryforobject(sql, new object[]{name},new beanpropertyrowmapper<>(student.class));
  • 定义自己的rowmapper

如果你sql查询出来的数据列名就是和实体类的属性名不一样,或者想按照自己的规则来装配实体类,那么就可以定义并使用自己的row mapper。

//自定义
public class studentrowmapper implements rowmapper<student> {

    @override
    public student maprow(resultset rs, int i) throws sqlexception {
        student student = new student();
        student.setname(rs.getstring("name"));
        student.setgender(rs.getstring("gender"));
        student.setemail(rs.getstring("email"));
        return student;
    }
}

//使用
string sql = "select name, gender, email from test_student where name = ?";
jdbctemplate.queryforobject(sql, new object[]{name}, new studentrowmapper());

批量修改

public int[] batchinsert(list<map<string, object>> datalist) {
    string sql = "insert into test_info(name, create_time, age) values(?, now(), ?)";
    list<object[]> paramarray = new arraylist<>();
    for (map<string, object> datainfo : datalist) {
        object[] obj = new object[2];
        obj[0] = datainfo.get("name");
        obj[1] = datainfo.get("age");
        paramarray.add(obj);
    }
    if (collectionutils.isnotempty(paramarray)) {
        return jdbctemplate.batchupdate(sql, paramarray);
    }
    return new int[0];
}

jdbctemplate支持的回调类

预编译语句及存储过程创建回调:用于根据jdbctemplate提供的连接创建相应的语句

preparedstatementcreator:通过回调获取jdbctemplate提供的connection,由用户使用该conncetion创建相关的preparedstatement;
callablestatementcreator:通过回调获取jdbctemplate提供的connection,由用户使用该conncetion创建相关的callablestatement;

import java.sql.connection;
import java.sql.resultset;
import java.sql.sqlexception;
import org.junit.test;
import org.junit.runner.runwith;
import org.springframework.beans.factory.annotation.autowired;
import org.springframework.dao.dataaccessexception;
import org.springframework.jdbc.core.jdbctemplate;
import org.springframework.jdbc.core.preparedstatementcallback;
import org.springframework.jdbc.core.preparedstatementcreator;
import org.springframework.test.context.contextconfiguration;
import org.springframework.test.context.junit4.springjunit4classrunner;

@runwith(springjunit4classrunner.class) // 关联spring与junit
@contextconfiguration(locations = { "classpath:applicationcontext.xml" }) // 加载配置spring配置文件
public class apptest {

    @autowired
    private jdbctemplate jdbctemplate;

    @test
    public void testppreparedstatement1() {
        int count = jdbctemplate.execute(new preparedstatementcreator() {
            public java.sql.preparedstatement createpreparedstatement(connection conn) throws sqlexception {
                return conn.preparestatement("select count(*) from user");
            }
        }, new preparedstatementcallback<integer>() {
            public integer doinpreparedstatement(java.sql.preparedstatement pstmt)
                    throws sqlexception, dataaccessexception {
                pstmt.execute();
                resultset rs = pstmt.getresultset();
                rs.next();
                return rs.getint(1);
            }
        });
        system.out.println(count);
    }
}

首先使用preparedstatementcreator创建一个预编译语句,其次由jdbctemplate通过preparedstatementcallback回调传回,由用户决定如何执行该preparedstatement。此处我们使用的是execute方法。

预编译语句设值回调:用于给预编译语句相应参数设值

preparedstatementsetter:通过回调获取jdbctemplate提供的preparedstatement,由用户来对相应的预编译语句相应参数设值;

batchpreparedstatementsetter:;类似于preparedstatementsetter,但用于批处理,需要指定批处理大小;

import java.sql.preparedstatement;
import java.sql.sqlexception;
import org.junit.assert;
import org.junit.test;
import org.junit.runner.runwith;
import org.springframework.beans.factory.annotation.autowired;
import org.springframework.jdbc.core.jdbctemplate;
import org.springframework.jdbc.core.preparedstatementsetter;
import org.springframework.test.context.contextconfiguration;
import org.springframework.test.context.junit4.springjunit4classrunner;

@runwith(springjunit4classrunner.class) // 关联spring与junit
@contextconfiguration(locations = { "classpath:applicationcontext.xml" }) // 加载配置spring配置文件
public class apptest {

    @autowired
    private jdbctemplate jdbctemplate;

    @test
    public void testpreparedstatement2() {
        string insertsql = "insert into user(user_name) values (?)";
        int count = jdbctemplate.update(insertsql, new preparedstatementsetter() {
            public void setvalues(preparedstatement pstmt) throws sqlexception {
                pstmt.setobject(1, "mmnn");
            }
        });
        assert.assertequals(1, count);
        string deletesql = "delete from user where user_name=?";
        count = jdbctemplate.update(deletesql, new object[] { "mmnn" });
        assert.assertequals(1, count);
    }
}

通过jdbctemplate的int update(string sql, preparedstatementsetter pss)执行预编译sql,其中sql参数为“insert into user(user_name) values (?) ”,该sql有一个占位符需要在执行前设值,preparedstatementsetter实现就是为了设值,使用setvalues(preparedstatement pstmt)回调方法设值相应的占位符位置的值。jdbctemplate也提供一种更简单的方式“update(string sql, object… args)”来实现设值,所以只要当使用该种方式不满足需求时才应使用preparedstatementsetter。

自定义功能回调:提供给用户一个扩展点,用户可以在指定类型的扩展点执行任何数量需要的操作

connectioncallback:通过回调获取jdbctemplate提供的connection,用户可在该connection执行任何数量的操作;
statementcallback:通过回调获取jdbctemplate提供的statement,用户可以在该statement执行任何数量的操作;
preparedstatementcallback:通过回调获取jdbctemplate提供的preparedstatement,用户可以在该preparedstatement执行任何数量的操作;
callablestatementcallback:通过回调获取jdbctemplate提供的callablestatement,用户可以在该callablestatement执行任何数量的操作;

结果集处理回调:通过回调处理resultset或将resultset转换为需要的形式

rowmapper:用于将结果集每行数据转换为需要的类型,用户需实现方法maprow(resultset rs, int rownum)来完成将每行数据转换为相应的类型。
rowcallbackhandler:用于处理resultset的每一行结果,用户需实现方法processrow(resultset rs)来完成处理,在该回调方法中无需执行rs.next(),该操作由jdbctemplate来执行,用户只需按行获取数据然后处理即可。
resultsetextractor:用于结果集数据提取,用户需实现方法extractdata(resultset rs)来处理结果集,用户必须处理整个结果集;

@test
public void testresultset1() {
    jdbctemplate.update("insert into user(user_name) values('name7')");
    string listsql = "select * from user where user_name=?";
    list result = jdbctemplate.query(listsql,new object[]{"name7"}, new rowmapper<map>() {
        public map maprow(resultset rs, int rownum) throws sqlexception {
            map row = new hashmap();
            row.put(rs.getint("user_id"), rs.getstring("user_name"));
            return row;
        }
    });
    assert.assertequals(1, result.size());//查询结果数量为1才向下执行
    jdbctemplate.update("delete from user where user_name='name7'");
}

rowmapper接口提供maprow(resultset rs, int rownum)方法将结果集的每一行转换为一个map,当然可以转换为其他类。

@test
public void testresultset2() {
    jdbctemplate.update("insert into user(user_name) values('name5')");
    string listsql = "select * from user";
    final list result = new arraylist();
    jdbctemplate.query(listsql, new rowcallbackhandler() {
        public void processrow(resultset rs) throws sqlexception {
            map row = new hashmap();
            row.put(rs.getint("user_id"), rs.getstring("user_name"));
            result.add(row);
        }
    });
    assert.assertequals(1, result.size());
    jdbctemplate.update("delete from user where user_name='name5'");
}

rowcallbackhandler接口也提供方法processrow(resultset rs),能将结果集的行转换为需要的形式。

@test
public void testresultset3() {
    jdbctemplate.update("insert into test(name) values('name5')");
    string listsql = "select * from test";
    list result = jdbctemplate.query(listsql, new resultsetextractor<list>() {
        public list extractdata(resultset rs) throws sqlexception, dataaccessexception {
            list result = new arraylist();
            while (rs.next()) {
                map row = new hashmap();
                row.put(rs.getint("id"), rs.getstring("name"));
                result.add(row);
            }
            return result;
        }
    });
    assert.assertequals(0, result.size());
    jdbctemplate.update("delete from test where name='name5'");
}

resultsetextractor使用回调方法extractdata(resultset rs)提供给用户整个结果集,让用户决定如何处理该结果集。

当然jdbctemplate提供更简单的queryforxxx方法,来简化开发:

//1.查询一行数据并返回int型结果  
jdbctemplate.queryforint("select count(*) from test");  
//2. 查询一行数据并将该行数据转换为map返回  
jdbctemplate.queryformap("select * from test where name='name5'");  
//3.查询一行任何类型的数据,最后一个参数指定返回结果类型  
jdbctemplate.queryforobject("select count(*) from test", integer.class);  
//4.查询一批数据,默认将每行数据转换为map       
jdbctemplate.queryforlist("select * from test");  
//5.只查询一列数据列表,列类型是string类型,列名字是name  
jdbctemplate.queryforlist("  
select name from test where name=?", new object[]{"name5"}, string.class);  
//6.查询一批数据,返回为sqlrowset,类似于resultset,但不再绑定到连接上  
sqlrowset rs = jdbctemplate.queryforrowset("select * from test");  

返回新增的自增id

@test
public void test(){

    string sql = "insert into sp_user(name) values (?)";
    keyholder keyholder = new generatedkeyholder();
    jdbctemplate.update(new preparedstatementcreator() {

        @override
        public preparedstatement createpreparedstatement(connection connection) throws sqlexception {
            // 设置返回的主键字段名
            preparedstatement ps = connection.preparestatement(sql, statement.return_generated_keys);
            ps.setstring(1, "harvey");
            return ps;
        }
    }, keyholder);
    // 获取到插入数据生成的id
    int num = keyholder.getkey().intvalue();
    system.out.println(num);
}

二、namedparameterjdbctemplate

什么是具名参数

在经典的 jdbc 用法中, sql 参数是用占位符 ? 表示,并且受到位置的限制。定位参数的问题在于, 一旦参数的顺序发生变化, 就必须改变参数绑定。
在 spring jdbc 框架中, 绑定 sql 参数的另一种选择是使用具名参数(named parameter)。

具名参数:sql 按名称(以冒号开头)而不是按位置进行指定,具名参数更易于维护,,也提升了可读性。具名参数由框架类在运行时用占位符取代,
具名参数只在
namedparameterjdbctemplate 中得到支持。


namedparameterjdbctemplate类拓展了jdbctemplate类,可以使用全部jdbctemplate方法。


namedparameterjdbctemplate主要提供以下三类方法:execute方法、query及queryforxxx方法、update及batchupdate方法。


namedparameterjdbctemplate可以使用datasource或jdbctemplate 对象作为构造器参数初始化。

常用api传入参数类型介绍


namedparameterjdbctemplate类为命名参数设值有两种方式:java.util.map 、rowmapper 和 sqlparametersource。

map<string,?> parammap

就是一个hash表,好处是可以根据参数名传参,parammap.put(“sqlparamname”,value)。

rowmapper rowmapper

这个接口为了实现sql查询结果和对象间的转换,可以自己实现,也可以使用系统实现,主要实现类有:

  • singlecolumnrowmapper ,sql结果为一个单列的数据,如list<string> , list<integer>,string,integer等
  • beanpropertyrowmapper, sql结果匹配到对象 list< xxxvo> , xxxvo

sqlparametersource

其作用和map一样,就是为sql中的条件参数赋值,默认实现有 :

  • mapsqlparametersource实现非常简单,只是封装了java.util.map。
  • beanpropertysqlparametersource封装了一个javabean对象,通过javabean对象属性来决定命名参数的值。
  • emptysqlparametersource 一个空的sqlparametersource ,常用来占位使用。
//beanpropertysqlparametersource传参方式
sqlparametersource sps = new beanpropertysqlparametersource(javabean);

//mapsqlparametersource传参方式
sqlparametersource sps = new mapsqlparametersource();
//保证参数名和key相同
sps.addvalue("key",value);

api介绍

查询

返回单行单列数据

public < t > t queryforobject(string sql, map<string, ?> parammap, class<t> requiredtype)
public < t > t queryforobject(string sql, sqlparametersource paramsource, class<t> requiredtype)

integer count = template.queryforobject("select count(*) from student", new hashmap<>(), integer.class);
string name = template.queryforobject( "select name from student where home_address  limit 1 ", emptysqlparametersource.instance, string.class); 

返回 (多行)单列 数据

public < t> list< t> queryforlist(string sql, map<string, ?> parammap, class< t > elementtype)
public < t> list< t> queryforlist(string sql, sqlparametersource paramsource, class< t> elementtype)

list< string> namelist = template.queryforlist("select name from student", new hashmap<>(), string.class);

返回单行数据

public < t> t queryforobject(string sql, map< string, ?> parammap, rowmapper< t>rowmapper)
public < t> t queryforobject(string sql, sqlparametersource paramsource, rowmapper< t> rowmapper)

student  stu = template.queryforobject(
                "select * from student limit 1", new hashmap<>(), new beanpropertyrowmapper<student>(student.class));
//beanpropertyrowmapper会把下划线转化为驼峰属性
//结果对象可比实际返回字段多或者少

注意:这两个api也可以使用singlecolumnrowmapper返回单行单列数据

string name = template.queryforobject(
                "select name from student limit 1", emptysqlparametersource.instance, new singlecolumnrowmapper<>(string.class));

返回map形式的单行数据

public map< string, object> queryformap(string sql, map< string, ?> parammap)
public map< string, object> queryformap(string sql, sqlparametersource paramsource)

map< string, object> studentmap = template.queryformap("select * from student limit 1", new hashmap<>());

注意:queryformap这个方法要求结果必须是有数据的,否则会报错。

返回多行数据

public < t> list< t> query(string sql, map< string, ?> parammap, rowmapper< t> rowmapper)
public < t> list< t> query(string sql, sqlparametersource paramsource, rowmapper< t> rowmapper)
public < t> list< t> query(string sql, rowmapper< t> rowmapper)

list< student> studentlist = template.query(
                "select * from student",  
                new beanpropertyrowmapper<>(student.class)
);     

同理,也可以使用singlecolumnrowmapper返回单行列表list< string>,list< integer>等。

返回多行数据(map)

public list< map< string, object>> queryforlist(string sql, map< string, ?> parammap)
public list< map< string, object>> queryforlist(string sql, sqlparametersource paramsource)

list<map<string, object>> maplist = template.queryforlist(
                "select * from student", new hashmap<>());

插入/修改/删除数据,使用updatexxx方法

使用map作为参数

int update(string sql, map<string, ?> parammap)

map<string, object> parammap = new hashmap<>();
parammap.put("id", uuid.randomuuid().tostring());
parammap.put("name", "小明");
parammap.put("age", 33);
parammap.put("homeaddress", "乐山");
parammap.put("birthday", new date());
template.update( 
     "insert into student(id,name,age,home_address,birthday) values (:id,:name,:age,:homeaddress,:birthday)",
     parammap
);

使用sqlparametersource作为参数

int update(string sql, sqlparametersource paramsource)

//使用 beanpropertysqlparametersource作为参数
studentdto dto=new studentdto();//这个dto为传入数据
dto.setid(uuid.randomuuid().tostring());
dto.setname("小红");
dto.sethomeaddress("成都");
//------------------------------
template.update("insert into student(id,name,home_address) values (:id,:name,:homeaddress)",
                new beanpropertysqlparametersource(dto));


//使用mapsqlparametersource 作为参数
mapsqlparametersource mapsqlparametersource = new mapsqlparametersource()
        .addvalue("id", uuid.randomuuid().tostring())
        .addvalue("name", "小王")
        .addvalue("homeaddress", "美国");
template.update("insert into student(id,name,home_address) values    
                   (:id,:name,:homeaddress)",mapsqlparametersource);

开发中尽量使用
namedparameterjdbctemplate代替jdbctemplate,如果想使用jdbctemplate,也可以通过namedparameterjdbctemplate#getjdbcoperations()获取

不建议使用查询结构为map的api