spring boot学习笔记
程序员文章站
2022-07-10 18:10:40
...
@SpringBootApplication
@RestController//引入了web
public class TeeApplication {
public static void main(String[] args) {
SpringApplication.run(TeeApplication.class, args);
}
@RequestMapping("/hello")//hello路径
public String hello(){
return "hello spring";
}
}
在terminal中输入,检查项目启动是否成功
//路径访问
curl http://localhost:8080/hello
//健康检查
curl http://localhost:8080/actuator/health
//生成一个可执行的jar包
mvn clean package -Dmaven.test.skip
//执行该jar包
java -jar jar-package-name
配置数据源
@Override
public void run(String... args) throws Exception{
showConnection();
}
private void showConnection() throws SQLException {
log.info(dataSource.toString());
Connection con = dataSource.getConnection();
log.info(con.toString());
con.close();
}
在浏览器中输入,查看配置的beans
http://localhost:8080/actator/beans
数据库查询
private void showdata(){
jdbcTemplate.queryForList("SELECT * FROM FOO").forEach(row->log.info(row.toString()));
}
多数据源配置,排除spring boot的自动配置
//@SpringBootApplication(exclude = {
DataSourceAutoConfiguration.class,
DataSourceTransactionManagerAutoConfiguration.class,
JdbcTemplateAutoConfiguration.class
})
//@Slf4j
public class TeeApplication{
手动配置DataSource
@Bean
@ConfigurationProperties("foo.datasource")
public DataSourceProperties fooDataSourceProperties(){
return new DataSourceProperties();
}
@Bean
public DataSource fooDataSource(){
DataSourceProperties dataSourceProperties = fooDataSourceProperties();
log.info("foo datasource:{}",dataSourceProperties.getUrl());
return dataSourceProperties.initializeDataSourceBuilder().build();
}
@Bean
@Resource
public PlatformTransactionManager fooTxManager(DataSource fooDataSource){
return new DataSourceTransactionManager(fooDataSource);
}
@Bean
@ConfigurationProperties("bar.datasource")
public DataSourceProperties barDataSourceProperties(){
return new DataSourceProperties();
}
@Bean
public DataSource barDataSource(){
DataSourceProperties dataSourceProperties = barDataSourceProperties();
log.info("bar datasource:{}",dataSourceProperties.getUrl());
return dataSourceProperties.initializeDataSourceBuilder().build();
}
@Bean
@Resource
public PlatformTransactionManager barTxManager(DataSource barDataSource){
return new DataSourceTransactionManager(barDataSource);
}
application.properties中写入数据源
foo.datasource.url = jdbc:h2:mem:foo
foo.datasource.username = sa
foo.datasource.password =
bar.datasource.url = jdbc:h2:mem:bar
bar.datasource.username = sa
bar.datasource.password =
数据源连接池
HikariCP
AilibabaDruid
application.properties中配置
spring.datasource.url=jdbc:h2:mem:foo
spring.datasource.username=sa
spring.datasource.password=dz1bVEiHxhLeyHjC3kT779p500fj0kg3a/xpctOC5HwYvlMaR5FPO/0pAvudExqqBkvKzD3bf83M4Y/vQ4nSAQ==
spring.datasource.druid.initialSize=5
spring.datasource.druid.minIdle=5
spring.datasource.druid.maxActive=20
spring.datasource.druid.filters=conn,config,stat,slf4j
spring.datasource..druidconnectionProperties=config.decrypt=true;config.decrypt.key=${public-key}
spring.datasource.druid.filter.config.enabled=true
spring.datasource.druid.testWhileIdle=false
spring.datasource.druid.testOnBorrow=false
spring.datasource.druid.testOnReturn=false
pom文件中排除HikariCP
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
<exclusions>
<exclusion>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-jdbc</artifactId>
</exclusion>
<exclusion>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
</exclusion>
</exclusions>
</dependency>
public void selectForUpdate(){
log.info("select {}",jdbcTemplate.queryForObject("SELECT ID FROM FOO WHERE ID=1 FOR UPDATE",Long.class));
try {
Thread.sleep(200);
}catch (InterruptedException e){
//log.info("exception");
}
}
//主函数中
new Thread(()->fooservice.selectForUpdate()).start();
new Thread(()->fooservice.selectForUpdate()).start();
数据库操作
常用的Bean注解
jdbc操作
数据库操作
Foo对象
import lombok.Builder;
import lombok.Data;
@Data//set get 方法
@Builder// 构造方法
public class Foo {
private Long id;
private String bar;
}
数据操作
@Slf4j
@Repository
public class FooDao {
@Autowired
private JdbcTemplate jdbcTemplate;
@Autowired
private SimpleJdbcInsert simpleJdbcInsert;//jdbc操作的辅助类
public void insertData(){
Arrays.asList("a","b").forEach(bar ->{
jdbcTemplate.update("INSERT INTO FOO (BAR) VALUES (?)",bar);
});
HashMap<String,String> row = new HashMap<>();
row.put("BAR","d");
Number id = simpleJdbcInsert.executeAndReturnKey(row);
log.info("ID of d: {}",id.longValue());
}
public void listData(){
log.info("count: {}",jdbcTemplate.queryForObject("SELECT COUNT(*) FROM FOO",Long.class));
List<String> list = jdbcTemplate.queryForList("SELECT BAR FROM FOO", String.class);
list.forEach(s -> log.info("BAR {}",s));
List<Foo> foolist = jdbcTemplate.query("SELECT * FROM FOO",new RowMapper<Foo>(){
@Override
public Foo mapRow(ResultSet rs, int rowNum) throws SQLException{//rowmap与result连接
return Foo.builder()
.id(rs.getLong(1))
.bar(rs.getString(2))
.build();
}
});
foolist.forEach(f -> log.info("Foo: {}",f));
}
}
批处理方法
jdbcTemplate.batchUpdate("INSERT INTO FOO (BAR) VALUES (?)",
new BatchPreparedStatementSetter() {
@Override
public void setValues(PreparedStatement preparedStatement, int i) throws SQLException {
preparedStatement.setString(1,"b-"+i);
}
@Override
public int getBatchSize() {//批处理次数
return 2;
}
}
);
List<Foo> list = new ArrayList<>();
list.add(Foo.builder().id(100L).bar("b-100").build());
list.add(Foo.builder().id(101L).bar("b-101").build());
namedParameterJdbcTemplate
.batchUpdate("INSERT INTO FOO (ID,BAR) VALUES (:id,:bar)",
SqlParameterSourceUtils.createBatch(list));
事务抽象
编程式事务
public void run(String... args) throws Exception{
log.info("count before transaction {}",getCount());
transactionTemplate.execute(new TransactionCallbackWithoutResult(){
@Override
protected void doInTransactionWithoutResult(TransactionStatus transactionStatus){
jdbcTemplate.execute("INSERT INTO FOO (ID,BAR) VALUES (4,'AA1')");
log.info("count in transaction {}",getCount());
transactionStatus.setRollbackOnly();
}
});
log.info("count after transaction {}",getCount());
}
声明式事务
测试类
@Autowired
private JdbcTemplate jdbcTemplate;
//@Autowired
//private FooService fooService;
@Override
@Transactional
public void insertRecord(){
jdbcTemplate.execute("INSERT INTO FOO (BAR) VALUES ('aaa1')");
}
@Override
@Transactional(rollbackFor = UnexpectedRollbackException.class)
public void insertThenRollback() throws UnexpectedRollbackException{
jdbcTemplate.execute("INSERT INTO FOO (BAR) VALUES ('bbb1')");
throw new UnexpectedRollbackException("sss");
}
@Override
public void invokeInsertThenRollback() throws UnexpectedRollbackException{
//insertThenRollback();//没有aop代理增强,没有事务
((FooService) (AopContext.currentProxy())).insertThenRollback();//当前类的代理对象
//fooService.insertThenRollback();//注入实例
}
测试代码
public void run(String... args) throws Exception{
fooservice.insertRecord();
log.info("aaa1 {}",
jdbcTemplate.queryForList("SELECT COUNT(*) FROM FOO WHERE BAR='aaa1'",long.class));
try{
fooservice.insertThenRollback();
}catch(Exception e) {
log.info("bbb1 {}",
jdbcTemplate.queryForList("SELECT COUNT(*) FROM FOO WHERE BAR='bbb1'",long.class));
}
try{
fooservice.invokeInsertThenRollback();
}catch(Exception e) {
log.info("bbb1 {}",
jdbcTemplate.queryForList("SELECT COUNT(*) FROM FOO WHERE BAR='bbb1'",long.class));
}
}
@Override
@Transactional(rollbackFor = UnexpectedRollbackException.class,propagation = Propagation.REQUIRES_NEW)
//@Transactional(rollbackFor = UnexpectedRollbackException.class,propagation = Propagation.NESTED)
public void insertThenRollback() throws UnexpectedRollbackException{
jdbcTemplate.execute("INSERT INTO FOO (BAR) VALUES ('bbb1')");
throw new UnexpectedRollbackException("sss");
}
@Override
public void invokeInsertThenRollback() throws UnexpectedRollbackException{
//insertThenRollback();//没有aop代理增强,没有事务
((FooService) (AopContext.currentProxy())).insertThenRollback();//当前类的代理对象
//fooService.insertThenRollback();//注入实例
}
JDBC异常
测试类
@RunWith(SpringRunner.class)
@SpringBootTest
public class TeeApplicationTests {
@Autowired
private JdbcTemplate jdbcTemplate;
@Test(expected = CustomDuplicatedKeyException.class)
public void testThrowingCustomException() {
jdbcTemplate.execute("INSERT INTO FOO (ID,BAR) VALUES (3,'A')");
jdbcTemplate.execute("INSERT INTO FOO (ID,BAR) VALUES (3,'B')");
}
}
pom文件错误码配置
<property name="customTranslations">
<bean class="org.springframework.jdbc.support.CustomSQLErrorCodesTranslation">
<property name="errorCodes" value="23001,23505"/>
<property name="exceptionClass" value="springhtwo.tee.CustomDuplicatedKeyException"/>
</bean>
</property>
错误类
public class CustomDuplicatedKeyException extends DuplicateKeyException {
public CustomDuplicatedKeyException(String msg){
super(msg);
}
public CustomDuplicatedKeyException(String msg,Throwable cause){
super(msg,cause);
}
}
多数据库、分库分表、读写分离