Spring Boot核心技术系统学习总结(七)Spring Boot Data

Spring Boot核心技术系统学习总结(七)Spring Boot Data

    SpringBoot_数据访问
    JDBC&自动配置原理
    整合Druid&配置数据源监控
    整合MyBatis
    整合JPA

    
一、SpringBoot_数据访问
    1.JDBC默认配置
        
        
    2.自动配置原理(源码分析)
        1)DataSourceConfiguration类中 定义了默认支持的 Tomcat, Hikari, Dbcp, Dbcp2 数据源
        2)DataSourceConfiguration类中,默认使用的Tomcat数据源(SpringBOOT v1.5.17)

/**
 * Tomcat Pool DataSource configuration.
 */
@ConditionalOnClass(org.apache.tomcat.jdbc.pool.DataSource.class)
@ConditionalOnMissingBean(DataSource.class)
//matchIfMissing = true 即默认数据源=org.apache.tomcat.jdbc.pool.DataSource.class
@ConditionalOnProperty(name = "spring.datasource.type", havingValue = "org.apache.tomcat.jdbc.pool.DataSource", matchIfMissing = true)
static class Tomcat {

	@Bean
	//spring.datasource.tomcat 开头的配置,可以优化数据源
	@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;
	}
}

        3)绑定数据源配置

@ConditionalOnMissingBean(DataSource.class)
@ConditionalOnProperty(name = "spring.datasource.type")
static class Generic {

	@Bean
	public DataSource dataSource(DataSourceProperties properties) {
		return properties.initializeDataSourceBuilder().build();
	}

}

        4)自动配置项:

@Configuration
@ConditionalOnClass({ DataSource.class, EmbeddedDatabaseType.class })
@EnableConfigurationProperties(DataSourceProperties.class)
@Import({ Registrar.class, DataSourcePoolMetadataProvidersConfiguration.class })
public class DataSourceAutoConfiguration {

	@Bean
	@ConditionalOnMissingBean //自动配置项
	public DataSourceInitializer dataSourceInitializer(DataSourceProperties properties,
			ApplicationContext applicationContext) {
		return new DataSourceInitializer(properties, applicationContext);
		// 其中,DataSourceInitializer 实现了 ApplicationListener<DataSourceInitializedEvent>
		// @PostConstruct
		// public void init() 方法会调用:runSchemaScripts()、runDataScripts()方法,实现自动运行建表语句、插入数据语句
		// fallbackResources.add("classpath*:data-all.sql"); 默认执行的省sql
		// fallbackResources.add("classpath*:data.sql");
		// 还可以通过配置在配置文件中添加制定的sql文件:
		// schema:    
      	    // ‐ classpath:department.sql
	}
}

二、整合Druid&配置数据源监控
    1.引入Druid数据源

<!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
<dependency>
	<groupId>com.alibaba</groupId>
	<artifactId>druid</artifactId>
	<version>1.1.18</version>
</dependency>

        application.yaml中的数据源配置(以下配置用于对DruidAbstractDataSource类中的属性进行绑定赋值):

spring:
  datasource:
	username: root
	password: 123456
	url: jdbc:mysql://localhost:33306/test
	driver-class-name: com.mysql.jdbc.Driver
	type: com.alibaba.druid.pool.DruidDataSource
	initialSize: 5
	minIdle: 5
	maxActive: 20
	maxWait: 60000
	timeBetweenEvictionRunsMillis: 60000
	minEvictableIdleTimeMillis: 300000
	validationQuery: SELECT 1 FROM DUAL
	testWhileIdle: true
	testOnBorrow: false
	testOnReturn: false
	poolPreparedStatements: true
	#   配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
	filters: stat,wall,log4j
	maxPoolPreparedStatementPerConnectionSize: 20
	useGlobalDataSourceStat: true
	connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500

        数据源配置类:

@Configuration
public class DruidConfig {

	@Bean
	@ConfigurationProperties(prefix = "spring.datasource")
	public DataSource druid(){
		return new DruidDataSource();
	}
}

        测试数据源:

@RunWith(SpringRunner.class)
@SpringBootTest
public class DatasourceApplicationTests {
	@Autowired
	DataSource dataSource;

	@Test
	public void contextLoads() {
		//SpringBoot2默认使用的数据源:class com.zaxxer.hikari.HikariDataSource
		//SpringBoot1.5.17:class org.apache.tomcat.jdbc.pool.DataSource
		System.out.println(dataSource.getClass());
	}
}

    2.配置druid数据源监控

@Configuration
public class DruidConfig {

    @Bean
    @ConfigurationProperties(prefix = "spring.datasource")
    public DataSource druid(){
        return new DruidDataSource();
    }
    //配置Druid的监控
    //1、配置一个管理后台的Servlet
    @Bean
    public ServletRegistrationBean statViewServlet(){
        //访问到druid监控后台的url与处理请求的servlet注册
        ServletRegistrationBean bean = new ServletRegistrationBean(new StatViewServlet(), "/druid/*");
        Map<String,String> initParams = new HashMap<>();
        //druid监控后台的参数设置:
//        public abstract class ResourceServlet extends HttpServlet {
//        private final static Log   LOG                 = LogFactory.getLog(ResourceServlet.class);
//
//        public static final String SESSION_USER_KEY    = "druid-user";
//        public static final String PARAM_NAME_USERNAME = "loginUsername";
//        public static final String PARAM_NAME_PASSWORD = "loginPassword";
//        public static final String PARAM_NAME_ALLOW    = "allow";
//        public static final String PARAM_NAME_DENY     = "deny";
//        public static final String PARAM_REMOTE_ADDR   = "remoteAddress";
        initParams.put("loginUsername","admin");
        initParams.put("loginPassword","123456");
        initParams.put("allow","");//默认就是允许所有访问
        initParams.put("deny","192.168.248.121");
        bean.setInitParameters(initParams);
        return bean;
    }

    //2、配置一个web监控的filter
    @Bean
    public FilterRegistrationBean webStatFilter(){
        FilterRegistrationBean bean = new FilterRegistrationBean();
        bean.setFilter(new WebStatFilter());
        Map<String,String> initParams = new HashMap<>();
        initParams.put("exclusions","*.js,*.css,/druid/*");
        bean.setInitParameters(initParams);
        bean.setUrlPatterns(Arrays.asList("/*"));
        return  bean;
    }
}

        测试效果:
        
        
三、整合MyBatis
    1.引入mybatis依赖:

<dependency>
	<groupId>org.mybatis.spring.boot</groupId>
	<artifactId>mybatis-spring-boot-starter</artifactId>
	<version>1.3.1</version>
</dependency>

    mybatis依赖树
    
    2.建立实体类:

@Data
public class Department implements Serializable {
	private Integer id;
	private String name;
}

    3.注解版的mybatis
        可以添加mybatis的定制器,实现表字段下划线转驼峰形式
             

import org.apache.ibatis.session.Configuration;
import org.mybatis.spring.boot.autoconfigure.ConfigurationCustomizer;
import org.springframework.context.annotation.Bean;

@org.springframework.context.annotation.Configuration
public class MyBatisConfig {

    @Bean //添加定制器,实现表字段下划线转驼峰形式
    public ConfigurationCustomizer configurationCustomizer(){
        return new ConfigurationCustomizer(){

            @Override
            public void customize(Configuration configuration) {
                configuration.setMapUnderscoreToCamelCase(true);
            }
        };
    }
}

        |- 编写mapper,也可以在启动类上加@MapperScan(value = "mapper所在的包名"):

@Mapper
public interface DeptMapper {

    @Select("select * from department t where t.id = #{id}")
    Department selectDept(int id);

    @Delete("delete from department where id = #{id}")
    int deleteDept(@Param("id") int id);

    @Update("update department t set t.department_name = #{name} where t.id = #{id}")
    int updateDeptNameById(@Param("id") int id, @Param("name") String name);

    //设置主键为id,自增
    @Options(keyProperty = "id", useGeneratedKeys = true)
    @Insert("insert into department (department_name) values (#{departmentName})")
    int insertDept(Department department);
}

测试类:

@SpringBootTest
@RunWith(SpringRunner.class)
public class DeptMapperTest {

    @Autowired
    DeptMapper deptMapper;

    @Test
    public void selectDept() {
        int id = 1;
        Department department = deptMapper.selectDept(id);
        Assert.assertEquals("AA", department.getDepartmentName());
    }

    @Test
    public void deleteDept() {
        int id = 1;
        int i = deptMapper.deleteDept(id);
        Assert.assertEquals(1, i);
    }

    @Test
    public void updateDeptNameById() {
        int id = 2;
        String name = "beijing office";
        int i = deptMapper.updateDeptNameById(id, name);
        Assert.assertEquals(1, i);
    }

    @Test
    public void insertDept() {
        Department department = new Department();
        department.setDepartmentName("BB");
        deptMapper.insertDept(department);
    }
}

    4.xml版的mybatis
    xml方式的mybatis配置文件目录:
    
    |- mybatis全局配置文件:mybatis-config.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!-- mybatis的全局配置文件 -->
    <settings>
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>
</configuration>
    |- DeptMapper配置文件:
<?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.datasource.mapper.DeptMapper">
    <!--    public Employee getEmpById(Integer id);

     public void insertEmp(Employee employee);-->
    <select id="selectDept" resultType="com.datasource.entity.Department">
        SELECT * FROM department WHERE id=#{id}
    </select>

    <insert id="insertDept" parameterType="com.datasource.entity.Department">
        INSERT INTO department(department_name) VALUES (#{departmentName})
    </insert>
</mapper>

    |- Mapper类:

@Mapper
public interface DeptMapper {

    //@Select("select * from department t where t.id = #{id}")
    Department selectDept(int id);

    //@Delete("delete from department where id = #{id}")
    int deleteDept(@Param("id") int id);

    //@Update("update department t set t.department_name = #{name} where t.id = #{id}")
    int updateDeptNameById(@Param("id") int id, @Param("name") String name);

    //设置主键为id,自增
    //@Options(keyProperty = "id", useGeneratedKeys = true)
    //@Insert("insert into department (department_name) values (#{departmentName})")
    int insertDept(Department department);
}

    |- 配置文件application.yaml新增:

mybatis:
  config-location: classpath:mybatis/mybatis-config.xml
  mapper-locations: classpath:mybatis/mapper/*.xml

    测试类:同上
    
四、整合JPA    
    1.SpringData
     
        SpringData为我们提供使用统一的API来对数据访问层进行操作;这主要是Spring Data Commons项目来实现的。Spring Data Commons让我们在使用关系型或者非关系型数据访问技术时都基于Spring提供的统一标准,标准包含了CRUD(创建、获取、更新、删除)、查询、排序和分页的相关操作。
    2.统一的Repository接口Repository<T, ID extends Serializable>:
        RevisionRepository<T, ID extends Serializable, N extends Number & Comparable<N>>:基于乐观锁机制
        CrudRepository<T, ID extends Serializable>:基本CRUD操作
        PagingAndSortingRepository<T, ID extends Serializable>:基本CRUD及分页
    3、提供数据访问模板类 xxxTemplate;如:MongoTemplate、RedisTemplate等
    4、JPA与Spring Data
        1)、JpaRepository基本功能编写接口继承JpaRepository既有crud及分页等基本功能
        2)、定义符合规范的方法命名,在接口中只需要声明符合规范的方法,即拥有对应的功能
        3)、@Query自定义查询,定制查询SQL
        4)、Specifications查询(Spring Data JPA支持JPA2.0的Criteria查询)
    
  --- 整合JPA实践 ---
    1、引入spring-boot-starter-data-jpa

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

    2、配置文件打印SQL语句

spring:
  jpa:
	show-sql: true
	hibernate:
	  ddl-auto: update

    3、创建Entity标注JPA注解

@Entity
@Data
@Table(name = "t_users")
public class User implements Serializable {

    @Id //标记主键
    @GeneratedValue(strategy = GenerationType.IDENTITY) //设置主键自增
    private Integer uid;

    @Column(name = "user_name", length = 64) //关联的列名,字段长度
    private String userName;

    @Column
    private Integer age;

}

    4、创建Repository接口继承JpaRepository

// 创建repository,关联实体类与主键类型
public interface UserRepository extends JpaRepository<User, Integer> {
}

    5、测试方法

@SpringBootTest
@RunWith(SpringRunner.class)
public class UserRepositoryTest {

    @Autowired
    UserRepository userRepository;

    @Test
    public void testInsert(){
        User user = new User();
        user.setUserName("小明");
        user.setAge(15);
        User savedUser = userRepository.save(user);
        System.out.println(savedUser);
}

    @Test
    public void testSelect(){
        int id = 1;
        User user = userRepository.findOne(id);
        System.out.println(user);
    }

}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值