jdbcTemplate使用
<dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>6.0.4</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.31</version></dependency><!-- spring里面自带了一个连接池,, 也可以用druid--><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.2.12</version></dependency></dependencies>
@Configuration
@PropertySource("classpath:db.properties")
@Data
public class JavaConfig {@Value("${db.username}")private String username;@Value("${db.password}")private String password;@Value("${db.url}")private String url;@Beanpublic DataSource dataSource(){DruidDataSource ds = new DruidDataSource();ds.setUsername(username);ds.setUrl(url);ds.setPassword(password);return ds;}@Beanpublic JdbcTemplate jdbcTemplate(DataSource dataSource){return new JdbcTemplate(dataSource);}}
public class Demo {public static void main(String[] args) {AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(JavaConfig.class);JdbcTemplate jdbcTemplate = ctx.getBean(JdbcTemplate.class);// // ddl 创建一张表,修改一个表的结构 data definition language 表定义操作
// jdbcTemplate.execute();
// // 批处理,调用这个方法
// jdbcTemplate.batchUpdate();
// // 增删改
// jdbcTemplate.update();
// jdbcTemplate.query();
// jdbcTemplate.queryForList();// ddl data definition language
// jdbcTemplate.execute();// 批处理
// jdbcTemplate.batchUpdate()
// jdbcTemplate.queryForList()
// jdbcTemplate.query()// add(jdbcTemplate);
// update(jdbcTemplate);
// delete(jdbcTemplate);
// query2(jdbcTemplate);
// query3(jdbcTemplate);
// query4(jdbcTemplate);
// query5(jdbcTemplate);query6(jdbcTemplate);}private static void add(JdbcTemplate jdbcTemplate){int row = jdbcTemplate.update("insert into user(name,address) values (?,?)", "cc", "chengdu");System.out.println("row = " + row);}private static void update(JdbcTemplate jdbcTemplate){int row = jdbcTemplate.update("update user set address = ? where id=? ", "beijing", 1);System.out.println("row = " + row);}private static void delete(JdbcTemplate jdbcTemplate){int row = jdbcTemplate.update("delete from user where id =?", 4);System.out.println("row = " + row);}public static void query(JdbcTemplate jdbcTemplate){jdbcTemplate.query("select * from user where address = ?", new RowCallbackHandler() {@Overridepublic void processRow(ResultSet rs) throws SQLException {// 外面声明一个list}},"chengdu");}public static void query2(JdbcTemplate jdbcTemplate){List<User> list = jdbcTemplate.query("select * from user where address = ?", new RowMapper<User>() {@Overridepublic User mapRow(ResultSet rs, int rowNum) throws SQLException {User user = new User();user.setId(rs.getInt("id"));user.setName(rs.getString("name"));user.setAddress(rs.getString("address"));return user;}}, "chengdu");System.out.println(Arrays.toString(list.toArray()));}public static void query3(JdbcTemplate jdbcTemplate){// 自动将查询结果 映射到对象上,,, 前提是查询的结果的列名称必须和实体的属性名称保持一致// 属性对不上,使用RowMapper自己去做一一映射List<User> list = jdbcTemplate.query("select * from user where address = ?", new BeanPropertyRowMapper<>(User.class), "chengdu");System.out.println(Arrays.toString(list.toArray()));}public static void query4(JdbcTemplate jdbcTemplate){// 查询一个用户User user = jdbcTemplate.queryForObject("select * from user where id = ?", new BeanPropertyRowMapper<>(User.class), 1);System.out.println("user = " + user);}public static void query5(JdbcTemplate jdbcTemplate){// 第二个参数,,设置普通对象,,,查询结果只能返回一列String name = jdbcTemplate.queryForObject("select name from user where id = ?", String.class, 1);System.out.println("name = " + name);}public static void query6(JdbcTemplate jdbcTemplate){// queryForList只能有一列,不能有多列List<String> users = jdbcTemplate.queryForList("select name from user", String.class);System.out.println(Arrays.toString(users.toArray()));}
}
传统的jdbcTemplate都是用 ?
做占位符,, ,,也可以不使用?
而是使用变量名称来传递参数。。使用NamedParameterJdbcTemplate
…避免问号的顺序搞反了,
@Beanpublic NamedParameterJdbcTemplate namedParameterJdbcTemplate(){return new NamedParameterJdbcTemplate(dataSource());}
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(JavaConfig.class);NamedParameterJdbcTemplate jdbcTemplate = ctx.getBean(NamedParameterJdbcTemplate.class);Map<String, Object> map = new HashMap<>();map.put("id",2);map.put("address","chengdu");List<User> list = jdbcTemplate.query("select * from user where id>:id and address = :address", map, new BeanPropertyRowMapper<>(User.class));System.out.println(Arrays.toString(list.toArray()));
事务
事务的四大特性
acid
- atomicity : 原子性,,, 一个事务中的所有操作,要么全部完成,要么全部不完成
- consistency : 一致性 ,,, 事务开始之前和事务结束之后,数据库的完整性没有被破坏
- isolation : 隔离性,, 多个事务执行,会隔离,,事务隔离等级:读未提交,读已提交,可重复读,串行化
- durability : 持久性,,,事务结束之后,对数据的修改是永久的
spring中的事务
编程式事务:
使用TransactionManager,, 先传入数据源配置一个TransactionManager,
/*** 事务管理器* @return*/@BeanPlatformTransactionManager platformTransactionManager(){return new DataSourceTransactionManager(dataSource());}
transaction.getTransaction()
获取一个事务,,
transaction.commit()
: 提交事务
transaction.rollback()
: 回滚事务
public void transfer(String from,String to,Double money){DefaultTransactionDefinition definition = new DefaultTransactionDefinition();TransactionStatus status = transactionManager.getTransaction(definition);try {accountDao.minusMoney(from,money);
// int i = 1/0;accountDao.addMoney(to,money);// 提交事务transactionManager.commit(status);} catch (Exception e) {System.out.println(e.getMessage());// 回滚事务transactionManager.rollback(status);}}}
也可以用 transactionTemplate ,, spring利用aop的思想,把很多重复的东西封装了,比如jdbcTeamplate,transactionTemplate
@BeanTransactionTemplate transactionTemplate(){// 传入一个 transactionManagerreturn new TransactionTemplate(platformTransactionManager());}
public void transfer(String from,String to,Double money){transactionTemplate.execute(new TransactionCallbackWithoutResult() {@Overrideprotected void doInTransactionWithoutResult(TransactionStatus status) {accountDao.minusMoney(from,money);int i = 1/0;accountDao.addMoney(to,money);}});}
编程式事务一般不用,因为还是有侵入的代码,事务和业务的代码混在一起
声明式事务
声明式事务本质上是aop,,需要配置tx:advice ,,事务的通知,,也就是需要被增强的方法名字,,,
aop将这个通知配置进去。。。
声明式事务底层就是aop,需要添加包:
<dependency><groupId>org.springframework</groupId><artifactId>spring-aspects</artifactId><version>6.0.4</version></dependency>
<?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: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/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd"><context:component-scan base-package="com.cj.ts02"/><context:property-placeholder location="db.properties"/><bean class="com.alibaba.druid.pool.DruidDataSource" id="dataSource"><property name="url" value="${db.url}"/><property name="username" value="${db.username}"/><property name="password" value="${db.password}"/></bean><bean class="org.springframework.jdbc.core.JdbcTemplate" id="jdbcTemplate"><property name="dataSource" ref="dataSource"/></bean><bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="transactionManager"><property name="dataSource" ref="dataSource"/></bean><!-- 声明式事务,本质还是aop-->
<!-- 要增强的方法--><tx:advice id="txAdvice" transaction-manager="transactionManager"><tx:attributes>
<!-- 配置事务的属性,哪些方法要加事务,可以使用通配符 --><tx:method name="transfer"/>
<!-- <tx:method name="add*"/>--></tx:attributes></tx:advice><!-- aop配置,,, 相当于把这个transfer方法动态代理了,,--><aop:config><aop:pointcut id="pc" expression="execution(* com.cj.ts02.AccountService.*(..))"/><aop:advisor advice-ref="txAdvice" pointcut-ref="pc"/></aop:config>
</beans>
java代码实现事务:使用EnableTransactionManager
开启事务,,开启了之后,,就能直接使用@Transactional
注解去标识,哪个方法要有事务
@Configuration
@ComponentScan(basePackages = "com.cj.ts02")
@PropertySource("classpath:db.properties")
// 开启事务注解,, 开了之后只需要在方法上添加 @Transactional 即可
@EnableTransactionManagement
public class JavaConfig {@Value("${db.url}")private String url;@Value("${db.username}")private String username;@Value("${db.password}")private String password;@Beanpublic JdbcTemplate jdbcTemplate(){JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource());return jdbcTemplate;}@BeanDataSource dataSource(){DruidDataSource ds = new DruidDataSource();ds.setUsername(username);ds.setPassword(password);ds.setUrl(url);return ds;}/*** 事务管理器* @return*/@BeanPlatformTransactionManager platformTransactionManager(){return new DataSourceTransactionManager(dataSource());}
}
java和xml结合使用,,, 在xml中可以使用<tx:annotation-driven/>
: 这个配置表示启用事务注解,,相当于@EnableTransactionManager
在spring中加事务的方式都一样,,,spring中将事务的实现都抽象出来了,有一套抽象的解决方案,,,框架只需要实现接口,就能使用spring中的事务
TransactionManager : 事务管理器
TransactionDefinition : 事务的定义
TransactionStatus : 事务的状态
PlatformTransactionManager
- getTransaction()