Spring 对数据库的操作在 jdbc 上面做了深层次的封装,使用 Spring 的注入功能,把 DataSource 注册到 JdbcTemplate 中。
基本使用
在 pom.xml 中引入相关依赖
- 数据库驱动
- 数据库连接池
- spring-jdbc
- spring-tx:事务和异常控制
```xml
mysql mysql-connector-java 8.0.22
<a name="5E9Ps"></a>
#### 数据库配置文件
在 src/main/resources 下创建数据库连接配置文件:db.properties
jdbc.username=root jdbc.password=1911472163Pzs_ jdbc.url=jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&useSSL=true jdbc.driverClassName=com.mysql.cj.jdbc.Driver
<a name="trjNE"></a>
#### spring 配置类
创建 Spring 配置类:
```java
@Configuration
@PropertySource(value = {"classpath:db.properties"}) //指定配置文件位置
@EnableTransactionManagement //开启事务配置
public class DemoConfig {
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.password}")
private String password;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.driverClassName}")
private String driverClassName;
// 配置一个Druid连接池
@Bean
public DataSource dataSource() {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setUsername(username);
dataSource.setPassword(password);
dataSource.setUrl(url);
dataSource.setDriverClassName(driverClassName);
return dataSource;
}
// 配置一个JdbcTemplate实例,注入dataSource数据源
@Bean
public JdbcTemplate jdbcTemplate(@Autowired DataSource dataSource) {
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
return jdbcTemplate;
}
}
测试 jdbcTemplate
JdbcTemplate 提供的方法:
- execute():用于执行任何 SQL 语句,一般用来执行 DDL 语句
- update()/batchUpdate():update 方法用于执行新增、修改、删除等语句;batchUpdate 方法用于执行批处理相关语句
- query()/queryForXXX():用于执行查询相关语句
call():用于执行存储过程、函数相关语句
public class DemoTest {
private JdbcTemplate jdbcTemplate;
@Before
public void before() {
ApplicationContext context =
new AnnotationConfigApplicationContext(DemoConfig.class);
jdbcTemplate = (JdbcTemplate) context.getBean("jdbcTemplate");
}
@Test
public void testInsert() {
// 插入数据
String sql = "insert into t_user (name, age) values (?, ?)";
int update = jdbcTemplate.update(sql, "李四", 18);
System.out.println(update);
}
@Test
public void testUpdate() {
// 更新数据
String sql = "update t_user set name=?,age=? where id=?";
int update = jdbcTemplate.update(sql, new Object[]{"万斯", 19, 1});
System.out.println(update);
}
@Test
public void testDelete() {
// 删除数据
String sql = "delete from t_user where id=?";
int update = jdbcTemplate.update(sql, 2);
System.out.println(update);
}
@Test
public void testBatchUpdate() {
// 批量插入
String sql = "insert into t_user (name, age) values (?, ?)";
List<Object[]> batchArgs = new ArrayList<Object[]>() {
{
add(new Object[]{"世界", 53});
add(new Object[]{"Bob", 83});
add(new Object[]{"风华", 48});
}
};
// batchUpdate的第二个参数为Object[]类型
int[] update = jdbcTemplate.batchUpdate(sql, batchArgs);
System.out.println(Arrays.toString(update));
}
@Test
public void testSingleSelect() {
// 查询数据,读取单个对象
String sql = "select id,name,age from t_user where id=?";
// BeanPropertyRowMapper要求数据库查询出来的列和实体属性一一对应,如果列名和属性不一致,则需要设置查询别名
RowMapper<User> rowMapper = new BeanPropertyRowMapper<>(User.class);
// 使用JdbcTemplate对象不能获取关联对象
User user = jdbcTemplate.queryForObject(sql, rowMapper, 3);
System.out.println(user);
}
@Test
public void testMultiSelect() {
String sql = "select id,name,age from t_user";
RowMapper<User> rowMapper = new BeanPropertyRowMapper<>(User.class);
// 查询多个对象
List<User> query = jdbcTemplate.query(sql, rowMapper);
// 避免空指针
Optional.of(query)
.map(Collection::stream)
.orElse(Stream.empty())
.forEach(System.out::println);
}
@Test
public void testOtherSelect() {
// 获取某个记录或者count、avg等函数返回的唯一值
String sql = "select count(*) from t_user";
Integer integer = jdbcTemplate.queryForObject(sql, Integer.class);
System.out.println(integer);
}
}
实际使用
1、构建 UserDao 层:
// UserDao
public interface UserDao {
// 插入数据
int insert(User user);
// 根据id查询数据
User selectById(int id);
// 查询数据
List<User> select();
// 更新数据
int update(User user);
// 删除数据
int delete(int id);
}
// UserDaoImpl实现类
@Repository
public class UserDaoImpl implements UserDao {
@Autowired
private JdbcTemplate jdbcTemplate;
private Integer selectLastInsertID() {
// 获取最后一个由Auto_Increment插入的值
String sql = "select LAST_INSERT_ID()";
return jdbcTemplate.queryForObject(sql, Integer.class);
}
@Override
public int insert(User user) {
// 插入数据
String sql = "insert into t_user (name, age) values (?, ?)";
int update = jdbcTemplate.update(sql, user.getName(), user.getAge());
// 获取刚刚插入数据的id
Integer id = selectLastInsertID();
// id回写到user
user.setId(id);
return update;
}
@Override
public User selectById(int id) {
// 构建查询语句
String sql = "select id,name,age from t_user where id=?";
// 构建对象映射
RowMapper<User> rowMapper = new BeanPropertyRowMapper<>(User.class);
// 进行查询
return jdbcTemplate.queryForObject(sql, rowMapper, id);
}
@Override
public List<User> select() {
// 构建查询语句
String sql = "select id,name,age from t_user limit ?,?";
// 构建对象映射
RowMapper<User> rowMapper = new BeanPropertyRowMapper<>(User.class);
// 这里可以作分页处理,这里就不再测试,直接固定数据
List<User> query = jdbcTemplate.query(sql, rowMapper, 2, 2);
return query;
}
@Override
public int update(User user) {
// 构建sql语句
String sql = "update t_user set name=?,age=? where id=?";
int update = jdbcTemplate.update(sql, user.getName(), user.getAge(), user.getId());
return update;
}
@Override
public int delete(int id) {
String sql = "delete from t_user where id=?";
int delete = jdbcTemplate.update(sql, id);
return delete;
}
}
2、构建 UserService 层:
在Spring中,如果需要进行事务管理,需要有如下几点:
- 在配置类上使用 @EnableTransactionManagement 开启事务配置
- 配置一个事务管理器:TransactionManager
- 在需要使用事务的 service 方法上使用 @Transaction 注解
在配置类中配置 jdbc 的事务管理器:
// 在配置类中配置jdbc的事务管理器
@Bean
public PlatformTransactionManager transactionManager() {
return new DataSourceTransactionManager(dataSource());
}
创建 UserService:
public interface UserService {
Integer insert(User user);
User selectById(int id);
List<User> select();
int update(User user);
int delete(int id);
}
创建 UserServiceImpl:
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserDao userDao;
@Override
@Transactional(propagation = Propagation.MANDATORY)
public Integer insert(User user) {
return userDao.insert(user);
}
@Override
public User selectById(int id) {
return userDao.selectById(id);
}
@Override
public List<User> select() {
return userDao.select();
}
@Override
@Transactional
public int update(User user) {
return userDao.update(user);
}
@Override
@Transactional
public int delete(int id) {
return userDao.delete(id);
}
}
3、测试:
public class UserServiceTest {
private UserService userService;
@Before
public void before() {
ApplicationContext context =
new AnnotationConfigApplicationContext(DemoConfig.class);
userService = context.getBean(UserService.class);
}
@Test
public void testInsert() {
User user = new User().setName("shen").setAge(44);
Integer insert = userService.insert(user);
System.out.println(insert);
System.out.println(user);
}
@Test
public void testDelete() {
int delete = userService.delete(8);
System.out.println(delete);
}
@Test
public void testSelect() {
List<User> select = userService.select();
Optional.of(select)
.map(Collection::stream)
.orElse(Stream.empty())
.forEach(System.out::println);
}
@Test
public void testUpdate() {
int i = userService.update(new User().setId(1).setName("狮虎").setAge(28));
System.out.println(i);
}
}