jdbctemplate.queryforobject方法入参不支持以map的形式传递参数,需要按照sql语句中参数的顺序组织入参的list。jdbctemplate.queryforobject方法直接不支持的in查询。只支持integer.class string.class 这种单数据类型的入参。
例如:list<long> my english studyidlist = ...;string name = ...;stringbuilder idlistsb = new stringbuilder();for(long id : idlist){ idlistsb.append(id + ",");}string sql = "lect count(*) from ur 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 = "lect * from ur 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);
spring对数据库的操作在jdbc上面做了深层次的封装,提供了一个 jdbc template 类,我们可以直接使用。只需要把datasource注册到jdbctemplate之中,其全限定命名为
org.springframework.jdbc.core.jdbctemplate。要使用jdbctemlate一般还需要事务和异常的控制。
//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 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 = "lect name from test_student where id = ?";jdbctemplate.queryforobject(sql, new object[]{id}, new singlecolumnrowmapper<>(string.class));string sql = "lect 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(resultt rs, int i) throws sqlexception { student student = new student(); student.tname(rs.getstring("name")); student.tgender(rs.getstring("gender")); student.temail(rs.getstring("email")); return student; }}//使用string sql = "lect name, gender, email from test_student where name = ?";jdbctemplate.queryforobject(sql, new object[]{name}, new studentrowmapper());
public int[] batchinrt(list<map<string, object>> datalist) { string sql = "inrt 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];}
preparedstatementcreator:通过回调获取jdbctemplate提供的connection,由用户使用该conncetion创建相关的preparedstatement;
callablestatementcreator:通过回调获取jdbctemplate提供的connection,由用户使用该conncetion创建相关的callablestatement;
import java.sql.connection;import java.sql.resultt;import java.sql.sqlexception;import org.junit.test;import org.junit.runner.runwith;import org.springframework.beans.factory.annotation.autowired;import org.springframework.dao.dataaccesxception;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("lect count(*) from ur"); } }, new preparedstatementcallback<integer>() { public integer doinpreparedstatement(java.sql.preparedstatement pstmt) throws sqlexception, dataaccesxception { pstmt.execute(); resultt rs = pstmt.getresultt(); rs.next(); return rs.getint(1); } }); system.out.println(count); }}
首先使用preparedstatementcreator创建一个预编译语句,其次由jdbctemplate通过preparedstatementcallback回调传回,由用户决定如何执行该preparedstatement。此处我们使用的是execute方法。
preparedstatementtter:通过回调获取jdbctemplate提供的preparedstatement,由用户来对相应的预编译语句相应参数设值;
batchpreparedstatementtter:;类似于preparedstatementtter,但用于批处理,需要指定批处理大小;
import java.sql.preparedstatement;import java.sql.sqlexception;import org.junit.asrt;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.preparedstatementtter;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 inrtsql = "inrt into ur(ur_name) values (?)"; int count = jdbctemplate.update(inrtsql, new preparedstatementtter() { public void tvalues(preparedstatement pstmt) throws sqlexception { pstmt.tobject(1, "mmnn"); } }); asrt.asrtequals(1, count); string deletesql = "delete from ur where ur_name=?"; count = jdbctemplate.update(deletesql, new object[] { "mmnn" }); asrt.asrtequals(1, count); }}
通过jdbctemplate的int update(string sql, preparedstatementtter pss)执行预编译sql,其中sql参数为“inrt into ur(ur_name) values (?) ”,该sql有一个占位符需要在执行前设值,preparedstatementtter实现就是为了设值,使用tvalues(preparedstatement pstmt)回调方法设值相应的占位符位置的值。jdbctemplate也提供一种更简单的方式“update(string sql, object… args)”来实现设值,所以只要当使用该种方式不满足需求时才应使用preparedstatementtter。
connectioncallback:通过回调获取jdbctemplate提供的connection,用户可在该connection执行任何数量的操作;
statementcallback:通过回调获取jdbctemplate提供的statement,用户可以在该statement执行任何数量的操作;
preparedstatementcallback:通过回调获取jdbctemplate提供的preparedstatement,用户可以在该preparedstatement执行任何数量的操作;
callablestatementcallback:通过回调获取jdbctemplate提供的callablestatement,用户可以在该callablestatement执行任何数量的操作;
rowmapper:用于将结果集每行数据转换为需要的类型,用户需实现方法maprow(resultt rs, int rownum)来完成将每行数据转换为相应的类型。
rowcallbackhandler:用于处理resultt的每一行结果,用户需实现方法processrow(resultt rs)来完成处理,在该回调方法中无需执行rs.next(),该操作由jdbctemplate来执行,用户只需按行获取数据然后处理即可。
resulttextractor:用于结果集数据提取,用户需实现方法extractdata(resultt rs)来处理结果集,用户必须处理整个结果集;
@testpublic void testresultt1() { jdbctemplate.update("inrt into ur(ur_name) va小飞扬lues('name7')"); string listsql = "lect * from ur where ur_name=?"; list result = jdbctemplate.query(listsql,new object[]{"name7"}, new rowmapper<map>() { public map maprow(resultt rs, int rownum) throws sqlexception { map row = new hashmap(); row.put(rs.getint("ur_id"), rs.getstring("ur_name")); return row; } }); asrt.asrtequals(1, result.size());//查询结果数量为1才向下执行 jdbctemplate.update("delete from ur where ur_name='name7'");}
rowmapper接口提供maprow(resultt rs, int rownum)方法将结果集的每一行转换为一个map,当然可以转换为其他类。
@testpublic void testresultt2() { jdbctemplate.update("inrt into ur(ur_name) values('name5')"); string listsql = "lect * from ur"; final list result = new arraylist(); jdbctemplate.query(listsql, new rowcallbackhandler() { public void processrow(resultt rs) throws sqlexception { map row = new hashmap(); row.put(rs.getint("ur_id"), rs.getstring("ur_name")); result.add(row); } }); asrt.asrtequals(1, result.size()); jdbctemplate.update("delete from ur where ur_name='name5'");}
rowcallbackhandler接口也提供方法processrow(resultt rs),能将结果集的行转换为需要的形式。
@testpublic void testresultt3() { jdbctemplate.update("inrt into test(name) values('name5')"); string listsql = "lect * from test"; list result = jdbctemplate.query(listsql, new resulttextractor<list>() { public list extractdata(resultt rs) throws sqlexception, dataaccesxception { list result = new arraylist(); while (rs.next()) { map row = new hashmap(); row.put(rs.getint("id"), rs.getstring("name")); result.add(row); } return result; } }); asrt.asrtequals(0, result.size()); jdbctemplate.update("delete from test where name='name5'");}
resulttextractor使用回调方法extractdata(resultt rs)提供给用户整个结果集,让用户决定如何处理该结果集。
当然jdbctemplate提供更简单的queryforxxx方法,来简化开发:
//1.查询一行数据并返回int型结果 jdbctemplate.queryforint("lect count(*) from test"); //2. 查询一行数据并将该行数据转换为map返回 jdbctemplate.queryformap("lect * from test where name='name5'"); //3.查询一行任何类型的数据,最后一个参数指定返回结果类型 jdbctemplate.queryforobject("lect count(*) from test", integer.class); //4.查询一批数据,默认将每行数据转换为map jdbctemplate.queryforlist("lect * from test"); //5.只查询一列数据列表,列类型是string类型,列名字是name jdbctemplate.queryforlist(" lect name from test where name=?", new object[]{"name5"}, string.class); //6.查询一批数据,返回为sqlrowt,类似于resultt,但不再绑定到连接上 sqlrowt rs = jdbctemplate.queryforrowt("lect * from test");
@testpublic void test(){ string sql = "inrt into sp_ur(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.tstring(1, "harvey"); return ps; } }, keyholder); // 获取到插入数据生成的id int num = keyholder.getkey().intvalue(); system.out.println(num);}
在经典的 jdbc 用法中, sql 参数是用占位符 ? 表示,并且受到位置的限制。定位参数的问题在于, 一旦参数的顺序发生变化, 就必须改变参数绑定。
在 spring jdbc 框架中, 绑定 sql 参数的另一种选择是使用具名参数(named parameter)。
具名参数:sql 按名称(以冒号开头)而不是按位置进行指定,具名参数更易于维护,,也提升了可读性。具名参数由框架类在运行时用占位符取代,
具名参数只在
namedparameterjdbctemplate 中得到支持。
namedparameterjdbctemplate类拓展了jdbctemplate类,可以使用全部jdbctemplate方法。
namedparameterjdbctemplate主要提供以下三类方法:execute方法、query及queryforxxx方法、update及batchupdate方法。
namedparameterjdbctemplate可以使用datasource或jdbctemplate 对象作为构造器参数初始化。
namedparameterjdbctemplate类为命名参数设值有两种方式:java.util.map 、rowmapper 和 sqlparametersource。
就是一个hash表,好处是可以根据参数名传参,parammap.put(“sqlparamname”,value)。
这个接口为了实现sql查询结果和对象间的转换,可以自己实现,也可以使用系统实现,主要实现类有:
singlecolumnrowmapper ,sql结果为一个单列的数据,如list<string> , list<integer>,string,integer等beanpropertyrowmapper, sql结果匹配到对象 list< xxxvo> , xxxvo其作用和map一样,就是为sql中的条件参数赋值,默认实现有 :
mapsqlparametersource实现非常简单,只是封装了java.util.map。beanpropertysqlparametersource封装了一个javabean对象,通过javabean对象属性来决定命名参数的值。emptysqlparametersource 一个空的sqlparametersource ,常用来占位使用。//beanpropertysql左传和春秋的关系parametersource传参方式sqlparametersource sps = new beanpropertysqlparametersource(javabean);//mapsqlparametersource传参方式sqlparametersource sps = new mapsqlparametersource();//保证参数名和key相同sps.addvalue("key",value);
返回单行单列数据
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("lect count(*) from student", new hashmap<>(), integer.class);string name = template.queryforobject( "lect 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)
publi1937年8月28日c < t> list< t> queryforlist(string sql, sqlparametersource paramsource, class< t> elementtype)
list< string> namelist = template.queryforlist("lect 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( "lect * from student limit 1", new hashmap<>(), new beanpropertyrowmapper<student>(student.class));//beanpropertyrowmapper会把下划线转化为驼峰属性//结果对象可比实际返回字段多或者少
注意:这两个api也可以使用singlecolumnrowmapper返回单行单列数据
string name = template.queryforobject( "lect 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("lect * 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( "lect * 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( "lect * from student", new hashmap<>());
使用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( "inrt 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.tid(uuid.randomuuid().tostring());dto.tname("小红");dto.thomeaddress("成都");//------------------------------template.update("inrt 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("inrt into student(id,name,home_address) values (:id,:name,:homeaddress)",mapsqlparametersource);
开发中尽量使用
namedparameterjdbctemplate代经验总结替jdbctemplate,如果想使用jdbctemplate,也可以通过namedparameterjdbctemplate#getjdbcoperations()获取不建议使用查询结构为map的api
本文发布于:2023-04-05 11:29:52,感谢您对本站的认可!
本文链接:https://www.wtabcd.cn/fanwen/zuowen/61bd11ced473d6f1bab56ede56df7ae1.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文word下载地址:template标签是什么意思(vue的template用法).doc
本文 PDF 下载地址:template标签是什么意思(vue的template用法).pdf
留言与评论(共有 0 条评论) |