Spring整合JDBC
Spring也封装了JDBC的代码,和Mybatis的功能作用是一样的。
Spring中提供了一个可以操作数据库的对象,该对象封装了JDBC技术。这个对象叫JDBCTemplate(JDBC模板),该对象与DButils中QueryRunner非常相处。
Spring jdbc的功能和Mybatis、Hibernate是一样的,都是持久层功能
Spring提供了很多整合DAO的技术
手动管理方法测试JDBC模板
1.先将数据库连接信息放到配置文件中:
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
<default-config>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/db0527</property>
<property name="user">root</property>
<property name="password">123</property>
<property name="initialPoolSize">5</property>
<property name="maxPoolSize">20</property>
</default-config>
</c3p0-config>
数据库表结构:
测试:
public void fun(){
ComboPooledDataSource dataSource = new ComboPooledDataSource();
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
int update = jdbcTemplate.update("insert into tb_user(name,balance) values ('1zzz',100)");
System.out.println(update);
}
添加成功:
Spring管理方法测试JDBC模板
使用到了JdbcTemplate对象。
1.准备数据库。
实体类:
public class User {
private Integer id;;
private String name;
private Double balance;
}
2.编写DAO接口、和实现CURD操作
public interface UserDao {
public void save(User user);
public void delete(Integer uid);
public void update(User user);
public User getUserById(Integer id);
}
实现接口方法:
public class UserDaoImpl implements UserDao {
private JdbcTemplate jt;
@Override
public void save(User user) {//插入数据
jt.update("insert into tb_user(name, balance) VALUES (?,?)",user.getName(),user.getBalance());
}
@Override
public void delete(Integer uid) {//删除
jt.update("delete from tb_user where id = ?",uid);
}
@Override
public void update(User user) {//更新
jt.update("update tb_user set name=?,balance=? where id=?",user.getName(),user.getBalance(),user.getId());
}
@Override
public User getUserById(Integer id) {//查询
String sql = "select id,name,balance from tb_user where id =?";
User user = jt.queryForObject(sql, new RowMapper<User>() {
@Override
public User mapRow(ResultSet resultSet, int i) throws SQLException {
User user1 = new User();
user1.setId(resultSet.getInt("id"));
user1.setName(resultSet.getString("name"));
user1.setBalance(resultSet.getDouble("balance"));
return user1;
}
}, id);
return user;
}
public JdbcTemplate getJt() {
return jt;
}
}
spring配置文件配置:
<bean name="datasource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/db0527"></property>
<property name="user" value="root"></property>
<property name="password" value="123"></property>
</bean>
<bean name="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="datasource"></property>
</bean>
<bean name="userdao" class="com.huadian.i_spring_jdbc.dao.impl.UserDaoImpl">
<property name="jt" ref="jdbcTemplate"></property>
</bean>
测试:
测试前表:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:i_applicationContext.xml")
public class demo {
@Autowired
private UserDao userDao;
@Test
public void fun(){//查询
System.out.println(userDao.getUserById(1));
// userDao.getUserById(1);
}
@Test
public void fun1(){//添加
User user = new User("777",1000.0);
userDao.save(user);
}
@Test
public void fun2(){//删除
userDao.delete(2);
}
@Test
public void fun3(){//更新
User user = new User(3, "aa", 100.0);
userDao.update(user);
}
}
查询:
添加:
删除:
更新:
Spring管理方法测试JDBC模板(DAO继承)
public class UserDaoImpl extends JdbcDaoSupport implements UserDao
使userDaoimpl继承JdbcDaoSupport 接口。此时在spring配置文件中就不需要添加
JdbcTemplate的依赖了。
<bean name="datasource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="com.mysql.jdbc.Driver"></property> <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/db0527"></property> <property name="user" value="root"></property> <property name="password" value="123"></property> </bean> <bean name="userdao" class="com.huadian.i_spring_jdbc.dao.impl.UserDaoImpl"> <property name="jt" ref="jdbcTemplate"></property> </bean>
这时候用 this.getJdbcTemplate() 来替换jt。
数据库信息放到配置文件中
添加配置文件db.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/db0527?characterEncoding=UTF-8
jdbc.username=root]
jdbc.password=123
开启注解扫描:
<context:property-placeholder location="classpath:db.properties"></context:property-placeholder>
<property name="user" value="root"></property>
<property name="user" value="${jdbc.username}"></property>
Spring中AOP事务
回顾事务相关内容
事务特性:ACID
事务并发的问题:脏读、不可重复读(行记录)、幻读(虚读)(表记录)
事务的隔离级别:1读未提交、2读已经提交数据 4 可重复读 8串行化
Spring需要干的事情
(1)封装相关的代码:打开事务、提交事务、回滚事务
(2)提供 事务操作的对象
因为在不同的平台,操作事务的代码各不相同,Spring提供一个接口,名字:PlatformTransactionManager接口,针对不同的平台提供不同的实现类。
(3)数据库相关的设置
隔离级别、是否只读、事务的传播行为(了解)
Spring管理事务方式
方式一:XML方式配置(重点)
(1)准备转账的材料,并且测试没有问题
(2)准备需要管理的事务
a.配置 核心事务管理器
<!--核心事务管理器-->
<bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
b.配置 事务管理对象 (可选)
<!--事务管理对象-->
<bean name="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager" ref="transactionManager"></property>
</bean>
(3)配置 通知
<!--通知:事务代码,我们需要将事务代码 织入 service 中方法 -->
<tx:advice id ="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="save*" isolation="DEFAULT" read-only="false" propagation="REQUIRED"/>
<tx:method name="persist*" isolation="DEFAULT" read-only="false" propagation="REQUIRED"/>
<tx:method name="modify*" isolation="DEFAULT" read-only="false" propagation="REQUIRED"/>
<tx:method name="update*" isolation="DEFAULT" read-only="false" propagation="REQUIRED"/>
<tx:method name="get*" isolation="DEFAULT" read-only="true" propagation="REQUIRED"/>
<tx:method name="find*" isolation="DEFAULT" read-only="true" propagation="REQUIRED"/>
<tx:method name="delete*" isolation="DEFAULT" read-only="false" propagation="REQUIRED"/>
<tx:method name="remove*" isolation="DEFAULT" read-only="false" propagation="REQUIRED"/>
<tx:method name="transfer*" isolation="DEFAULT" read-only="false" propagation="REQUIRED"/> </tx:attributes>
</tx:advice>
(4)将通知 织入 目标对象
<!--将通知 织入 目标-->
<aop:config>
<aop:pointcut id="txPc" expression="execution(* com.huadian.k_transaction_xml.service.impl.*ServiceImpl.*(..))"></aop:pointcut>
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPc"></aop:advisor>
</aop:config>
测试:
dao接口实现:
public class UserDaoImpl extends JdbcDaoSupport implements UserDao {
@Override
public void reduceBalance(Integer userId, Double money) {
this.getJdbcTemplate().update( "update tb_user set balance = balance - ? where id = ?",money,userId );
}
@Override
public void increaseBalance(Integer userId, Double money) {
this.getJdbcTemplate().update( "update tb_user set balance = balance + ? where id = ?",money,userId );
}
}
service接口实现:
public class UserServiceImpl implements UserService {
@Autowired
private UserDao userDao;
@Override
public void transfer(Integer to, Integer from, double money) {
userDao.increaseBalance(to,money );
int i = 5/0; //模拟错误
userDao.reduceBalance( from,money );
}
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
}
测试类:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:k_applicationContext.xml")
public class demo {
@Autowired
private UserService userService;
@Test
public void fun(){
userService.transfer( 1,3,100 );
}
}
方式二:注解方式配置(重点)
a.配置 核心事务管理器
<!--核心事务管理器-->
<bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
b.配置 事务管理对象 (可选)
<!--事务管理对象-->
<bean name="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager" ref="transactionManager"></property>
</bean>
(3)开启注解管理事务
<!--开启注解事务管理-->
<tx:annotation-driven />
其他配置:
<!--注解扫描-->
<context:component-scan base-package="com.huadian.l_transaction_annotaion"></context:component-scan>
<!--C3P0连接池-->
<bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/db0527"></property>
<property name="user" value="root"></property>
<property name="password" value="123"></property>
</bean>
<!--DAO-->
<bean name="userDao" class="com.huadian.l_transaction_annotaion.dao.impl.UserDaoImpl">
<property name="dataSource" ref="dataSource"></property>
</bean>
注解:srvice接口实现:
@Transactional(isolation = Isolation.DEFAULT,propagation = Propagation.REQUIRED,readOnly = false)
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserDao userDao ;
@Override
public void transfer(Integer to, Integer from, double money) {
userDao.increaseBalance(to,money );
int i = 5/0; //模拟错误
userDao.reduceBalance( from,money );
}
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
测试:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:l_applicationContext.xml")
public class demo {
@Autowired
private UserService userService;
@Test
public void fun(){
userService.transfer( 1,3,100 );
}
}
注意:
public class UserDaoImpl extends JdbcDaoSupport implements UserDao
当dao层使用了继承的时候,就不能使用注解方式,他会找不到datasource。