1. JdbcTemplate的简介
什么是JdbcTemplate?
Spring框架 对JDBC进行封装,使用JdbcTemplate实现对数据库操作;
2. 如何进行简单的Template实际操作
假定接下来需要进行数据库的增删改查,为此,我创建一个library数据库,在这个数据库中我创建了一个book表,表里面有三个字段,反别是Bid、Bname、Bauthor;
以下均为IDEA中的操作;
第一步:创建一个与数据库表结构类似的Javabean
public class BookEn {
private int Bid;
private String Bname;
private String Bauthor;
public void setBid(int bid) {
Bid = bid;
}
public void setBname(String bname) {
Bname = bname;
}
public int getBid() {
return Bid;
}
public String getBname() {
return Bname;
}
public String getBauthor() {
return Bauthor;
}
public void setBauthor(String bauthor) {
Bauthor = bauthor;
}
@Override
public String toString() {
return "BookEn{" +
"Bid=" + Bid +
", Bname='" + Bname + '\'' +
", Bauthor='" + Bauthor + '\'' +
'}';
}
}
第二步创建配置文件:(配置文件中的内容,其实也可以直接使用类注解实现,但是感觉更加麻烦,这里先用配置文件)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!--导入配置文件-->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!--将配置文件中的数据放入-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" >
<property name="driverClassName" value="${prop.driver}"/>
<property name="url" value="${prop.url}"/>
<property name="username" value="${prop.user}"/>
<property name="password" value="${prop.password}"/>
</bean>
<!--JdbcTemplate对象,注入DateSource-->
<!--JdbcTemplate对象-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<!--注入dataSource-->
<property name="dataSource" ref="dataSource"></property>
</bean>
</beans>
注解配置类:
@Configuration
@PropertySource("classpath:jdbc.properties")//指定资源文件位置
@ComponentScan(basePackages = {"cn.dxs.spring"})//指定需要扫描的类的位置;
public class SpringConfig {
//给每个属性先赋配置文件中的值
@Value("${prop.driver}")
private String driverClassName;
@Value("${prop.url}")
private String url;
@Value("${prop.user}")
private String username;
@Value("${prop.password}")
private String password;
@Bean
public DataSource dataSource(){//这里返回的对象必须是带有连接Mysql值的;
DruidDataSource data = new DruidDataSource();
data.setDriverClassName(driverClassName);
data.setUrl(url);
data.setUsername(username);
data.setPassword(password);
return data;//返回对象实例,方便下面的方法调用;
}
@Bean
public JdbcTemplate jdbcTemplate(){
return new JdbcTemplate(dataSource());//去源码,看一下创建对象的方式,创建,并返回就可以了;
}
}
第三步:创建Dao层的接口以及实现类
public interface BookDao {
//添加方法;
void addBook(BookEn bookEn);
//添加删除方法
void delete(BookEn bookEn);
//添加修改方法
void update(BookEn bookEn);
//添加查询单个数据方法
int selectcount();
//通过查询返回指定对象
BookEn seclectObject(BookEn bookEn);
//通过查询返回一个List数组;
List<BookEn> selectList();
}
-------------------下面是实现类--------------
@Component(value = "bookDaoImp")//创建本类对象
public class BookDaoImp implements BookDao {
@Autowired //注入JdbcTemplate
private JdbcTemplate jdbcTemplate;
@Override
public void addBook(BookEn bookEn) {
String sql = "insert into book values(?,?,?)";
//由于后面放的是可变参数,所以这里可以设置一个Object数组
Object[] args = {bookEn.getBid(),bookEn.getBname(),bookEn.getBauthor()};
//第一个参数是SQL语句,第二个参数是可变参数;
int update = jdbcTemplate.update(sql,args);
System.out.println(update);//输出返回参数,看看是多少;
}
@Override
public void delete(BookEn bookEn) {
String sql = "delete from book where Bid=?";
Object[] obj = {bookEn.getBid()};
int i = jdbcTemplate.update(sql,obj);
System.out.println(i);
}
@Override
public void update(BookEn bookEn) {
String sql = "update book set Bauthor=?,Bname=? where Bid=?";
Object[] obj = {bookEn.getBauthor(),bookEn.getBname(),bookEn.getBid(),};
int i = jdbcTemplate.update(sql,obj);
System.out.println(i);
}
//查询表记录数方法;
@Override
public int selectcount() {
String sql = "select count(*) from book";
Integer integer = jdbcTemplate.queryForObject(sql, Integer.class);
return integer;
}
//查询指定对象;
@Override
public BookEn seclectObject(BookEn bookEn) {
String sql = "select * from book where Bid=?";
return jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<BookEn>(BookEn.class), bookEn.getBid());
}
@Override
public List<BookEn> selectList() {
//查询所有的数据,返回一个对象数组
String sql = "select * from book";
List<BookEn> query = jdbcTemplate.query(sql, new BeanPropertyRowMapper<BookEn>(BookEn.class));
return query;
}
}
总结:
在进行增删改
时主要使用的JdbcTemplate中的方法是update(sql,Obgect args)第一个参数是sql语句,第二个参数是一个可变参数(主要是看你的sql语句有多少是?还有就是参数要和上面的进行对齐,顺序不能乱);
查询表的总条目
,是使用queryForObject(sql语句,Class对象),第二个参数就是你需要返回类的Class对象(即返回类.class)
查询表中的对象
,也是使用queryForObject(sql语句,RowMapper<>(),Object args),第二个参数可以写RowMapper接口的实现类实例,BeanPropertyRowMappe<标注返回类类型>(返回类.class);第三个参数是你想要放入sql中的条件;
查询表中的对象数组
;使用的方法是query(sql语句,RowMapper接口实现类对象,【可以有条件,也可以没有】),如果查询整个表的对象,就像我上面代码里面的写法就是没有问题,但是如果想要有条件的查询,就需要第三个参数添加条件;
第四步:连接好数据库之后,就需要到Sevice层区,进行方法的封装,逻辑的处理;
@Service(value = "bookservice")
public class Bookservice {
@Autowired
private BookDao bookDao;
//添加插入数据的方法;
public void addBook(BookEn bookEn){
bookDao.addBook(bookEn);
}
//删除的方法
public void delete(BookEn bookEn){
bookDao.delete(bookEn);
}
//更新的方法
public void update(BookEn bookEn){
bookDao.update(bookEn);
}
//查询总条数的方法;
public int selectcount(){
return bookDao.selectcount();
}
//查询返回指定对象
public BookEn selectObject(BookEn bookEn){
return bookDao.seclectObject(bookEn);
}
public List<BookEn> selectList(){
return bookDao.selectList();
}
}
为什么会有Service层,我的理解应该就是可以将很多不同的方法综合到一起,不然如果不这样直接使用使用Dao实现类中的方法,到时候可能太混乱了;我这个例子很难体现出Service层的作用,因为逻辑很少,但是实际上sql语句也是可以拼接的,如果在这里将sql语句也拼接完,到Dao层就只需要执行了,可能这就是它的意义吧,解耦;仔细看Service几乎没有什么实际对象;
第五步:创建一个测试包,专门写测试类:以下是一个测试方法;
@Test
public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("Spring-config.xml");
Bookservice bookservice = context.getBean("bookservice", Bookservice.class);
//只能创建对象,然后自己放值进去
BookEn bookEn = new BookEn();
bookEn.setBid(3);
bookEn.setBname("十日谈");
bookEn.setBauthor("薄伽丘");
//将放入的值插进去;
bookservice.update(bookEn);
}
3. JdbcTemplate批量操作数据库
3.1 批量操作数据库
在DAO层创建的Java代码:
void batchAddBook(List<Object[]> batchArgs);
//创建批量修改的方法;
void batchupdateBook(List<Object[]> batchArgs);
//批量删除
void batchdeletebook(List<Object[]> batchArgs);
---------------------------上面代码的实现--------------
//批量添加数据进入数据库
@Override
public void batchAddBook(List<Object[]> batchArgs) {
String sql = "insert into book values(?,?,?)";
//输入参数和sql语句进行执行;
int[] i = jdbcTemplate.batchUpdate(sql, batchArgs);
//输出影响的行数
System.out.println(Arrays.toString(i));
}
@Override
public void batchupdateBook(List<Object[]> batchArgs) {
String sql = "update book set Bname=?,Bauthor=? where Bid=?";
int[] i = jdbcTemplate.batchUpdate(sql, batchArgs);
System.out.println(Arrays.toString(i));
}
@Override
public void batchdeletebook(List<Object[]> batchArgs) {
String sql = "delete from book where Bid=?";
//查看返回值,就是数据库中受影响的行数;
int[] i = jdbcTemplate.batchUpdate(sql, batchArgs);
System.out.println(Arrays.toString(i));
}
总结: 在这里插入多行sql语句时使用的方法时batchupdate(sql,List<Object[]>),第一个参数就是一个Sql语句,第二个参数则是一个Object数组为元素的List数组;
在service层:
//批量添加数据
public void batchAdd(List<Object[]> batchArgs){
bookDao.batchAddBook(batchArgs);
}
//批量修改数据
public void batchupdate(List<Object[]> batchArgs){
bookDao.batchupdateBook(batchArgs);
}
public void batchdelete(List<Object[]> batchArgs){
bookDao.batchdeletebook(batchArgs);
}
测试方法层:
@Test
public void test5(){
ApplicationContext context = new ClassPathXmlApplicationContext("Spring-config.xml");
Bookservice bookservice = context.getBean("bookservice", Bookservice.class);
//只能创建对象,然后自己放值进去
List<Object[]> batchargs = new ArrayList<>();
Object[] o1 = {"st","刘慈欣",7};
Object[] o2 = {"十日","薄伽丘",8};
Object[] o3 = {"平凡的","路遥",9};
batchargs.add(o1);
batchargs.add(o2);//将值放入这个动态数组;
batchargs.add(o3);
bookservice.batchupdate(batchargs);//执行方法;
}
Java杂记
- 如果出现Java连接MySQL,结果MySQL乱码的情况,第一件事就是查编码集,还有
表的编码集和表中行的编码集可能不一样
; - 修改行的编码集的语法(虽然记录过,但遇到了还是再做一次笔记):
alter table 表名 change column 旧列名 新列名 类型 character set 字符集 其它约束条件
- 经过Spring中的配置文件全注解的学习,我发现一个将配置文件用全注解实现的规律,简单而言:
就是<bean>标签的都是类,在配置类中写一个方法,该方法使用@Bean注解修饰,最后还要返回一个该类的对象,
除此之外,<property>标签中的值,其实就是这个方法中的成员变量,id就是名字,value就是值;
其它的标签要么就是普通属性,要么就要放到类上面(有特定的注解,比如组件扫描@ComponentScan);