二、spring Boot构建的Web应用中,基于MySQL数据库的几种数据库连接方式进行介绍
2017-08-11 14:46
1136 查看
包括JDBC、JPA、MyBatis、多数据源和事务。
一、JDBC连接数据库
1、属性配置文件(application.properties)spring.datasource.url=jdbc:mysql://localhost:3306/test spring.datasource.username=root spring.datasource.password=123456 spring.datasource.driver-class-name=com.mysql.jdbc.Driver
如果使用JNDI,则可以替代spring.datasource的url、username、password,如:
spring.datasource.jndi-name=java:tomcat/datasources/example
值得一提的是,无论是SpringBoot默认的DataSource配置还是你自己的DataSourcebean,都会引用到外部属性文件中的属性配置。所以假设你自定义的DataSourcebean,你可以在定义bean时设置属性,也可以在属性文件中,以“spring.datasource.*”的方式使属性配置外部化。
2、pom.xml配置maven依赖
<!--MYSQL--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <!--SpringBootJDBC--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency>
3、
StudentService.java
packageorg.springboot.sample.service; importjava.sql.ResultSet; importjava.sql.SQLException; importjava.util.List; importorg.springboot.sample.entity.Student; importorg.springframework.beans.factory.annotation.Autowired; importorg.springframework.jdbc.core.JdbcTemplate; importorg.springframework.jdbc.core.RowMapper; importorg.springframework.stereotype.Service; @Service publicclassStudentService{ @Autowired privateJdbcTemplatejdbcTemplate; publicList<Student>getList(){ Stringsql="SELECTID,NAME,SCORE_SUM,SCORE_AVG,AGEFROMSTUDENT"; return(List<Student>)jdbcTemplate.query(sql,newRowMapper<Student>(){ @Override publicStudentmapRow(ResultSetrs,introwNum)throwsSQLException{ Studentstu=newStudent(); stu.setId(rs.getInt("ID")); stu.setAge(rs.getInt("AGE")); stu.setName(rs.getString("NAME")); stu.setSumScore(rs.getString("SCORE_SUM")); stu.setAvgScore(rs.getString("SCORE_AVG")); returnstu; } }); } }
Student.java实体类
packageorg.springboot.sample.entity; importjava.io.Serializable; publicclassStudentimplementsSerializable{ privatestaticfinallongserialVersionUID=2120869894112984147L; privateintid; privateStringname; privateStringsumScore; privateStringavgScore; privateintage; //节省文章长度,getset方法省略 }
StudentController.java
packageorg.springboot.sample.controller; importjava.util.List; importorg.slf4j.Logger; importorg.slf4j.LoggerFactory; importorg.springboot.sample.entity.Student; importorg.springboot.sample.service.StudentService; importorg.springframework.beans.factory.annotation.Autowired; importorg.springframework.web.bind.annotation.RequestMapping; importorg.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/stu") publicclassStudentController{ privatestaticfinalLoggerlogger=LoggerFactory.getLogger(StudentController.class); @Autowired privateStudentServicestudentService; @RequestMapping("/list") publicList<Student>getStus(){ logger.info("从数据库读取Student集合"); returnstudentService.getList(); } }
本文对工程添加文件后工程结构图:
然后启动项目,访问地址:
[ { id:1, name:"小明", sumScore:"252", avgScore:"84", age:1 }, { id:2, name:"小王", sumScore:"187", avgScore:"62.3", age:1 }, { id:3, name:"莉莉", sumScore:"", avgScore:"", age:0 }, { id:4, name:"柱子", sumScore:"230", avgScore:"76.7", age:1 }, { id:5, name:"大毛", sumScore:"", avgScore:"", age:0 }, { id:6, name:"亮子", sumScore:"0", avgScore:"0", age:1 }
连接池说明
Tomcat7之前,Tomcat本质应用了DBCP连接池技术来实现的JDBC数据源,但在Tomcat7之后,Tomcat提供了新的JDBC连接池方案,作为DBCP的替换或备选方案,解决了许多之前使用DBCP的不利之处,并提高了性能。详细请参考:SpringBoot为我们准备了最佳的数据库连接池方案,只需要在属性文件(例如application.properties)中配置需要的连接池参数即可。
我们使用Tomcat数据源连接池,需要依赖tomcat-jdbc,只要应用中添加了spring-boot-starter-jdbc或spring-boot-starter-data-jpa依赖,则无需担心这点,因为将会自动添加tomcat-jdbc依赖。
假如我们想用其他方式的连接池技术,只要配置自己的DataSourcebean,即可覆盖SpringBoot的自动配置。
请看我的数据源配置:
spring.datasource.url=jdbc:mysql://localhost:3306/test spring.datasource.username=root spring.datasource.password=123456 spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.max-idle=10
spring.datasource.max-wait=10000
spring.datasource.min-idle=5
spring.datasource.initial-size=5
spring.datasource.validation-query=SELECT1
spring.datasource.test-on-borrow=false
spring.datasource.test-while-idle=true
spring.datasource.time-between-eviction-runs-millis=18800
spring.datasource.jdbc-interceptors=ConnectionState;SlowQueryReport(threshold=0)
配置过连接池的开发人员对这些属性的意义都有所认识。
我们打开DEBUG日志输出,logback.xml中添加:
<loggername="org.springframework.boot"level="DEBUG"/>
然后启动项目,注意观察日志输出,如下图中会显示自动启用了连接池:
在上面的数据源配置中添加了过滤器,并设置了延迟时间为0(故意设置很低,实际项目中请修改):
spring.datasource.jdbc-interceptors=ConnectionState;SlowQueryReport(threshold=0)
这个时候,我们访问
o.a.t.j.p.interceptor.SlowQueryReport:SlowQueryReportSQL=SELECTID,NAME,SCORE_SUM,SCORE_AVG,AGEFROMSTUDENT;time=3ms;
二、将介绍如何在
修改pom.xml依赖
与上一篇介绍的jdbc不同的是spring-boot-starter-jdbc修改为spring-boot-starter-data-jpa即可,当然<!--MYSQL--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <!--SpringBootJPA--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency>
注意:如果你想JDBC和JPA可以一起使用,SpringBoot是支持的,你只需要把JDBC和JPA的依赖都添加在pom.xml中即可。无需其他特殊处理,有关JDBC的使用介绍请看上一篇“
修改属性配置文件
在属性配置文件中添加JPA相关属性,注意这些并非必须,我们如果只添加dataSource的url\username\password\driver-class-name也可以正常使用,有关JPA的其他配置都是可选的。spring.jpa.database= spring.jpa.show-sql= spring.jpa.properties= spring.jpa.generate-ddl= spring.jpa.open-in-view= spring.jpa.database-platform= spring.jpa.hibernate.ddl-auto= spring.data.jpa.repositories.enabled= spring.jpa.hibernate.naming-strategy=
熟悉JPA的根据名字应基本知道这些分别的作用了。
传统上,JPA实体类在persistence.xml文件中指定的。使用SpringBoot,这个文件是没有必要的,因为它使用“实体扫描”,默认情况下主配置@EnableAutoConfiguration或@SpringBootApplication下面的所有包都将会被扫描。任何使用注解@Entity,@Embeddable或@MappedSuperclass的类都将被管理。
Java代码实例
一个接口一个Controller
我们创建一个接口IScoreDao.
packageorg.springboot.sample.dao; importjava.util.List; importjavax.transaction.Transactional; importorg.springboot.sample.entity.Score; importorg.springframework.data.jpa.repository.Modifying; importorg.springframework.data.jpa.repository.Query; importorg.springframework.data.repository.CrudRepository; importorg.springframework.data.repository.query.Param; publicinterfaceIScoreDaoextendsCrudRepository<Score,Integer>{ @Transactional @Modifying @Query("updateScoretsett.score=:scorewheret.id=:id") intupdateScoreById(@Param("score")floatscore,@Param("id")intid); @Query("selecttfromScoret") List<Score>getList(); }
注意,如果你其中使用了修改、新增、删除操作,则必须要在接口上面或者对应的方法上面添加@Transactional注解,否则会抛出异常。
实体类Score.java
packageorg.springboot.sample.entity; importjava.io.Serializable; importjava.util.Date; importjavax.persistence.Column; importjavax.persistence.Entity; importjavax.persistence.GeneratedValue; importjavax.persistence.Id; importjavax.persistence.Table; /** *成绩 * */ @Entity @Table(name="score") publicclassScoreimplementsSerializable{ privatestaticfinallongserialVersionUID=8127035730921338189L; @Id @GeneratedValue privateintid; @Column(nullable=false,name="STUDENTID")//这里说一下,我使用指定数据库列的时候,使用小写会不起作用,修改为大写便正常了。不知道为何,如果遇到一样问题的可以尝试下。 privateintstuId; @Column(nullable=false,name="SUBJECTNAME") privateStringsubjectName; @Column(nullable=false) privatefloatscore; @Column(nullable=false,name="EXAMTIME") privateDateexamTime; //省去get、set方法(占用文章空间) }
ScoreController.java
packageorg.springboot.sample.controller; importjava.util.List; importorg.slf4j.Logger; importorg.slf4j.LoggerFactory; importorg.springboot.sample.dao.IScoreDao; importorg.springboot.sample.entity.Score; importorg.springframework.beans.factory.annotation.Autowired; importorg.springframework.web.bind.annotation.RequestMapping; importorg.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/score") publicclassScoreController{ privatestaticfinalLoggerlogger=LoggerFactory.getLogger(ScoreController.class); @Autowired privateIScoreDaoscoreService; @RequestMapping("/scoreList") publicList<Score>getScoreList(){ logger.info("从数据库读取Score集合"); //测试更新数据库 logger.info("更新的行数:"+scoreService.updateScoreById(88.8f,2)); scoreService.delete(23); returnscoreService.getList(); } }
然后在浏览器访问地址:
最后要说明的是,Spring会自动为我们继承CrudRepository接口的接口创建实现类。我们只需要在使用的时候直接使用注解@Autowired注入即可(IScoreDao接口上也没有必要增加@Component、@Repository等注解)。
还有,我这里为了简单起见,直接将操作数据库的在Controller中使用,实际项目中,是不建议这样做的,IScoreDao的所属角色是数据库持久,我们还应当有Service(如ScoreService)来调用IScoreDao的方法,然后在Controller中调用Service中的方法。原因是因为,我们数据库访问层,都是接口定义方法,上面注解注入SQL和参数,没有具体的代码逻辑处理。如果我们想在执行SQL之前或之后执行逻辑处理,只能在Service中或者Controller(不建议)中。
我们严格按照这种方式去做(持久层只与SQL有关,通过接口定义无逻辑处理),这样才是彻彻底底的持久层。越严格的规范制度,在某种程度上来说其实越有利于代码的管理和项目代码的迭代发展。
当然,如果你实在想要实现自己的class实现类,下面会附上一个实例代码,在此之前,我们先看一个图片:
这个图是Spring使用动态代理创建的接口实例,可以看出,其使用的是SimpleJpaRepository类,所以如果我们实现自己的Repository,可以扩展SimpleJpaRepository并实现自己的factory-class入手,这里不做详解。注意凡事实现Repository接口的实现类都不需要添加@Repository注解,否则你会遇到问题。
本文介绍JPA相比上一篇关于JDBC的介绍增加的文件工程截图为:
熟悉其中一种持久数据的方法后,其他类似的都大同小异。
三、SpringBoot种配置MyBatis
其实mybatis官网在2015年11月底就已经发布了对SpringBoot集成的Release版本,Github上有代码:
前面对JPA和JDBC连接
先说个题外话,SpringBoot默认使用org.apache.tomcat.jdbc.pool.DataSource
现在有个叫HikariCP的JDBC连接池组件,据说其性能比常用的c3p0、tomcat、bone、vibur这些要高很多。
我打算把工程中的DataSource变更为HirakiDataSource,做法很简单:
首先在application.properties配置文件中指定dataSourceType
spring.datasource.type=com.zaxxer.hikari.HikariDataSource
然后在pom中添加Hikari的依赖
<dependency> <groupId>com.zaxxer</groupId> <artifactId>HikariCP</artifactId> <!--版本号可以不用指定,SpringBoot会选用合适的版本--> </dependency>
言归正传,下面说在
关于在SpringBoot中集成MyBatis,可以选用基于注解的方式,也可以选择xml文件配置的方式。通过对两者进行实际的使用,还是建议使用XML的方式(官方也建议使用XML)。
下面将介绍通过xml的方式来实现查询,其次会简单说一下注解方式,最后会附上分页插件(PageHelper)的集成。
一、通过xml配置文件方式
1、添加pom依赖
<dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <!--请不要使用1.0.0版本,因为还不支持拦截器插件,1.0.1-SNAPSHOT是博主写帖子时候的版本,大家使用最新版本即可--> <version>1.0.1-SNAPSHOT</version> </dependency>
2、创建接口Mapper(不是类)和对应的Mapper.xml文件
定义相关方法,注意方法名称要和Mapper.xml文件中的id一致,这样会自动对应上StudentMapper.
packageorg.springboot.sample.mapper; importjava.util.List; importorg.springboot.sample.entity.Student; /** *StudentMapper,映射SQL语句的接口,无逻辑实现 * */ publicinterfaceStudentMapperextendsMyMapper<Student>{ List<Student>likeName(Stringname); StudentgetById(intid); StringgetNameById(intid); }
MyMapper.java
packageorg.springboot.sample.config.mybatis; importtk.mybatis.mapper.common.Mapper; importtk.mybatis.mapper.common.MySqlMapper; /** *被继承的Mapper,一般业务Mapper继承它 * */ publicinterfaceMyMapper<T>extendsMapper<T>,MySqlMapper<T>{ //TODO //FIXME特别注意,该接口不能被扫描到,否则会出错 }
StudentMapper.xml
<?xmlversion="1.0"encoding="UTF-8"?> <!DOCTYPEmapperPUBLIC"-//mybatis.org//DTDMapper3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mappernamespace="org.springboot.sample.mapper.StudentMapper"> <!--type为实体类Student,包名已经配置,可以直接写类名--> <resultMapid="stuMap"type="Student"> <idproperty="id"column="id"/> <resultproperty="name"column="name"/> <resultproperty="sumScore"column="score_sum"/> <resultproperty="avgScore"column="score_avg"/> <resultproperty="age"column="age"/> </resultMap> <selectid="getById"resultMap="stuMap"resultType="Student"> SELECT* FROMSTUDENT WHEREID=#{id} </select> <selectid="likeName"resultMap="stuMap"parameterType="string"resultType="list"> SELECT* FROMSTUDENT WHERENAMELIKECONCAT('%',#{name},'%') </select> <selectid="getNameById"resultType="string"> SELECTNAME FROMSTUDENT WHEREID=#{id} </select> </mapper>
3、实体类
packageorg.springboot.sample.entity; importjava.io.Serializable; /** *学生实体 * */ publicclassStudentimplementsSerializable{ privatestaticfinallongserialVersionUID=2120869894112984147L; privateintid; privateStringname; privateStringsumScore; privateStringavgScore; privateintage; //getset方法省略 }
4、修改application.properties配置文件
mybatis.mapper-locations=classpath*:org/springboot/sample/mapper/sql/mysql/*Mapper.xml mybatis.type-aliases-package=org.springboot.sample.entity
5、在Controller或Service调用方法测试
@Autowired privateStudentMapperstuMapper; @RequestMapping("/likeName") publicList<Student>likeName(@RequestParamStringname){ returnstuMapper.likeName(name); }
二、使用注解方式
查看官方1、启动类(我的)中添加@MapperScan注解
@SpringBootApplication @MapperScan("sample.mybatis.mapper") publicclassSampleMybatisApplicationimplementsCommandLineRunner{ @Autowired privateCityMappercityMapper; publicstaticvoidmain(String[]args){ SpringApplication.run(SampleMybatisApplication.class,args); } @Override publicvoidrun(String...args)throwsException{ System.out.println(this.cityMapper.findByState("CA")); } }
2、在接口上使用注解定义CRUD语句
packagesample.mybatis.mapper; importorg.apache.ibatis.annotations.Param; importorg.apache.ibatis.annotations.Select; importsample.mybatis.domain.City; /** *@authorEddúMeléndez */ publicinterfaceCityMapper{ @Select("SELECT*FROMCITYWHEREstate=#{state}") CityfindByState(@Param("state")Stringstate); }
其中City就是一个普通Java类。
关于MyBatis的注解,有篇文章讲的很清楚,可以参考:
三、集成分页插件
这里与其说集成分页插件,不如说是介绍如何集成一个plugin。MyBatis提供了拦截器接口,我们可以实现自己的拦截器,将其作为一个plugin装入到SqlSessionFactory中。Github上有位开发者写了一个分页插件,我觉得使用起来还可以,挺方便的。
Github项目地址:
下面简单介绍下:
首先要说的是,Spring在依赖注入bean的时候,会把所有实现MyBatis中Interceptor接口的所有类都注入到SqlSessionFactory中,作为plugin存在。既然如此,我们集成一个plugin便很简单了,只需要使用@Bean创建PageHelper对象即可。
1、添加pom依赖
<dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>4.1.0</version> </dependency>
2、新增MyBatisConfiguration.java
packageorg.springboot.sample.config; importjava.util.Properties; importorg.slf4j.Logger; importorg.slf4j.LoggerFactory; importorg.springframework.context.annotation.Bean; importorg.springframework.context.annotation.Configuration; importcom.github.pagehelper.PageHelper; /** *MyBatis配置 * */ @Configuration publicclassMyBatisConfiguration{ privatestaticfinalLoggerlogger=LoggerFactory.getLogger(MyBatisConfiguration.class); @Bean publicPageHelperpageHelper(){ logger.info("注册MyBatis分页插件PageHelper"); PageHelperpageHelper=newPageHelper(); Propertiesp=newProperties(); p.setProperty("offsetAsPageNum","true"); p.setProperty("rowBoundsWithCount","true"); p.setProperty("reasonable","true"); pageHelper.setProperties(p); returnpageHelper; } }
3、分页查询测试
@RequestMapping("/likeName") publicList<Student>likeName(@RequestParamStringname){ PageHelper.startPage(1,1); returnstuMapper.likeName(name); }
更多参数使用方法,详见PageHelper说明文档(上面的Github地址)。
相关文章推荐
- SpringBoot中连接MYSQL数据库,并使用JPA进行数据库的相关操作
- SpringBoot中连接MYSQL数据库,并使用JPA进行数据库的相关操作
- 介绍几种 ADO.net 中的数据库连接方式
- 【Spring】基于c3p0连接池,实现数据库加解密连接MySQL数据库
- 运用java进行web开发时常用的连接数据库方式
- 【框架】[Spring] 基于Spring框架的Web应用演示(附带cglib工具进行动态代理)
- Spring连接数据库的几种常用的方式
- Spring boot构建基于rest的Web服务
- 使用Spring Boot快速构建基于SQLite数据源的应用
- 采用Gradle快速构建基于Spring boot的MVC应用
- 基于 JSF+Spring + JPA 构建敏捷的Web应用[88250原创]
- 使用Spring Boot快速构建基于SQLite数据源的应用
- Spring连接数据库的几种常用的方式
- 使用Spring Boot快速构建基于SQLite数据源的应用
- Spring Boot应用连接数据库MySQL
- Spring连接数据库的几种常用的方式
- Spring实战5-基于Spring构建Web应用
- Spring连接数据库的几种常用的方式
- 基于 JSF+Spring + JPA 构建敏捷的Web应用[88250原创]
- 基于spring-boot的web应用,ckeditor上传文件图片文件