Spring 学习笔记心得(十)JdbcTemplet (注解+XML配置文件)解析

这里小编要提到的是JdbcTemplet在Spring中有两种编写风格,第一种就是普通的占位符,第二种就是NamedParameterJdbcTemplet的命名使用,下面小编就来介绍一下如何使用

1.首先介绍JdbcTemplet中的部分方法介绍

update() 执行DML语句
queryForMap() 查询结果将结果集封装成map集合
queryForMap() 查询结果将结果集封装成map集合
queryForList() 查询结果将结果集封装为list集合
query() 查询竭结果,将结果封装为JavaBean对象

1.1 query()方法示例:

   @Test
    public void query(){
        String sql = "select * from info";
        List<Info> querys = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(Info.class));
        for (Info query : querys) {
            System.out.println(query);
        }
    }
输出结果:
Info{id=6, lastName='aa', email='[email protected]', addr='aaaa'}
Info{id=7, lastName='bb', email='[email protected]', addr='bbbb'}
Info{id=8, lastName='cc', email='[email protected]', addr='cccc'}
Info{id=9, lastName='dd', email='[email protected]', addr='dddd'}
Info{id=10, lastName='ee', email='[email protected]', addr='eeee'}
Info{id=11, lastName='gg', email='[email protected]', addr='gggg'}
Info{id=12, lastName='ff', email='[email protected]', addr='ffff'}
Info{id=13, lastName='hh', email='[email protected]', addr='hhhh'}
Info{id=14, lastName='ii', email='[email protected]', addr='iiii'}
Info{id=15, lastName='jj', email='[email protected]', addr='aabbcc'}

1.2 queryForMap()方法示例:

    @Test
    public void queryForMap(){
            //查询一个对象出来 把它封装为键值对
            String sql = "select * from info where id = ?";
        Map<String, Object> stringObjectMap = jdbcTemplate.queryForMap(sql,10);
        Set<String> maps = stringObjectMap.keySet();
        for (String map : maps) {
            System.out.println("map : "+ map + " " + stringObjectMap.get(map));
        }
    }
输出结果:
map : id 10
map : lastName ee
map : email ee@qq.com
map : addr eeee

1.3 queryForObject()方法示例:

 @Test
    public void queryForObject(){
            String sql = "select * from info where id = ? ";
        Info info = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<>(Info.class),6);
            System.out.println(info);
        }
Info{id=6, lastName='aa', email='[email protected]', addr='aaaa'}

1.4 queryForObject()查询聚合函数返回值:

		 @Test
        public void queryForObject2(){
            String sql = "SELECT COUNT(id) FROM info ";
            Long size = jdbcTemplate.queryForObject(sql, long.class);
            
        }

1.5 queryForList方法示例:

  @Test
        public void queryForList(){
            String sql = "select * from info";
            List<Map<String, Object>> alist = jdbcTemplate.queryForList(sql);
            for (Map<String, Object> maps : alist) {
                Set<String> map = maps.keySet();
                for (String s : map) {
                    System.out.print("s:"+maps.get(s)+"\t");
                }
                System.out.println("\n-------------------");
            }
        }
输出结果:
s:6	s:aa	s:aa@qq.com	s:aaaa	
-------------------------------------------
s:7	s:bb	s:bb@qq.com	s:bbbb	
-------------------------------------------
s:8	s:cc	s:cc@qq.com	s:cccc	
-------------------------------------------
s:9	s:dd	s:dd@qq.com	s:dddd	
-------------------------------------------
s:10	s:ee	s:ee@qq.com	s:eeee	
-------------------------------------------
s:11	s:gg	s:gg@qq.com	s:gggg	
-------------------------------------------
s:12	s:ff	s:ff@qq.com	s:ffff
-------------------------------------------
s:13	s:hh	s:hh@qq.com	s:hhhh	
-------------------------------------------
s:14	s:ii	s:ii@qq.com	s:iiii
-------------------------------------------
s:15	s:jj	s:jj@qq.com	s:aabbcc	
-------------------------------------------

2.JdbcTemplet注解形式配置使用

2.1 创建Dao类(BookSaleDao)

public interface BookSaleDao {

    //根据书的id查找书的价格
    public int findBookPriceByBnis(String is);
    //根据书的id更新书的库存
    public void updateStockByBnis(String is);
    //买书操作
    public void flushBookBuy();
    //更新用户余额
    public void UpdateUserAccount(String is , int price);

}

2.2 创建DaoImp类(BookSaleDaoImpl)

@Repository("bookSaleDao")
public class BookSaleDaoImpl implements BookSaleDao{

    @Autowired
    private JdbcTemplate jdbcTemplate;
    @Autowired
    private BookSaleDao bookSaleDao;
    @Override
    public int findBookPriceByBnis(String is) {
      
    }

    @Override
    public void updateStockByBnis(String is) {
       
    }
        
    @Override
    public void flushBookBuy() {
     
    }

    @Override
    public void UpdateUserAccount(String is, int price) {
     
    }

}

2.3 创建applicationContext.xml配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:p="http://www.springframework.org/schema/p"
       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-4.2.xsd">
<-- 扫描包 -->
<context:component-scan base-package="cn.itcast.jdbcSpring.Transcation"></context:component-scan>
  <!--  引入外部配置文件 -->
<context:property-placeholder location="classpath:druid.properties"></context:property-placeholder>
  <!--  配置数据源 -->
<bean id="source" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="username" value="${jdbc.user}"></property>
    <property name="password" value="${jdbc.password}"></property>
    <property name="url" value="${jdbc.url}"></property>
    <property name="driverClassName" value="${jdbc.driverClassName}"></property>
</bean>
			  <!--  配置JdbcTemplate -->
        <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
            <property name="dataSource" ref="source"></property>
        </bean>

</beans>

2.4 druid.properties配置文件创建使用(千万要注意配置文件中不要乱敲空格,不然很容易出现意外的…)

jdbc.user=root
jdbc.password=123456
jdbc.url=jdbc:mysql:///wom?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true
jdbc.driverClassName=com.mysql.cj.jdbc.Driver
jdbc.initialSize=5
jdbc.maxActive=10
jdbc.maxWait=3000
jdbc.maxIdle=8
jdbc.minIdle=3

2.4.1 数据库中的脚本:

# 1.用户表 username , price 
# 2.书表  Bnis , price 
# 3.库存表  Bnis_id , stock

CREATE TABLE user_Account
( username VARCHAR(20) NOT NULL , 
   price INT(4) NOT NULL  )

CREATE TABLE book
(Bnis VARCHAR(3) NOT NULL , 
 price INT(4) NOT NULL )
 
 CREATE TABLE book_stock
 ( Bnis_id VARCHAR(3) NOT NULL , 
   stock INT(3) NOT NULL )
   
   SELECT * FROM user_Account , book , book_stock

2.4.2 user_Account表中的内容

在这里插入图片描述
2.4.3 book表中的内容:

在这里插入图片描述
2.4.4 book_stock表中的内容

Spring 学习笔记心得(十)JdbcTemplet (注解+XML配置文件)解析_第1张图片

2.5 编写测试类(TestAnnotationTranscation)

 private ApplicationContext ctx;
        private BookSaleDao bookSaleDao;
        private JdbcTemplate jdbcTemplate;
    {
        ctx = new ClassPathXmlApplicationContext("spring-annotation_transcation.xml");
        bookSaleDao = ctx.getBean(BookSaleDao.class);
        jdbcTemplate = ctx.getBean(JdbcTemplate.class);


    }
    @Test
    public void testFindPrice(){
        int price = bookSaleDao.findBookPriceByBnis("101");
        System.out.println(price);
    }
@Test
    public void testFindStock(){
        bookSaleDao.updateStockByBnis("101");
    }
    @Test
    public void executionSql(){
       bookSaleDao.flushBookBuy();
    }

2.6 首先实现根据书的id查找书的价格(findBookPriceByBnis(String is)),这里时queryForObject()方法传入的时Integer.class

@Repository("bookSaleDao")
public class BookSaleDaoImpl implements BookSaleDao{

    @Autowired
    private JdbcTemplate jdbcTemplate;
    @Autowired
    private BookSaleDao bookSaleDao;
    @Override
    public int findBookPriceByBnis(String is) {
        return jdbcTemplate.queryForObject("SELECT price FROM book WHERE Bnis = ? " , Integer.class , is);
    }
}
输出结果:100

2.7 因为DML可能会出现异常,而且MYSQL是允许数据为负数,所以小编自定义两个异常,一个是更新库存的异常,另一个是用户买书时余额不足的异常

2.7.1 更新库存类 (BookStockLessException)重写五个构造方法

public class BookStockLessException extends RuntimeException{

    public BookStockLessException() {
    }

    public BookStockLessException(String message) {
        super(message);
    }

    public BookStockLessException(String message, Throwable cause) {
        super(message, cause);
    }

    public BookStockLessException(Throwable cause) {
        super(cause);
    }

    public BookStockLessException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
        super(message, cause, enableSuppression, writableStackTrace);
    }
}

2.7.2 创建用户余额不足类UserPriceException,声明同上

public class UserPriceException extends RuntimeException 

2.8 实现 根据书的id更新书的库存 updateStockByBnis(String is)

 @Override
    public void updateStockByBnis(String is) {
        /**
         * MYSQL没有检查语法 所以自定义检查锁
         */
        String select_stock = "SELECT stock FROM book_stock WHERE Bnis_id = ? ";

        Integer stock_count = jdbcTemplate.queryForObject(select_stock, Integer.class, is);
       
        if(stock_count == 0){
            throw new BookStockLessException("库存不足...");
        }
        String sql = "UPDATE book_stock SET stock = stock - 1 WHERE Bnis_id = ?";
        jdbcTemplate.update(sql,is);
    }

2.9 实现用户买书方法(UpdateUserAccount(String is, int price) )

 /*
          MYSQL没有检查语法 所以自定义检查锁
         */
        String select_sql = "SELECT price FROM user_Account WHERE username = ?";
        Integer brance = jdbcTemplate.queryForObject(select_sql, Integer.class, "Rocy");
      
        if(brance - price < 0){
           throw new UserPriceException("余额不足...");
        }
        String execute_update_sql = "update user_Account set price = price - ? where username = ?";

        jdbcTemplate.update(execute_update_sql,price,"Rocy");

3 这里我们虽然看似已经写好了,但是,关于DML操作涉及到事务的概念,如果我们这里不配事务管理器,即使出现了异常,也仅仅只是出现异常,没有得到解决和回滚,我们最初的实现方式是手动提交手动捕获和手动回滚。但是spring给我们提供了@Transcational注解,所以我们使用只需要添加注解即可

3.1 实现买书交流全流程:加上@Transcational注解之后,发生交易异常可以实现回滚

  @Override
  @Transactional
    public void flushBookBuy() {
        String is = "101";
        //1.根据书的id查询价格
        int price = bookSaleDao.findBookPriceByBnis("101");
        //2.买书
        bookSaleDao.updateStockByBnis(is);
        //3.是否成功买书
        bookSaleDao.UpdateUserAccount(is,price);
    }

3.2 测试事务回滚:

用户金额:
在这里插入图片描述
库存数量:
在这里插入图片描述
书的单价是100元,如果这个时候我去买书,那么肯定是不会成功的,执行买书的方法,结果如下:

Spring 学习笔记心得(十)JdbcTemplet (注解+XML配置文件)解析_第2张图片
再次查看数据库中:书的库存还是没有发生改变,用户金额也没有发生改变
在这里插入图片描述
在这里插入图片描述


3.XML配置文件配置事务

3.1 创建applicationContext.xml配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/tx
       http://www.springframework.org/schema/tx/spring-tx.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context-4.2.xsd
       http://www.springframework.org/schema/aop 
       http://www.springframework.org/schema/aop/spring-aop.xsd">
 
    <!--
            1.配置bena
            2 导入druid 连接池文件
            3.配置数据源
            4.配置事务管理器
            5.配置事务开启器
            6.配置切入点
            7.切入点和事务管理器联系
    -->
    <bean id="bookSaleDao" class="cn.itcast.jdbcSpring.Transcation.Xml_Annotation.BookSaleDao.BookSaleDaoImpl">
        <property name="jdbcTemplate" ref="jdbcTemplate"></property>
    </bean>
    <!-- 引入外部配置文件 -->
    <context:property-placeholder location="classpath:druid.properties"/>
  
    <!-- 配置DriverManagerDataSource数据源 -->
    <bean id="source" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="username" value="${jdbc.user}"/>
        <property name="password" value="${jdbc.password}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="driverClassName" value="${jdbc.driverClassName}"/>
    </bean>

    <!-- 2.jdbc-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="source"></property>
    </bean>
		<!--  配置事务管理器 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="source"></property>
    </bean>
	
		<!--  配置事务开启 -->
    <tx:advice id="txDriver" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="*" rollback-for="java.lang.Exception"/>
        </tx:attributes>
    </tx:advice>

<!--  配置切入点与事务管理器的联系 -->
<aop:config>
    <aop:pointcut id="point"
         expression="execution(* cn.itcast.jdbcSpring.Transcation.Xml_Annotation.BookSaleDao.BookSaleDao.*(..))"></aop:pointcut>
    <aop:advisor advice-ref="txDriver" pointcut-ref="point"></aop:advisor>
</aop:config>
</beans>

测试买书方法,效果与楼上注解方式一致,这里要注意的是rollback-for=“java.lang.Exception”,这里是指定遇见什么异常才会回滚,这里直接声明最大的异常类。好了关于注解和XML配置文件的注解方式就这么多了,希望能够帮助到大家

你可能感兴趣的:(spring,spring,java)