工程公司网站建设,国外 网站网站,网站建设进度表下载,视频网站的服务器多大From: https://www.cnblogs.com/paddix/p/8178943.html 上篇文章中已经通过一个简单的HelloWorld程序讲解了Spring boot的基本原理和使用。本文主要讲解如何通过spring boot来访问数据库#xff0c;本文会演示三种方式来访问数据库#xff0c;第一种是JdbcTemplate#xff0…From: https://www.cnblogs.com/paddix/p/8178943.html 上篇文章中已经通过一个简单的HelloWorld程序讲解了Spring boot的基本原理和使用。本文主要讲解如何通过spring boot来访问数据库本文会演示三种方式来访问数据库第一种是JdbcTemplate第二种是JPA第三种是Mybatis。之前已经提到过本系列会以一个博客系统作为讲解的基础所以本文会讲解文章的存储和访问但不包括文章的详情因为最终的实现是通过MyBatis来完成的所以对于JdbcTemplate和JPA只做简单演示MyBatis部分会完整实现对文章的增删改查。
一、准备工作 在演示这几种方式之前需要先准备一些东西。第一个就是数据库本系统是采用MySQL实现的我们需要先创建一个tb_article的表 1 2 3 4 5 6 7 8 9 10 11 12 13 14 DROP TABLE IF EXISTS tb_article; CREATE TABLE tb_article ( id bigint(20) NOT NULL AUTO_INCREMENT, title varchar(255) NOT NULL DEFAULT , summary varchar(1024) NOT NULL DEFAULT , status int(11) NOT NULL DEFAULT 0, type int(11) NOT NULL, user_id bigint(20) NOT NULL DEFAULT 0, create_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, update_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, public_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id) ) ENGINEInnoDB DEFAULT CHARSETutf8; 后续的演示会对这个表进行增删改查大家应该会看到这个表里面并没有文章的详情原因是文章的详情比较长如果放在这个表里面容易影响查询文章列表的效率所以文章的详情会单独存在另外的表里面。此外我们需要配置数据库连接池这里我们使用druid连接池另外配置文件使用yaml配置即application.yml你也可以使用application.properties配置文件没什么太大的区别如果对ymal不熟悉有兴趣也可以查一下比较简单。连接池的配置如下 1 2 3 4 5 6 7 spring: datasource: url: jdbc:mysql://127.0.0.1:3306/blog?useUnicodetruecharacterEncodingUTF-8useSSLfalse driverClassName: com.mysql.jdbc.Driver username: root password: 123456 type: com.alibaba.druid.pool.DruidDataSource 最后我们还需要建立与数据库对应的POJO类代码如下 1 2 3 4 5 6 7 8 9 public class Article { private Long id; private String title; private String summary; private Date createTime; private Date publicTime; private Date updateTime; private Long userId; private Integer status;br private Integer type;brbr} 好了需要准备的工作就这些现在开始实现数据库的操作。 二、与JdbcTemplate集成 首先我们先通过JdbcTemplate来访问数据库这里只演示数据的插入上一篇文章中我们已经提到过Spring boot提供了许多的starter来支撑不同的功能要支持JdbcTemplate我们只需要引入下面的starter就可以了 1 2 3 4 dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-jdbc/artifactId /dependency 现在我们就可以通过JdbcTemplate来实现数据的插入了 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 public interface ArticleDao { Long insertArticle(Article article); } Repository public class ArticleDaoJdbcTemplateImpl implements ArticleDao { Autowired private NamedParameterJdbcTemplate jdbcTemplate; Override public Long insertArticle(Article article) { String sql insert into tb_article(title,summary,user_id,create_time,public_time,update_time,status) values(:title,:summary,:userId,:createTime,:publicTime,:updateTime,:status); MapString, Object param new HashMap(); param.put(title, article.getTitle()); param.put(summary, article.getSummary()); param.put(userId, article.getUserId()); param.put(status, article.getStatus()); param.put(createTime, article.getCreateTime()); param.put(publicTime, article.getPublicTime()); param.put(updateTime, article.getUpdateTime()); return (long) jdbcTemplate.update(sql, param); } } 我们通过JUnit来测试上面的代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 RunWith(SpringJUnit4ClassRunner.class) SpringBootTest(classes Application.class) public class ArticleDaoTest { Autowired private ArticleDao articleDao; Test public void testInsert() { Article article new Article(); article.setTitle(测试标题); article.setSummary(测试摘要); article.setUserId(1L); article.setStatus(1); article.setCreateTime(new Date()); article.setUpdateTime(new Date()); article.setPublicTime(new Date()); articleDao.insertArticle(article); } } 要支持上面的测试程序也需要引入一个starter 1 2 3 4 5 dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-test/artifactId scopetest/scope /dependency 从上面的代码可以看出其实除了引入jdbc的start之外基本没有配置这都是spring boot的自动帮我们完成了配置的过程。上面的代码需要注意的Application类的位置该类必须位于Dao类的父级的包中比如这里Dao都位于com.pandy.blog.dao这个包下现在我们把Application.java这个类从com.pandy.blog这个包移动到com.pandy.blog.app这个包中则会出现如下错误 1 2 3 4 5 6 Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type com.pandy.blog.dao.ArticleDao available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {org.springframework.beans.factory.annotation.Autowired(requiredtrue)} at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1493) at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1104) at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066) at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:585) ... 28 more 也就是说找不到ArticleDao的实现这是什么原因呢上一篇博文中我们已经看到SpringBootApplication这个注解继承了ComponentScan其默认情况下只会扫描Application类所在的包及子包。因此对于上面的错误除了保持Application类在Dao的父包这种方式外也可以指定扫描的包来解决 1 2 3 4 5 6 7 SpringBootApplication ComponentScan({com.pandy.blog}) public class Application { public static void main(String[] args) throws Exception { SpringApplication.run(Application.class, args); } } 三、与JPA集成 现在我们开始讲解如何通过JPA的方式来实现数据库的操作。还是跟JdbcTemplate类似首先我们需要引入对应的starter 1 2 3 4 dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-data-jpa/artifactId /dependency 然后我们需要对POJO类增加Entity的注解并指定表名如果不指定默认的表名为article然后需要指定ID的及其生成策略这些都是JPA的知识与Spring boot无关如果不熟悉的话可以看下JPA的知识点 1 2 3 4 5 6 7 8 9 10 11 12 13 Entity(name tb_article) public class Article { Id GeneratedValue private Long id; private String title; private String summary; private Date createTime; private Date publicTime; private Date updateTime; private Long userId; private Integer status; } 最后我们需要继承JpaRepository这个类这里我们实现了两个查询方法第一个是符合JPA命名规范的查询JPA会自动帮我们完成查询语句的生成另一种方式是我们自己实现JPQLJPA支持的一种类SQL的查询。 1 2 3 4 5 6 7 public interface ArticleRepository extends JpaRepositoryArticle, Long { public ListArticle findByUserId(Long userId); Query(select art from com.pandy.blog.po.Article art where title:title) public ListArticle queryByTitle(Param(title) String title); } 好了我们可以再测试一下上面的代码 1 2 3 4 5 6 7 8 9 10 11 12 RunWith(SpringJUnit4ClassRunner.class) SpringBootTest(classes Application.class) public class ArticleRepositoryTest { Autowired private ArticleRepository articleRepository; Test public void testQuery(){ ListArticle articleList articleRepository.queryByTitle(测试标题); assertTrue(articleList.size()0); } } 注意这里还是存在跟JdbcTemplate类似的问题需要将Application这个启动类未于Respository和Entity类的父级包中否则会出现如下错误 1 2 3 4 5 6 Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type com.pandy.blog.dao.ArticleRepository available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {org.springframework.beans.factory.annotation.Autowired(requiredtrue)} at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1493) at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1104) at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066) at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:585) ... 28 more 当然同样也可以通过注解EnableJpaRepositories指定扫描的JPA的包但是还是不行还会出现如下错误 1 2 3 4 5 6 7 8 9 10 11 12 13 14 Caused by: java.lang.IllegalArgumentException: Not a managed type: class com.pandy.blog.po.Article at org.hibernate.jpa.internal.metamodel.MetamodelImpl.managedType(MetamodelImpl.java:210) at org.springframework.data.jpa.repository.support.JpaMetamodelEntityInformation.init(JpaMetamodelEntityInformation.java:70) at org.springframework.data.jpa.repository.support.JpaEntityInformationSupport.getEntityInformation(JpaEntityInformationSupport.java:68) at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getEntityInformation(JpaRepositoryFactory.java:153) at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:100) at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:82) at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:199) at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.initAndReturn(RepositoryFactoryBeanSupport.java:277) at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.afterPropertiesSet(RepositoryFactoryBeanSupport.java:263) at org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean.afterPropertiesSet(JpaRepositoryFactoryBean.java:101) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1687) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1624) ... 39 more 这个错误说明识别不了Entity所以还需要通过注解EntityScan来指定Entity的包最终的配置如下 1 2 3 4 5 6 7 8 9 SpringBootApplication ComponentScan({com.pandy.blog}) EnableJpaRepositories(basePackagescom.pandy.blog) EntityScan(com.pandy.blog) public class Application { public static void main(String[] args) throws Exception { SpringApplication.run(Application.class, args); } } 四、与MyBatis集成 最后我们再看看如何通过MyBatis来实现数据库的访问。同样我们还是要引入starter 1 2 3 4 5 dependency groupIdorg.mybatis.spring.boot/groupId artifactIdmybatis-spring-boot-starter/artifactId version1.1.1/version /dependency 由于该starter不是spring boot官方提供的所以版本号于Spring boot不一致需要手动指定。 MyBatis一般可以通过XML或者注解的方式来指定操作数据库的SQL个人比较偏向于XML所以本文中也只演示了通过XML的方式来访问数据库。首先我们需要配置mapper的目录。我们在application.yml中进行配置 1 2 3 4 mybatis: config-locations: mybatis/mybatis-config.xml mapper-locations: mybatis/mapper/*.xml type-aliases-package: com.pandy.blog.po 这里配置主要包括三个部分一个是mybatis自身的一些配置例如基本类型的别名。第二个是指定mapper文件的位置第三个POJO类的别名。这个配置也可以通过 Java configuration来实现由于篇幅的问题我这里就不详述了有兴趣的朋友可以自己实现一下。 配置完后我们先编写mapper对应的接口 1 2 3 4 5 6 7 8 9 10 11 12 public interface ArticleMapper { public Long insertArticle(Article article); public void updateArticle(Article article); public Article queryById(Long id); public ListArticle queryArticlesByPage(Param(article) Article article, Param(pageSize) int pageSize, Param(offset) int offset); } 该接口暂时只定义了四个方法即添加、更新以及根据ID查询和分页查询。这是一个接口并且和JPA类似可以不用实现类。接下来我们编写XML文件 View Code 最后我们需要手动指定mapper扫描的包 1 2 3 4 5 6 7 SpringBootApplication MapperScan(com.pandy.blog.dao) public class Application { public static void main(String[] args) throws Exception { SpringApplication.run(Application.class, args); } } 好了与MyBatis的集成也完成了我们再测试一下 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 RunWith(SpringJUnit4ClassRunner.class) SpringBootTest(classes Application.class) public class ArticleMapperTest { Autowired private ArticleMapper mapper; Test public void testInsert() { Article article new Article(); article.setTitle(测试标题2); article.setSummary(测试摘要2); article.setUserId(1L); article.setStatus(1); article.setCreateTime(new Date()); article.setUpdateTime(new Date()); article.setPublicTime(new Date()); mapper.insertArticle(article); } Test public void testMybatisQuery() { Article article mapper.queryById(1L); assertNotNull(article); } Test public void testUpdate() { Article article mapper.queryById(1L); article.setPublicTime(new Date()); article.setUpdateTime(new Date()); article.setStatus(2); mapper.updateArticle(article); } Test public void testQueryByPage(){ Article article new Article(); article.setUserId(1L); ListArticle list mapper.queryArticlesByPage(article,10,0); assertTrue(list.size()0); } } 五、总结 本文演示Spring boot与JdbcTemplate、JPA以及MyBatis的集成整体上来说配置都比较简单以前做过相关配置的同学应该感觉比较明显Spring boot确实在这方面给我们提供了很大的帮助。后续的文章中我们只会使用MyBatis这一种方式来进行数据库的操作这里还有一点需要说明一下的是MyBatis的分页查询在这里是手写的这个分页在正式开发中可以通过插件来完成不过这个与Spring boot没什么关系所以本文暂时通过这种手动的方式来进行分页的处理。