Chapter7: SpringBoot与数据访问
尚硅谷SpringBoot顶尖教程
1. JDBC
1.1 依赖及配置
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope><version>8.0.12</version>
</dependency>
全局配置文件配置数据源基础参数
## 数据源
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.url=jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
数据源的配置属性封装在DataSourceProperties
里面,支持在全局配置文件配置spring.datasource.xxx
的属性。
@ConfigurationProperties(prefix = "spring.datasource")
public class DataSourcePropertiesimplements BeanClassLoaderAware, EnvironmentAware, InitializingBean {private Class<? extends DataSource> type;private String driverClassName;private String url;private String username;private String password;// ...// 构建数据源public DataSourceBuilder initializeDataSourceBuilder() {return DataSourceBuilder.create(getClassLoader()).type(getType()).driverClassName(determineDriverClassName()).url(determineUrl()).username(determineUsername()).password(determinePassword());}// ...
}
1.2 数据源自动配置原理
数据源的自动配置查看自动配置类DataSourceAutoConfiguration
, 导入了DataSourceConfiguration数据源配置类, 数据源实例化的相关配置都在这个类中;
@Configuration
@ConditionalOnClass({ DataSource.class, EmbeddedDatabaseType.class })
@EnableConfigurationProperties(DataSourceProperties.class)
@Import({ Registrar.class, DataSourcePoolMetadataProvidersConfiguration.class })
public class DataSourceAutoConfiguration {// ...@Configuration@Conditional(PooledDataSourceCondition.class)@ConditionalOnMissingBean({ DataSource.class, XADataSource.class })@Import({ DataSourceConfiguration.Tomcat.class, DataSourceConfiguration.Hikari.class,DataSourceConfiguration.Dbcp.class, DataSourceConfiguration.Dbcp2.class,DataSourceConfiguration.Generic.class })@SuppressWarnings("deprecation")protected static class PooledDataSourceConfiguration {}// ...
}
上面的自动配置类中导入了配置类DataSourceConfiguration
, web模块自动导入了spring-boot-starter-tomcat, 默认使用org.apache.tomcat.jdbc.pool.DataSource
作为数据源, 可以使用spring.datasource.type指定数据源类型。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-e7uqYZUV-1686468913853)(SpringBoot学习笔记-atguigu.assets/1686146719144.png)]
abstract class DataSourceConfiguration {@SuppressWarnings("unchecked")protected <T> T createDataSource(DataSourceProperties properties,Class<? extends DataSource> type) {// 根据导入的数据源类型type,实例化数据源return (T) properties.initializeDataSourceBuilder().type(type).build();}/*** Tomcat Pool DataSource configuration.*/@ConditionalOnClass(org.apache.tomcat.jdbc.pool.DataSource.class)@ConditionalOnProperty(name = "spring.datasource.type", havingValue = "org.apache.tomcat.jdbc.pool.DataSource", matchIfMissing = true)static class Tomcat extends DataSourceConfiguration {@Bean@ConfigurationProperties(prefix = "spring.datasource.tomcat")public org.apache.tomcat.jdbc.pool.DataSource dataSource(DataSourceProperties properties) {// 创建数据库连接池org.apache.tomcat.jdbc.pool.DataSource dataSource = createDataSource(properties, org.apache.tomcat.jdbc.pool.DataSource.class);DatabaseDriver databaseDriver = DatabaseDriver.fromJdbcUrl(properties.determineUrl());String validationQuery = databaseDriver.getValidationQuery();if (validationQuery != null) {dataSource.setTestOnBorrow(true);dataSource.setValidationQuery(validationQuery);}return dataSource;}}/*** Hikari DataSource configuration.*/@ConditionalOnClass(HikariDataSource.class)@ConditionalOnProperty(name = "spring.datasource.type", havingValue = "com.zaxxer.hikari.HikariDataSource", matchIfMissing = true)static class Hikari extends DataSourceConfiguration {@Bean@ConfigurationProperties(prefix = "spring.datasource.hikari")public HikariDataSource dataSource(DataSourceProperties properties) {return createDataSource(properties, HikariDataSource.class);}}/*** DBCP DataSource configuration.** @deprecated as of 1.5 in favor of DBCP2*/@ConditionalOnClass(org.apache.commons.dbcp.BasicDataSource.class)@ConditionalOnProperty(name = "spring.datasource.type", havingValue = "org.apache.commons.dbcp.BasicDataSource", matchIfMissing = true)@Deprecatedstatic class Dbcp extends DataSourceConfiguration {@Bean@ConfigurationProperties(prefix = "spring.datasource.dbcp")public org.apache.commons.dbcp.BasicDataSource dataSource(DataSourceProperties properties) {org.apache.commons.dbcp.BasicDataSource dataSource = createDataSource(properties, org.apache.commons.dbcp.BasicDataSource.class);DatabaseDriver databaseDriver = DatabaseDriver.fromJdbcUrl(properties.determineUrl());String validationQuery = databaseDriver.getValidationQuery();if (validationQuery != null) {dataSource.setTestOnBorrow(true);dataSource.setValidationQuery(validationQuery);}return dataSource;}}/*** DBCP DataSource configuration.*/@ConditionalOnClass(org.apache.commons.dbcp2.BasicDataSource.class)@ConditionalOnProperty(name = "spring.datasource.type", havingValue = "org.apache.commons.dbcp2.BasicDataSource", matchIfMissing = true)static class Dbcp2 extends DataSourceConfiguration {@Bean@ConfigurationProperties(prefix = "spring.datasource.dbcp2")public org.apache.commons.dbcp2.BasicDataSource dataSource(DataSourceProperties properties) {return createDataSource(properties,org.apache.commons.dbcp2.BasicDataSource.class);}}/*** Generic DataSource configuration.*/@ConditionalOnMissingBean(DataSource.class)// 使用spring.datasource.type指定数据源类型@ConditionalOnProperty(name = "spring.datasource.type")static class Generic {@Beanpublic DataSource dataSource(DataSourceProperties properties) {return properties.initializeDataSourceBuilder().build();}}
}
DataSourceBuilder#build()方法实例化数据源, 默认支持的数据源类型有:org.apache.tomcat.jdbc.pool.DataSource
org.apache.commons.dbcp.BasicDataSource
org.apache.commons.dbcp2.BasicDataSource
com.zaxxer.hikari.HikariDataSource
public class DataSourceBuilder {private static final String[] DATA_SOURCE_TYPE_NAMES = new String[] {"org.apache.tomcat.jdbc.pool.DataSource","com.zaxxer.hikari.HikariDataSource","org.apache.commons.dbcp.BasicDataSource", // deprecated 过时了"org.apache.commons.dbcp2.BasicDataSource" };private Class<? extends DataSource> type;// ...public DataSource build() {// 返回的就是当前builder的数据源类型type//type出处: DataSourceProperties#initializeDataSourceBuilder().type(type)Class<? extends DataSource> type = getType();DataSource result = BeanUtils.instantiate(type);maybeGetDriverClassName();bind(result);return result;}public DataSourceBuilder type(Class<? extends DataSource> type) {this.type = type;return this;}// ...
}
1.3 数据源数据初始化
数据源自动配置类中实例化DataSourceInitializer,数据源的一些初始化工作在这里面完成。
@Configuration
@ConditionalOnClass({ DataSource.class, EmbeddedDatabaseType.class })
@EnableConfigurationProperties(DataSourceProperties.class)
@Import({ Registrar.class, DataSourcePoolMetadataProvidersConfiguration.class })
public class DataSourceAutoConfiguration {// ...@Bean@ConditionalOnMissingBeanpublic DataSourceInitializer dataSourceInitializer(DataSourceProperties properties,ApplicationContext applicationContext) {return new DataSourceInitializer(properties, applicationContext);}// ...
}
DataSourceInitializer实现了ApplicationListener接口,重写onApplicationEvent方法, 里面会调用runDataScripts()方法执行指定sql文件中插入数据的sql语句。
class DataSourceInitializer implements ApplicationListener<DataSourceInitializedEvent> {DataSourceInitializer(DataSourceProperties properties,ApplicationContext applicationContext) {this.properties = properties;this.applicationContext = applicationContext;}// 重写ApplicationListener#onApplicationEvent方法@Overridepublic void onApplicationEvent(DataSourceInitializedEvent event) {if (!this.properties.isInitialize()) {logger.debug("Initialization disabled (not running data scripts)");return;}// NOTE the event can happen more than once and// the event datasource is not used hereif (!this.initialized) {// 执行数据库脚本runDataScripts();this.initialized = true;}}// 执行数据库脚本private void runDataScripts() {// 获取spring.datasource.data配置的sql脚本List<Resource> scripts = getScripts("spring.datasource.data",this.properties.getData(), "data");String username = this.properties.getDataUsername();String password = this.properties.getDataPassword();// 运行脚本runScripts(scripts, username, password);}// 运行脚本private void runScripts(List<Resource> resources, String username, String password) {if (resources.isEmpty()) {return;}ResourceDatabasePopulator populator = new ResourceDatabasePopulator();populator.setContinueOnError(this.properties.isContinueOnError());populator.setSeparator(this.properties.getSeparator());if (this.properties.getSqlScriptEncoding() != null) {populator.setSqlScriptEncoding(this.properties.getSqlScriptEncoding().name());}for (Resource resource : resources) {populator.addScript(resource);}DataSource dataSource = this.dataSource;if (StringUtils.hasText(username) && StringUtils.hasText(password)) {dataSource = DataSourceBuilder.create(this.properties.getClassLoader()).driverClassName(this.properties.determineDriverClassName()).url(this.properties.determineUrl()).username(username).password(password).build();}// 获取数据库连接,执行sql语句DatabasePopulatorUtils.execute(populator, dataSource);}
}
DataSourceInitializer中的init方法使用@PostConstruct
注解声明,在实例化完成后会执行该方法进行初始化工作,里面通过runSchemaScripts() 运行sql脚本执行了创建表的操作。
class DataSourceInitializer implements ApplicationListener<DataSourceInitializedEvent> {DataSourceInitializer(DataSourceProperties properties,ApplicationContext applicationContext) {this.properties = properties;this.applicationContext = applicationContext;}// 初始化@PostConstructpublic void init() {if (!this.properties.isInitialize()) {logger.debug("Initialization disabled (not running DDL scripts)");return;}if (this.applicationContext.getBeanNamesForType(DataSource.class, false,false).length > 0) {this.dataSource = this.applicationContext.getBean(DataSource.class);}if (this.dataSource == null) {logger.debug("No DataSource found so not initializing");return;}// 运行schema脚本runSchemaScripts();}// 运行schema脚本private void runSchemaScripts() {// 获取spring.datasource.schema配置的schema脚本List<Resource> scripts = getScripts("spring.datasource.schema",this.properties.getSchema(), "schema");if (!scripts.isEmpty()) {String username = this.properties.getSchemaUsername();String password = this.properties.getSchemaPassword();runScripts(scripts, username, password);try {this.applicationContext.publishEvent(new DataSourceInitializedEvent(this.dataSource));// The listener might not be registered yet, so don't rely on it.if (!this.initialized) {runDataScripts();this.initialized = true;}}catch (IllegalStateException ex) {logger.warn("Could not send event to complete DataSource initialization ("+ ex.getMessage() + ")");}}}
}
上面运行的两个脚本都是从DataSourceInitializer#getScripts方法中查找得到的,支持执行类路径下指定的脚本文件,如果没有指定就执行默认的脚本。
spring.datasource.platform配置xxx,那么脚本文件默认命名为schema-xxx.sql 或 data-xxx.sql ;
spring.datasource.platform没有配置,脚本文件默认为schema.sql或schema-all.sql, 可以使用schema属性指定加载sql的位置
// resources=spring.datasource.data or spring.datasource.schema指定的sql脚本
// fallback=data or schame
private List<Resource> getScripts(String propertyName, List<String> resources,String fallback) {if (resources != null) {// 如果spring.datasource.data 或 spring.datasource.schema有配置指定的脚本,就执行此处查找脚本资源。return getResources(propertyName, resources, true);}// 如果spring.datasource.data 或 spring.datasource.schema没有配置,就查找类路径下默认的脚本// platform=allString platform = this.properties.getPlatform();List<String> fallbackResources = new ArrayList<String>();// 默认脚本 schema-all.sql or data-all.sql fallbackResources.add("classpath*:" + fallback + "-" + platform + ".sql");// 默认脚本 schema.sql or data.sqlfallbackResources.add("classpath*:" + fallback + ".sql");return getResources(propertyName, fallbackResources, false);
}
全局配置文件配置执行的脚本, 建表脚本teacher.sql和初始化数据脚本initTeacher.sql
# 初始化执行sql
#spring.datasource.platform=xxx
spring.datasource.schema=classpath*:ddlSql/teacher.sql
spring.datasource.data=classpath*:ddlSql/initTeacher.sql
teacher.sql脚本内容
CREATE TABLE `teacher` (`tid` int(11) NOT NULL AUTO_INCREMENT,`tname` varchar(50) DEFAULT NULL,PRIMARY KEY (`tid`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
initTeacher.sql脚本内容
insert into teacher(tid,tname) values (null,'王老师'),(null,'crysw老师');
启动应用,查看启动日志。
[2023-06-07 23:01:36.036] [com.alibaba.druid.pool.DruidDataSource] [main] [923] [INFO ] {dataSource-1} inited
[2023-06-07 23:01:36.036] [org.springframework.jdbc.datasource.init.ScriptUtils] [main]
// 运行sql脚本teacher.sql
[441] [INFO ] Executing SQL script from URL [file:/D:/Develops/IdeaProjects/study-spring-boot/spring-boot-atguigu/spring-boot-02-config/target/classes/ddlSql/teacher.sql]
[2023-06-07 23:01:36.036] [org.springframework.jdbc.datasource.init.ScriptUtils] [main]
// 创建表teacher
[473] [DEBUG] 0 returned as update count for SQL: CREATE TABLE `teacher` ( `tid` int(11) NOT NULL AUTO_INCREMENT, `tname` varchar(50) DEFAULT NULL, PRIMARY KEY (`tid`) ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8
[2023-06-07 23:01:36.036] [org.springframework.jdbc.datasource.init.ScriptUtils] [main] [476] [DEBUG] SQLWarning ignored: SQL state 'HY000', error code '1681', message [Integer display width is deprecated and will be removed in a future release.]
[2023-06-07 23:01:36.036] [org.springframework.jdbc.datasource.init.ScriptUtils] [main] [476] [DEBUG] SQLWarning ignored: SQL state 'HY000', error code '3719', message ['utf8' is currently an alias for the character set UTF8MB3, but will be an alias for UTF8MB4 in a future release. Please consider using UTF8MB4 in order to be unambiguous.]
[2023-06-07 23:01:36.036] [org.springframework.jdbc.datasource.init.ScriptUtils] [main] [507] [INFO ] Executed SQL script from URL [file:/D:/Develops/IdeaProjects/study-spring-boot/spring-boot-atguigu/spring-boot-02-config/target/classes/ddlSql/teacher.sql] in 28 ms.
[2023-06-07 23:01:36.036] [org.springframework.jdbc.datasource.DataSourceUtils] [main] [329] [DEBUG] Returning JDBC Connection to DataSource
[2023-06-07 23:01:36.036] [org.springframework.jdbc.datasource.DataSourceUtils] [main] [110] [DEBUG] Fetching JDBC Connection from DataSource
// 运行sql脚本initTeacher.sql
[2023-06-07 23:01:36.036] [org.springframework.jdbc.datasource.init.ScriptUtils] [main] [441] [INFO ] Executing SQL script from URL [file:/D:/Develops/IdeaProjects/study-spring-boot/spring-boot-atguigu/spring-boot-02-config/target/classes/ddlSql/initTeacher.sql]
[2023-06-07 23:01:36.036] [org.springframework.jdbc.datasource.init.ScriptUtils] [main]
// 插入初始化数据到teacher表
[473] [DEBUG] 2 returned as update count for SQL: insert into teacher(tid,tname) values (null,'王老师'),(null,'crysw老师')
[2023-06-07 23:01:36.036] [org.springframework.jdbc.datasource.init.ScriptUtils] [main] [507] [INFO ] Executed SQL script from URL [file:/D:/Develops/IdeaProjects/study-spring-boot/spring-boot-atguigu/spring-boot-02-config/target/classes/ddlSql/initTeacher.sql] in 4 ms.
1.4 数据模板
spring提供了数据库模板JdbcTemplate
给我们来操作数据库, 自动配置类JdbcTemplateAutoConfiguration
提供了jdbcTemplate组件。
@Configuration
@ConditionalOnClass({ DataSource.class, JdbcTemplate.class })
@ConditionalOnSingleCandidate(DataSource.class)
@AutoConfigureAfter(DataSourceAutoConfiguration.class)
public class JdbcTemplateAutoConfiguration {private final DataSource dataSource;public JdbcTemplateAutoConfiguration(DataSource dataSource) {this.dataSource = dataSource;}@Bean@Primary@ConditionalOnMissingBean(JdbcOperations.class)public JdbcTemplate jdbcTemplate() {return new JdbcTemplate(this.dataSource);}
}
编写controller,使用数据模板jdbcTemplate操作数据库测试。
@Controller
public class HelloController {Logger logger = LoggerFactory.getLogger(this.getClass());@Autowiredprivate JdbcTemplate jdbcTemplate;@ResponseBody@GetMapping("/queryTeacher")public Map<String, Object> queryTeacher() {List<Map<String, Object>> teachers = jdbcTemplate.queryForList("select * from teacher");return teachers.get(0);}
}
访问 http://localhost:8082/boot1/queryTeacher
, 返回结果:
{"tid": 1,"tname": "王老师"
}
2. 整合Druid数据源
2.1 依赖及配置
导入依赖
<dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.1.8</version>
</dependency>
全局配置文件指定数据库连接池类型(指定数据源)
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
编写配置类,整合Druid数据源
@Configuration
public class DruidConfig {@ConfigurationProperties(prefix = "spring.datasource")@Beanpublic DataSource druidDataSource() {return new DruidDataSource();}// 配置Druid监控// 1. 配置一个管理后台的Servlet@Beanpublic ServletRegistrationBean statViewServlet() {ServletRegistrationBean bean = new ServletRegistrationBean(new StatViewServlet(), "/druid/*");Map<String, String> initParams = new HashMap<>();// 设置Druid监控登录用户和密码initParams.put("loginUsername", "admin");initParams.put("loginPassword", "123456");initParams.put("allow", ""); // 默认允许所有initParams.put("deny", "192.168.1.103"); // 拒绝该主机访问bean.setInitParameters(initParams);return bean;}// 2. 配置一个web监控的filter@Beanpublic FilterRegistrationBean webStatFilter() {FilterRegistrationBean filterBean = new FilterRegistrationBean();filterBean.setFilter(new WebStatFilter());Map<String, String> filterParams = new HashMap<>();filterParams.put("exclusions", "*.js,*.css,/druid/*");filterBean.setInitParameters(filterParams);filterBean.setUrlPatterns(Arrays.asList("/*"));return filterBean;}
}
2.2 druid监控
启动应用,访问 http://localhost:8082/boot1/druid
进入Druid监控登录界面
访问查询请求 , http://localhost:8082/boot1/queryTeacher
查看监控。
2.3 druid自动配置类
上面是自定义的数据源配置类,提供了DruidDataSource实例。还可以使用druid官方提供的启动器提供了自动配置类 DruidDataSourceAutoConfigure
, 不用自己编写配置类。
<dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.2.3</version>
</dependency>
自动配置类 DruidDataSourceAutoConfigure
@Configuration
@ConditionalOnClass(DruidDataSource.class)
@AutoConfigureBefore(DataSourceAutoConfiguration.class)
@EnableConfigurationProperties({DruidStatProperties.class, DataSourceProperties.class})
@Import({DruidSpringAopConfiguration.class,// 监控的servlet配置DruidStatViewServletConfiguration.class,// 监控的filter配置DruidWebStatFilterConfiguration.class,// DruidFilterConfiguration.class})
public class DruidDataSourceAutoConfigure {private static final Logger LOGGER = LoggerFactory.getLogger(DruidDataSourceAutoConfigure.class);@Bean(initMethod = "init")@ConditionalOnMissingBeanpublic DataSource dataSource() {LOGGER.info("Init DruidDataSource");return new DruidDataSourceWrapper();}
}
druid的监控servlet配置中,需要指定监控界面开启为true,才能访问监控界面;
@ConditionalOnWebApplication
@ConditionalOnProperty(name = "spring.datasource.druid.stat-view-servlet.enabled", havingValue = "true")
public class DruidStatViewServletConfiguration {//...
}
druid监控url请求,需要配置开启webFilter,才能实现请求的拦截监控。
@ConditionalOnWebApplication
@ConditionalOnProperty(name = "spring.datasource.druid.web-stat-filter.enabled", havingValue = "true")
public class DruidWebStatFilterConfiguration {//...
}
在全局配置文件中配置druid监控的相关参数
# 开启druid监控
spring.datasource.druid.stat-view-servlet.enabled=true
spring.datasource.druid.stat-view-servlet.login-username=admin
spring.datasource.druid.stat-view-servlet.login-password=12345678
spring.datasource.druid.stat-view-servlet.reset-enable=false
spring.datasource.druid.stat-view-servlet.url-pattern=/druid/*
spring.datasource.druid.web-stat-filter.enabled=true
spring.datasource.druid.web-stat-filter.url-pattern=/*
spring.datasource.druid.web-stat-filter.exclusions=*.js,*.css,/druid/*
注释掉自定义的数据源配置类, 再次启动应用访问 http://localhost:8082/boot1/druid
也成功进入Druid监控登录界面。随机触发几个请求,也可以实现监控。
druid监控博文学习
Spring系列之集成Druid连接池及监控配置 - 掘金
SpringBoot开启Druid监控统计功能(SQL监控、慢SQL记录、Spring监控、去广告)
3. 整合Mybatis
3.1 依赖管理
<dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>1.3.5</version>
</dependency>
依赖关系图
3.2 mybatis核心配置及参数配置
在类路径下添加mybatis核心配置文件mybatis-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><!-- 全局配置参数,需要时再设置 --><settings><!-- 打开延迟加载开关 --><setting name="lazyLoadingEnabled" value="true"/><!-- 将积极加载改为消极加载,即按需加载 --><setting name="aggressiveLazyLoading" value="false"/><!-- 开启二级缓存 --><setting name="cacheEnabled" value="true"/><!--开启驼峰映射--><setting name="mapUnderscoreToCamelCase" value="true"/></settings>
</configuration>
在全局配置文件application.properties中配置mybatis参数
## mybatis配置
mybatis.config-location=classpath:mybatis/mybatis-config.xml
mybatis.mapper-locations=classpath:mybatis/mapper/*.xml
mybatis.type-aliases-package=com.aiguigu.springboot02config.entities
3.3 mapper接口开发
注解版mapper接口,不需要mapper映射xml文件,sql直接写在接口方法上。
// 指定这是一个操作数据库的mapper接口
//@Mapper // 注释掉后在启动类上加@MapperScan(value = {"com.aiguigu.spriingboot02config.mapper"})
public interface DepartmentMapper {@Select("select * from department where id=#{id}")public Department getDeptById(Integer id);@Delete("delete from department where id=#{id}")public int deleteDeptById(Integer id);@Options(useGeneratedKeys = true, keyProperty = "id")@Insert("insert into department(department_name) values(#{departmentName})")public int insertDept(Department department);@Update("update department set department_name=#{departmentName} where id=#{id}")public int updateDept(Department department);
}
mapper接口+mapper映射xml文件的方式
// @Mapper 或 @MapperScan将接口扫描装配到容器中
public interface EmployeeMapper {Employee2 getEmpById(Integer id);void insertEmp(Employee2 employee);
}
EmployeeMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.aiguigu.springboot02config.mapper.EmployeeMapper"><select id="getEmpById" resultType="com.aiguigu.springboot02config.entities.Employee2">select * from employee where id = #{id}</select><insert id="insertEmp" useGeneratedKeys="true" keyProperty="id" keyColumn="id">insert into employee(lastName,email,gender,d_id)values(#{lastName},#{email},#{gender},#{d_id})</insert>
</mapper>
4. 整合JPA
4.1 Spring Data简介
Spring Data项目简化了基于Spring框架应用的数据访问技术,包括非关系型数据库、Map-Reduce框架、云数据服务等,另外也包含对关系数据库的访问支持。
Spring Data为我们提供使用统一的API来对数据访问层进行操作;这主要是Spring Data Commons项目来实现的。Spring Data Commons让我们在使用关系型或非关系型数据访问技术时都基于Spring提供的统一标准,标准包含了CRUD(创建、获取、更新、删除)、查询、排序和分页的相关操作。
Repository<T ID extends Serializable> 统一的Repository接口 ;
RevisionRepository<T, ID extends Serializable, N extends Number & Comparable<N>> 基于乐观锁机制;
CrudRepository<T, ID extends Serializable> 基本的CRUD操作;
PagingAndSortingRepository<T, ID extends Serializable> 基本CRUD及分页;
xxxTemplate 数据访问模板类 (JdbcTemplate, RedisTemplate);
JPA与Spring Data
- JpaRepository 基本功能, 编写接口继承JpaRepository, 就有了crud及分页等基本功能;
- 定义符合规范的方法命名, 在接口中只需要声明符合规范的方法, 就拥有对应的功能;
-
@Query 自定义查询, 定制查询SQL;
整合框架图
4.2 使用Spring Data JPA
导入依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
编写一个实体类(bean)和数据库表进行映射, 并且配置好映射关系。
// 使用JPA注解配置映射关系
@Entity // 标识这是一个实体类,和数据库表映射
@Table(name = "tb_user") // 指定映射的库表, 如果省略默认表名就是user
public class User {@Id // 主键@GeneratedValue(strategy = GenerationType.IDENTITY) // 自增主键private Integer id;@Column(name = "last_name", length = 50)private String lastName;@Column // 省略默认列名就是属性名private String email;public User() {}public User(Integer id, String lastName, String email) {this.id = id;this.lastName = lastName;this.email = email;}// setXXX and getXXX
}
编写一个Dao接口操作, 实体类对应的数据库表(Repository)。
// 继承 JpaRepository 完成对数据库表的操作
public interface UserRepository extends JpaRepository<User, Integer> {
}
基本的配置
## 更新或者创建数据库表结构
spring.jpa.hibernate.ddl-auto=update
## 控制台显示sql
spring.jpa.show-sql=true
编写controller使用repository
@RestController
public class UserController {@AutowiredUserRepository userRepository;@GetMapping("/user/{id}")public User getUser(@PathVariable("id") Integer id) {User user = userRepository.findOne(id);return user;}@GetMapping("/user")public User insertUser(User user) {User _user = userRepository.save(user);return _user; // 封装了自增主键id返回}
}
测试 http://localhost:8082/boot1/user?lastName=admin&email=admin@qq.com
访问 http://localhost:8082/boot1/user/1
相关文章:

Chapter7: SpringBoot与数据访问
尚硅谷SpringBoot顶尖教程 1. JDBC 1.1 依赖及配置 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <dependency><groupId>mysql</groupId…...
【Sqlite3】maraidb和sqlite3部分命令操作区别
maraidb和sqlite3部分命令操作区别记录 1.安装sqlite3 在实现我的视频点播系统项目时,我尝试封装了两种数据库的调用逻辑 mysql(maraidb)sqlite3 这里封装sqlite3的原因是,sqlite3主要针对的就是嵌入式数据库,其性能…...

Linux中新建用户使用sudo问题
文章目录 sudo问题 sudo问题 sudo:权限提示指令,当使用sudo这条指令时,会将普通用户的权限提升为root权限 但是在命令行新建用户,这个用户使用sudo指令对一条指令提权是用不了的 这个用户没有在sudoers file这个文件中ÿ…...

Sentinel源码分析-ProceesorSlotChain调用链及树状资源节点
Sentinel 实现流控,隔离,降级等功能,本质要做两件事: 数据统计: 统计某个资源的访问数据(QPS,RT(响应时间),异常比例)等信息规则判断: 判断流控规…...

springboot 连接 kafka集群(kafka版本 2.13-3.4.0)
springboot 连接 kafka集群 一、环境搭建1.1 springboot 环境1.2 kafka 依赖 二、 kafka 配置类2.1 发布者2.1.1 配置2.1.2 构建发布者类2.1.3 发布消息 2.2 消费者2.2.1 配置2.2.2 构建消费者类2.2.3 进行消息消费 一、环境搭建 1.1 springboot 环境 JDK 11 Maven 3.8.x spr…...

Nacos配置中心使用(Spring Cloud版)
目标 向项目中集成Nacos配置。原项目是一个SpringBoot项目。这里假设我们无法修改原有项目的SpringBoot版本。 注意 在不动SpringBoot版本的前提下,根据SpringBoot的版本,确定Spring Cloud和Nacos版本。Nacos版本其实就是Spring Cloud Alibaba版本。在…...

STM32F407硬件I2C实现MPU6050通讯(CUBEIDE)
STM32F407硬件I2C实现MPU6050通讯 文章目录 STM32F407硬件I2C实现MPU6050通讯cubeide设置写操作与读操作函数实现复位,读取温度,角度等函数封装mpu6050.cmpu6050.h代码分析 DMP移植1.修改头文件路径为自己的头文件路径2.修改I2C读写函数为自己mcu平台的读…...

HTML5 语义元素(一)页面结构
本篇主要介绍HTML5增加的语义元素中关于页面结构方面的,包含: <article>、<aside>、<figure>、<figcaption>、<footer>、<header>、<main>、<nav>、<section>等元素。 目录 1. 语义元素介绍 1.…...

嵌套滚动实践:onInterceptTouchEvent与NestedScrolling【实用为准】
嵌套滚动:内外两层均可滚动,比如上半部分是一个有限的列表,下半部分是WebView,在内层上半部分展示到底的时候,外部父布局整体滚动内部View,将底部WevView拉起来,滚动到顶部之后再将滚动交给内部…...

Redis入门 - 5种基本数据类型
原文首更地址,阅读效果更佳! Redis入门 - 5种基本数据类型 | CoderMast编程桅杆https://www.codermast.com/database/redis/five-base-datatype.html 说明 在我们平常的业务中基本只会使用到Redis的基本数据类型(String、List、Hash、Set、…...

mybatis-plus用法(一)
MyBatis-plus 是一款 Mybatis 增强工具,用于简化开发,提高效率。下文使用缩写 mp来简化表示 MyBatis-plus,本文主要介绍 mp 整合 Spring Boot 的使用。 (5条消息) mybatis-plus用法(二)_渣娃工程师的博客-CSDN博客 1…...
源码安装包管理
1. 源码包基本概述 在linux环境下面安装源码包是比较常见的, 早期运维管理工作中,大部分软件都是通过源码安装的。那么安装一个源码包,是需要我们自己把源代码编译成二进制的可执行文件。 源码包的编译用到了linux系统里的编译器,通常源码包…...
Vue|获取表单数据
在Vue中获取表单数据有多种方式,具体取决于你使用的是哪种表单元素和你的需求。 1. 单个表单元素: 如果你只需要获取单个表单元素的值,可以使用v-model指令将表单元素的值绑定到Vue实例的一个属性上。例如: <input type&quo…...

微信小程序入门学习02-TDesign中的自定义组件
目录 1 显示文本2 自定义组件3 变量定义4 值绑定总结 我们上一篇讲解了TDesign模板的基本用法,如何开始阅读模板。本篇我们讲解一下自定义组件的用法。 1 显示文本 官方模板在顶部除了显示图片外,还显示了一段文字介绍。文字是嵌套在容器组件里…...

【linux kernel】linux media子系统分析之media控制器设备
文章目录 一、抽象媒体设备模型二、媒体设备三、Entity四、Interfaces五、Pad六、Link七、Media图遍历八、使用计数和电源处理九、link设置十、Pipeline和Media流十一、链接验证十二、媒体控制器设备的分配器API 本文基于linux内核 4.19.4,抽象媒体设备模型框架的相…...

Scala--03
第6章 面向对象 Scala 的面向对象思想和Java 的面向对象思想和概念是一致的。 Scala 中语法和 Java 不同,补充了更多的功能。 6.1类和对象详解 6.1.1组成结构 构造函数: 在创建对象的时候给属性赋值 成员变量: 成员方法(函数) 局部变量 代码块 6.1.2构造器…...
【MongoDB】--MongoDB高级功能
目录 一、前言二、聚合管道aggregate1、示例说明2、具体代码实现一、前言 这里主要记录mongodb一些高级功能使用,如聚合。 二、聚合管道aggregate 聚合操作将来自多个文档的值组合在一起,并且可以对分组数据执行各种操作以返回单个结果,主要用于处理数据(诸如统计平均值,…...
C# new与malloc
目录 C# new与malloc C# new与malloc的区别 C# new关键字底层做的操作 C# new与malloc new关键字: new关键字在C#中用于实例化对象,并为其分配内存。它是面向对象编程的基本操作之一。使用new关键字可以在托管堆上分配内存,同时调用对象的构…...

微软MFC技术简明介绍
我是荔园微风,作为一名在IT界整整25年的老兵,今天来看一下微软MFC技术简明介绍 Visual C 与 MFC 微软公司于1992年上半年推出了C/C 7.0 产品时初次向世人介绍了MFC 1.0,这个产品包含了20,000行C原始代码,60个以上的Windows相关类…...

汽车电子Autosar之车载以太网
前言 近些年来,随着为了让汽车更加安全、智能、环保等,一系列的高级辅助驾驶功能喷涌而出。未来满足这些需求,就对传统的电子电器架构带来了严峻的考验,需要越来越多的电子部件参与信息交互,导致对网络传输速率&#x…...
KubeSphere 容器平台高可用:环境搭建与可视化操作指南
Linux_k8s篇 欢迎来到Linux的世界,看笔记好好学多敲多打,每个人都是大神! 题目:KubeSphere 容器平台高可用:环境搭建与可视化操作指南 版本号: 1.0,0 作者: 老王要学习 日期: 2025.06.05 适用环境: Ubuntu22 文档说…...

K8S认证|CKS题库+答案| 11. AppArmor
目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作: 1)、切换集群 2)、切换节点 3)、切换到 apparmor 的目录 4)、执行 apparmor 策略模块 5)、修改 pod 文件 6)、…...
【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密
在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...

Psychopy音频的使用
Psychopy音频的使用 本文主要解决以下问题: 指定音频引擎与设备;播放音频文件 本文所使用的环境: Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...
Python如何给视频添加音频和字幕
在Python中,给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加,包括必要的代码示例和详细解释。 环境准备 在开始之前,需要安装以下Python库:…...
【JavaSE】绘图与事件入门学习笔记
-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角,以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向,距离坐标原点x个像素;第二个是y坐标,表示当前位置为垂直方向,距离坐标原点y个像素。 坐标体系-像素 …...

学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2
每日一言 今天的每一份坚持,都是在为未来积攒底气。 案例:OLED显示一个A 这边观察到一个点,怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 : 如果代码里信号切换太快(比如 SDA 刚变,SCL 立刻变&#…...
DeepSeek 技术赋能无人农场协同作业:用 AI 重构农田管理 “神经网”
目录 一、引言二、DeepSeek 技术大揭秘2.1 核心架构解析2.2 关键技术剖析 三、智能农业无人农场协同作业现状3.1 发展现状概述3.2 协同作业模式介绍 四、DeepSeek 的 “农场奇妙游”4.1 数据处理与分析4.2 作物生长监测与预测4.3 病虫害防治4.4 农机协同作业调度 五、实际案例大…...
Java编程之桥接模式
定义 桥接模式(Bridge Pattern)属于结构型设计模式,它的核心意图是将抽象部分与实现部分分离,使它们可以独立地变化。这种模式通过组合关系来替代继承关系,从而降低了抽象和实现这两个可变维度之间的耦合度。 用例子…...

MySQL 知识小结(一)
一、my.cnf配置详解 我们知道安装MySQL有两种方式来安装咱们的MySQL数据库,分别是二进制安装编译数据库或者使用三方yum来进行安装,第三方yum的安装相对于二进制压缩包的安装更快捷,但是文件存放起来数据比较冗余,用二进制能够更好管理咱们M…...