这里小编要提到的是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='aa@qq.com', addr='aaaa'}
Info{id=7, lastName='bb', email='bb@qq.com', addr='bbbb'}
Info{id=8, lastName='cc', email='cc@qq.com', addr='cccc'}
Info{id=9, lastName='dd', email='dd@qq.com', addr='dddd'}
Info{id=10, lastName='ee', email='ee@qq.com', addr='eeee'}
Info{id=11, lastName='gg', email='gg@qq.com', addr='gggg'}
Info{id=12, lastName='ff', email='ff@qq.com', addr='ffff'}
Info{id=13, lastName='hh', email='hh@qq.com', addr='hhhh'}
Info{id=14, lastName='ii', email='ii@qq.com', addr='iiii'}
Info{id=15, lastName='jj', email='jj@qq.com', 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='aa@qq.com', 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表中的内容
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元,如果这个时候我去买书,那么肯定是不会成功的,执行买书的方法,结果如下:
再次查看数据库中:书的库存还是没有发生改变,用户金额也没有发生改变
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配置文件的注解方式就这么多了,希望能够帮助到大家