本文共 13937 字,大约阅读时间需要 46 分钟。
springboot中对应数据库的访问方式,默认底层默认采用整合spring data技术进行处理和操作,所以可以对于关系型或者非关系型数据库都可以轻松访问。下面主要针对jdbc、mybatis、spring data jpa的方式来进行数据访问。
我们前面了解到spring框架中内嵌的jdbc的数据层访问主要通过jdbcTemplate类来操作对应sql语句的访问的,当然一些前期工作数据源、数据库连接配置等相关操作,在springboot自动封装的框架中,肯定都简化了。只要简单的操作就欧了。那些原理前面了解就ok了。
(1)首先肯定要配置数据源连接,springboot中就在配置文件中设置这些属性:这边用yuml语法设置的实现,没有用properties。
(1.1)这边有个细节,就是上图中驱动类com.mysql.jdbc.Driver是哪个驱动管理类加载的(数据库驱动管理类加载驱动),然后会获取真正驱动接口的实现,那么springboot中对应jdbc默认使用的数据源管理类是哪个呢?这边这个数据源管理类的意思是管理数据驱动和包含有连接数据库基本信息(url、密码等)的一个类,这种类我们以前见过有c3p0或者dpcp等。但这边是用的是tomcat.jdbc的数据源。 由于配置文件中都对对该驱动管理类进行属性注入了,那么该类肯定已经是被注册到容器了,所以就可以直接@autowire获取该驱动管理类实例(bean)。 (2)下面好像突然不知道干嘛了,springboot都是自动配置的,那首先看配置类,从配置类中了解原理过程。springboot开发要有一种意识:先明确是何技术、直接找该技术的自动配置类xxxautoconfiguration、还有一个配置属性类xxx.properties这两个核心类,要特别注意。然后看这类中:什么bulider(构建器)呀,什么initial(初始化)呀都可以随便看看。还有一些xxxconfigurer(属性扩展类)、xxxcustomizer(属性定制类)。都注意注意。总比没目的看好吧! (3)我们之前了解过spring中内嵌的数据库访问的jdbc的方式,核心是jdbcTemplate类,看上图中有jdbcTemplate,进入源码发现如下:直接已经注入容器了,那么我们就可以直接使用了。 (4)直接测试类中属性注入来获取jdbcTemplate;好像目前为止入门就做了两件事:一个是手动配置数据连接,另一个就是数据库访问代码编写了。当然,里面还有好多东西,这个只是入门的演示。package com.example.controller;import java.util.List;import java.util.Map;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.jdbc.core.JdbcTemplate;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.ResponseBody;@Controllerpublic class mycontroller { @Autowired JdbcTemplate jdbcTemplate; @ResponseBody @RequestMapping("/jdbc") public List
由上面入门可见springboot中对应数据访问的方式简化了很多,入门很简单,但实际上肯定不止那些呀!下面分析可以在项目中直接辅助构建数据库中表结构的部分。
上面我们知道springboot中默认使用时内置的数据源,但是通常我们开发不用,常使用DruidDataSource或者HikariDataSource数据源。DruidDataSource这个由成套的数据源的监控和安全机制,HikariDataSource运行效率要高,目前使用阿里的DruidDataSource。
(2.1)首先设置自定义的数据源,在属性配置文件中设置:spring.datasource.type:com.alibaba.druid.pool.DruidDataSource这样就使用自定义的数据源了(这个外来数据源是数据源配置类中通过反射技术将这个数据源给配置和创建的),但是这个数据源中一些属性的注入怎么设置呢,springboot中属性注入通常在组件注册(注册bean)进容器的过程中,在这个bean上添加注解@ConfigurationProperties(prefix=“spring.datasource/xxx”)和属性配置文件中设置属性的方式完成的。@Configurationpublic class mydatasource {// 这边自己定义这个bean组件进入容器,这样顺带可以设置和配置文件中进行配置属性的映射,springboot中自动配置一般都是由条件判断的// 如果没有自定义组件,才会自动向容器中注入组件的。@conditionalonbean @Bean @ConfigurationProperties(prefix="spring.datasource") public DataSource druid() { return new DruidDataSource(); } }===============================================spring: datasource: username: root password: 123456 url: jdbc:mysql://10.10.16.190:3306/sunxiang 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
(2.2)阿里这个数据源于成套的监控机制,所以可以配置这些功能:
配置对这个数据源的监控;监控肯定通过图形界面来监控呀!所以这个druid数据源包中肯定也有相关servlet的设置(即管理后台的servlet请求【statviewservlet这个类,也是druid数据库配套打包的类。这个类内部都设置好了一些访问的请求处理和返回的响应信息】)。注意!!!这个servlet类是外部定义且封装的一个servlet,就和我们原生servlet那边学习的一样。但是springboot中jar包没有xml,所以这个servlet映射的话(就是传统在web.xml中设置映射内容)。springboot中类似的做法是将这个servlet在ServletRegistrationBean类中注册进去就OK了,作用和以前在xml中配置url映射一样。简单说就是这个ServletRegistrationBean就相当于一个这个servlet的web.xml配置文件实际上,springboot中整合mybatis就是配置都自动化,其他本质还是mybatis的实现,这边如果有点生疏可以看:。
(1)首先,肯定要映入springboot的mybatis的依赖环境,springboot内部没有自己的mybatis的整合包,这个是mybatis自家整合springboot的一个环境依赖,当然这里面都有:
(2)创建数据源相关类型的配置:确定用哪个数据源、还有数据源中那些属性设置。这个也比较关键,就这上面一节特意详解了数据源。 (3)数据库中表数据的准备 (4)数据库库中表所对应的java的bean准备,便于框架能够完美自动映射。我们知道mybatis实现数据的访问,核心要两个配置文件:一个全局配置文件(数据源等连接信息),另一个是具体的sql的语句信息设置即mapper映射文件(mapper.xml,里面是许多具体sql语句执行的信息)。
(1)springboot中对应全局配置文件都封装实现了,就是自动配置类完成了,我们只要简单确定数据源类型就OK了,那么还有映射文件的配置呢?这个就是下面springboot中比较关键的部分了,映射文件转为在接口中注解的方式来替代了。 (2)核心的注解@mapper。就是告知springboot这个类是映射文件,即告知这个类就是一个操作数据库的mapper。里面就是有具体sql语句、sql语句的输入参数、输出参数。 实际上这不就是原生mybatis那边的mapper接口开发的过程嘛(只不过那边是接口和映射文件分开,而这边通过注解方式两个组合只通过接口体现出来了)!主要就是映射文件的实现: ( 注解中映射文件的sql实现是@select、@insert、@delete等这些注解实现的。@mapper表示映射的操作标识,就是那些sql中参数映射到方法的对应变量上,或者反向的过程等,即sql中字段的输入参数和sql执行后输出的数据库内容的自动映射到java的方法上对应的方法输入和方法的返回对象中。)
package com.example.mapper;import org.apache.ibatis.annotations.Delete;import org.apache.ibatis.annotations.Insert;import org.apache.ibatis.annotations.Mapper;import org.apache.ibatis.annotations.Options;import org.apache.ibatis.annotations.Select;import org.apache.ibatis.annotations.Update;import com.example.bean.user;@Mapper//这边就是mybaits那边的sql映射文件的作用,以前是在sql映射文件中中编写sql语句还有语句的输入参数和输出参数。public interface UserMapper { @Select("select * from user where id=#{id}") public user getuserbyid( Integer id); @Options() @Update("update user set name=#{name} where id=#{id}") public int updateuserbyid(user u); @Options(useGeneratedKeys = true,keyProperty = "id") @Insert("insert into user(id,name,gender,birth_day) values(#{id},#{name},#{gender},#{birthDay})") public int insertuser(user u); @Delete("delete from user where id=#{id}") public int deleteuser(Integer id);}
然后实现: 这边有个细节注意:就是上面定义的接口为啥可以直接注入生成对象呢?接口是如何生成实现对象的呢?这边实现肯定有个前提:就是这个实现的方式是固定通用或者死板的,所以才可以由框架自动生成的,要是灵活多变的,还真以为框架多人工智能呀!。详细可以见mybatis中原生dao开发方式——接口实现的过程
package com.example.control;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.PathVariable;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import com.example.bean.user;import com.example.mapper.UserMapper;@RestControllerpublic class usercontroller { @Autowired UserMapper map; @RequestMapping("/getuser/{id}") //根据id查询用户信息 public user getuser(@PathVariable("id")Integer id) { user getuserbyid = map.getuserbyid(id); return getuserbyid; } @RequestMapping("/deleteuser/{id}") //根据id删除数据中指定记录 public int deleteuser(@PathVariable("id")Integer id) { int deleteuser = map.deleteuser(id); return deleteuser; } @RequestMapping("/updateuser") public user updateuser(user u) { map.updateuserbyid(u); user getuser = getuser(u.getId()); return getuser; } @RequestMapping("/adduser") //增加用户的信息到数据库中 public user insertuser(user u) { map.insertuser(u); return u; }}
分析:上面实现过程有几个细节点
Public interface UserDao { public User getUserById(int id) throws Exception; public void insertUser(User user) throws Exception;}===================================Public class UserDaoImpl implements UserDao{public UserDaoImpl(SqlSessionFactory sqlSessionFactory){ this.setSqlSessionFactory(sqlSessionFactory); } private SqlSessionFactory sqlSessionFactory; @Override public User getUserById(int id) throws Exception { SqlSession session = sqlSessionFactory.openSession(); //spring整合后该条语句变成:SqlSession session = getSqlSession(); User user = null; try { //通过sqlsession调用selectOne方法获取一条结果集 //参数1:指定定义的statement的id,参数2:指定向statement中传递的参数 user = session.selectOne("test.findUserById",id); System.out.println(user); } finally{ session.close(); } return user; }
springboot中注解的mybatis方式中免去手工整合一些配置文件和完全免去单独映射文件的编写,而这边配置文件的方式中映射文件还是要单独编写的,(更正一下,前面注解版的配置文件也要简单设置一些,但是只设置一些基本参数数据)就类似于原生mybatis的接口实现的整个过程!但是过程前期的一些环境配置都由springboot自动实现了,所以也还是省了许多琐事。
spring: datasource: username: root password: root url: jdbc:mysql://localhost:3306/sun driver-class-name: com.mysql.jdbc.Driver type: com.alibaba.druid.pool.DruidDataSource
@Mapperpublic interface employeemapper { public employee getemployeebyid(Integer id) ; public void addemployee(employee e);}-------------------------------------------------------------insert into employee(lastName,gender,email,d_id) values(#{lastName},#{gender},#{email},#{did})
//也是在springboot的配置文件中设置mybatis的配置文件的位置属性。这边是用的yml格式的。当然可以用properties格式。mybatis: config-location: classpath:mapper/mybatis-config.xml mapper-locations: - classpath:mapper/employeemapper.xml
实际上这边要关注的思想:接口是如何自动由框架生成该接口的实现的。为什么要明确这个呢?本质是spring data中提供了统一的功能接口,让我们自定义自己接口来继承这些接口,这样我们自定义的接口就具有这些统一接口的功能了。值得注意的是,我们自定义的接口实现都不用我们管,spring data框架自动帮我们实现。当然接口的那些功能也肯定实现了,我们直接调用方法就OK了。
上面的过程:是不是就是我们最初学java的时候一直梦寐以求的事情,直接写出什么功能的接口,然后自动生成这些功能的实现 如果想要简单理解这样过程可以参照mybatis的接口实现dao的开发方式过程,这只是类比的理解(简单说就是这些实现肯定都是依据规定的约束,然后经过通用固定死板的实现的,所以框架才能自动帮我们封装自动实现,这种过程一定会常听见一个词:规范),详细spring data的理解,我也不是很了解(哈哈)spring data是spring公司为了简化spring框架进行数据访问的一项技术,这个技术既支持关系型数据库访问也支持非关系型数据库的访问。它下面有许多子项目/模块,分别支持不同类型数据访问的,如MongoDB、redis、JPA(java 持久层)。spring data的目的旨在使用统一的api来对数据访问层的操作(无论关系型或者非关系型数据库都通过统一标准来实现(实际上本质是springdata提供了一些统一接口,然我们自定义接口来继承这些接口就可以了)。)这个标准中包含了基本的增删改查、排序、分页等操作。
(一)jdbc的数据访问实现核心:(1)自动配置(整体大环境自动搭建)(2)简单属性设置(数据源,数据库连接)(3)jdbctemplate自动注入对象(该对象中直接和sql操作)
(二)mybatis的数据访问实现:(1)自动配置(整体大环境自动搭建)(2)简单的属性设置(数据源,数据库连接)(3)表结构对应的实体类准备(方便自动完成数据库中表记录和java中对象数据的相互映射)(4)mybatis的接口(作用:关联sql映射文件,且执行sql文件中sql语句和输入参数输出参数的自动映射)和sql映射文件的分开操作(注解版是两个结合的,配置文件版是分开的,这样结构清晰不混乱、且解耦合。) (三)JPA的实现:(1)自动配置(整体大环境自动搭建)(2)简单属性设置(即在属性配置文件中设置数据源,数据库连接)这个好像所有数据访问都要设置的步骤。(3)开始实体类准备,同时在实体类中注解来自动生成数据库中对应的数据表结构(4)定义自己的接口,并集成所需功能的接口(如一些接口有分页,排序功能;一些接口有基本增删改查的功能;还有其他类,或者傻瓜式继承japrepository接口)。这些继承功能接口之后,也不用我们实现,spring data自动帮助实现这些接口并注册进容器了,我们后面直接容器中@autowire注入就可以调用这些实现类了,然后直接使用其中功能方法,是不是简单多了。(1)JPA是spring data中的一个java持久层API,是一个数据访问层的规范,它规范里面有:通过注解来简化数据库的操作(如直接定义数据表对应的实体类的时候,同时通过注解来自动生成数据库中对应的数据表结构)。这个规范的实现有:hibernate、toplink、openJPA等。spring data中默认使用hibernate来完成接口的实现的。 所以是基于ORM(对象关系映射object relational mapping)思想的。
(2)jap数据访问过程:核心三步走:(1)实体类并明确映射关系、(2)自定义一个接口并更加所需功能继承对应功能的统一接口、(3)直接通过接口的实现类来操作实体映射对应的数据表。//使用JPA注解配置映射关系 @Entity //告诉JPA这是一个实体类(和数据表映射的类) @Table(name = "tbl_user") //@Table来指定和哪个数据表对应;如果省略默认表名就是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;
//继承JpaRepository框架提供的统一接口来完成对数据库的操作。这个就是类似于web开发中的dao层接口,是一样的。//功能是对数据库的操作,好像以前dao层的接口实现里面,抽象方法的实现里面都是直接通过Sql语句或者Hql语句完成的吧!//由于里面方法名是固定的,所以方法的功能也是固定的,所以里面的实现sql语句也应该是固定的,所以才可以由spring data//自动完成抽象方法的实现吧! public interface UserRepository extends JpaRepository{ }
spring: jpa: hibernate: # 更新或者创建数据表结构 生成策略 ddl‐auto: update # 控制台显示SQL;JPA和数据访问的sql执行的语句 show‐sql: true
上面就是JPA的实现过程;
前后交互的开发风格常按照restful风格:
转载地址:http://nhdxi.baihongyu.com/