spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/test?useSSL=false&serverTimezone=Asia/Shanghai&characterEncoding=utf8
username: root
password: 123456
hikari:
maximum-pool-size: 10
minimum-idle: 5
idle-timeout: 600000
max-lifetime: 1800000
connection-timeout: 30000
spring:
datasource:
master:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/master
username: root
password: 123456
slave:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/slave
username: root
password: 123456
@Configuration
public class DataSourceConfig {
@Bean
@Primary
@ConfigurationProperties(prefix = "spring.datasource.master")
public DataSource masterDataSource() {
return DataSourceBuilder.create().build();
}
@Bean
@ConfigurationProperties(prefix = "spring.datasource.slave")
public DataSource slaveDataSource() {
return DataSourceBuilder.create().build();
}
}
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
</dependency>
@Repository
public class UserDao {
@Autowired
private JdbcTemplate jdbcTemplate;
// 查询
public User findById(Long id) {
String sql = "SELECT * FROM user WHERE id = ?";
return jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<>(User.class), id);
}
// 查询列表
public List<User> findAll() {
String sql = "SELECT * FROM user";
return jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(User.class));
}
// 插入
public int insert(User user) {
String sql = "INSERT INTO user (name, age) VALUES (?, ?)";
return jdbcTemplate.update(sql, user.getName(), user.getAge());
}
// 更新
public int update(User user) {
String sql = "UPDATE user SET name = ?, age = ? WHERE id = ?";
return jdbcTemplate.update(sql, user.getName(), user.getAge(), user.getId());
}
// 删除
public int delete(Long id) {
String sql = "DELETE FROM user WHERE id = ?";
return jdbcTemplate.update(sql, id);
}
}
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>3.0.2</version>
</dependency>
mybatis:
mapper-locations: classpath:mapper/*.xml
type-aliases-package: com.example.entity
configuration:
map-underscore-to-camel-case: true
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
@Mapper
public interface UserMapper {
@Select("SELECT * FROM user WHERE id = #{id}")
User findById(Long id);
@Select("SELECT * FROM user")
List<User> findAll();
@Insert("INSERT INTO user (name, age) VALUES (#{name}, #{age})")
@Options(useGeneratedKeys = true, keyProperty = "id")
int insert(User user);
@Update("UPDATE user SET name = #{name}, age = #{age} WHERE id = #{id}")
int update(User user);
@Delete("DELETE FROM user WHERE id = #{id}")
int delete(Long id);
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.mapper.UserMapper">
<resultMap id="userMap" type="User">
<id property="id" column="id"/>
<result property="name" column="name"/>
<result property="age" column="age"/>
</resultMap>
<select id="findById" resultMap="userMap">
SELECT * FROM user WHERE id = #{id}
</select>
<select id="findByCondition" resultMap="userMap">
SELECT * FROM user
<where>
<if test="name != null and name != ''">
AND name LIKE CONCAT('%', #{name}, '%')
</if>
<if test="age != null">
AND age = #{age}
</if>
</where>
</select>
<insert id="insert" useGeneratedKeys="true" keyProperty="id">
INSERT INTO user (name, age) VALUES (#{name}, #{age})
</insert>
</mapper>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.3.1</version>
</dependency>
mybatis-plus:
mapper-locations: classpath:mapper/*.xml
type-aliases-package: com.example.entity
global-config:
db-config:
id-type: auto
logic-delete-field: deleted
logic-delete-value: 1
logic-not-delete-value: 0
configuration:
map-underscore-to-camel-case: true
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
@Data
@TableName("user")
public class User {
@TableId(type = IdType.AUTO)
private Long id;
private String name;
private Integer age;
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
@TableLogic
private Integer deleted;
}
@Mapper
public interface UserMapper extends BaseMapper<User> {
// 继承 BaseMapper 后自动拥有 CRUD 方法
}
public interface UserService extends IService<User> {
}
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
}
@RestController
@RequestMapping("/api/users")
public class UserController {
@Autowired
private UserService userService;
@GetMapping
public List<User> list() {
return userService.list();
}
@GetMapping("/{id}")
public User getById(@PathVariable Long id) {
return userService.getById(id);
}
@GetMapping("/search")
public List<User> search(@RequestParam(required = false) String name,
@RequestParam(required = false) Integer age) {
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
wrapper.like(name != null, User::getName, name)
.eq(age != null, User::getAge, age)
.orderByDesc(User::getCreateTime);
return userService.list(wrapper);
}
@PostMapping
public boolean save(@RequestBody User user) {
return userService.save(user);
}
@PutMapping("/{id}")
public boolean update(@PathVariable Long id, @RequestBody User user) {
user.setId(id);
return userService.updateById(user);
}
@DeleteMapping("/{id}")
public boolean delete(@PathVariable Long id) {
return userService.removeById(id);
}
// 分页查询
@GetMapping("/page")
public Page<User> page(@RequestParam(defaultValue = "1") Integer current,
@RequestParam(defaultValue = "10") Integer size) {
return userService.page(new Page<>(current, size));
}
}
@Configuration
public class MyBatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 分页插件
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
// 乐观锁插件
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return interceptor;
}
}
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
@Transactional
public void transfer(Long fromId, Long toId, BigDecimal amount) {
// 扣款
User from = userMapper.selectById(fromId);
from.setBalance(from.getBalance().subtract(amount));
userMapper.updateById(from);
// 模拟异常
// int i = 1 / 0;
// 收款
User to = userMapper.selectById(toId);
to.setBalance(to.getBalance().add(amount));
userMapper.updateById(to);
}
}
| 属性 | 说明 |
|---|
| propagation | 传播行为 |
| isolation | 隔离级别 |
| timeout | 超时时间 |
| readOnly | 是否只读 |
| rollbackFor | 回滚异常 |
| noRollbackFor | 不回滚异常 |
@Transactional(
propagation = Propagation.REQUIRED,
isolation = Isolation.DEFAULT,
timeout = 30,
readOnly = false,
rollbackFor = Exception.class
)
public void doSomething() {
// ...
}
| 传播行为 | 说明 |
|---|
| REQUIRED | 有事务加入,没有新建(默认) |
| REQUIRES_NEW | 总是新建事务 |
| SUPPORTS | 有事务加入,没有非事务执行 |
| NOT_SUPPORTED | 以非事务执行 |
| MANDATORY | 必须有事务,否则异常 |
| NEVER | 必须没事务,否则异常 |
| NESTED | 嵌套事务 |