企业级博客项目笔记(二)

一、数据持久化

1.JPA简介

  • JPA(Java Persistence API)是用于管理Java EE 和Java SE 环境中的持久化,以及对象/关系映射的Java API
  • 封装JPA的框架有:EclipseLink、Hibernate、Apache OpenJPA
  • 注意:实体实例被当做值以分离对象的方式进行传递(例如通过会话bean的远程业务接口),则该类必须实现Serializable接口---序列化接口
  • 关系:
    • 一对一:@OneToOne
    • 一对多:@OneToMany
    • 多对一:@ManyToOne
    • 多对多:@ManyToMany

2.EntityManager

  • EntityManager接口

    • 定义用于与持久性上下文进行交互的方法
    • 创建和删除持久实体实例,通过实体的主键查找实体
    • 允许在实体上运行查询
  • 获取EntityManager实例:
@PersistenceUnit
EntityManagerFactory emf;
EntityManager em;
@Resource
UserTransaction utx;
...
em=emf.createEntityManager();
try{utx.begin();em.persist(SomeEntity);em.merge(AnotherEntity);em.remove(ThirdEntity);utx.commit();
}catch(Exception e){utx.rollback();
}
  • 查找实体
@PersistenceContext
EntityManager em;
public void enterOrder(int custID,CustomerOrder newOrder){Customer cust=em.find(Customer.class,custID);cust.getOrders().add(newOrder);newOrder.setCustomer(cust);
}

3.Spring Data JPA

  • Spring Data JPA简介

    • 是更大的Spring Data家族的一部分
    • 对基于JPA的数据访问层的增强支持
    • 更容易构建基于使用Spring数据访问技术栈的应用程序
  • CrudRepository接口:声明增删改查的方法
  • PagingAndSortingRepository接口:声明分页和排序的方法
  • Spring Data JPA 自定义接口(继承Repository接口)
    • 根据方法名创建查询
public interface PersonRepository extends Repository<User,Long>{List<Person> findByEmailAddressAndLastname(EmailAddress emailAddress,String lastname);...
}

二、Spring Data JPA、Hibernate与Spring Boot集成

1.配置环境

  • MySQL Community Server 5.7.17
  • Spring Data JPA 1.11.1.RELEASE
  • Hibernate 5.2.8.Final
  • MySQL Connector/J 6.0.5

2.修改build.gradle

//依赖关系
dependencies{...//添加Spring Data JPA 的依赖compile('org.springframework.boot:spring-boot-starter-data-jpa')//添加MySQL连接驱动的依赖compile('mysql:mysql-connector-java:6.0.5')//添加H2数据库依赖runtime('com.h2database:h2:1.4.193')...
}
buildscript{...//自定义Hibernate的版本ext['hibernate.version'] = '5.2.8.Final'...
}

3.验证集成是否成功

  • 打开cmd,运行gradlew bootRun
  • 打开浏览器访问项目,创建用户成功,说明集成成功

三、数据持久化实战

1.后台编码

  • User.java
@Entity //实体
public class User {@Id  //主键@GeneratedValue(strategy = GenerationType.IDENTITY) //主键生成策略:自增private Long id; //实体的唯一标识private String name; //用户名称private String email; //用户邮箱protected User(){}   //无参构造函数,设为protected防止直接使用public User(Long id,String name,String email){this.id=id;this.name=name;this.email=email;}public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getEmail() {return email;}public void setEmail(String email) {this.email = email;}@Override   //重写toString方法public String toString(){return String.format("User[id=%d,name='%s',email='%s']",id,name,email);}
}
  • UserRepository.java
public interface UserRepository extends CrudRepository<User,Long> {}
  • UserController.java
@RestController
@RequestMapping("/users")
public class UserController {@Autowiredprivate UserRepository userRepository;/*** 获取用户列表* @param model* @return*/@GetMappingpublic ModelAndView list(Model model){model.addAttribute("userList",userRepository.findAll());model.addAttribute("title","用户管理");return new ModelAndView("users/list","userModel",model);}/*** 根据id查询用户* @param id* @param model* @return*/@GetMapping("{id}")public ModelAndView view(@PathVariable("id")Long id, Model model){User user=userRepository.findOne(id);model.addAttribute("user",user);model.addAttribute("title","查看用户");return new ModelAndView("users/view","userModel",model);}/*** 获取创建表单页面* @param model* @return*/@GetMapping("/form")public ModelAndView createForm(Model model){model.addAttribute("user",new User(null,null,null));model.addAttribute("title","创建用户");return new ModelAndView("users/form","userModel",model);}/*** 更新用户* @param user* @return*/@PostMappingpublic ModelAndView saveOrUpdateUser(User user){user=userRepository.save(user);return new ModelAndView("redirect:/users");}/*** 根据id删除用户* @param id* @return*/@GetMapping("/delete/{id}")public ModelAndView delete(@PathVariable("id")Long id){userRepository.delete(id);return new ModelAndView("redirect:/users");}/*** 根据id修改用户* @param id* @param model* @return*/@GetMapping("/modify/{id}")public ModelAndView modify(@PathVariable("id")Long id,Model model){User user=userRepository.findOne(id);model.addAttribute("user",user);model.addAttribute("title","修改用户");return new ModelAndView("users/form","userModel",model);}}

2.查看H2数据库

  • 修改application.properties 
    #使用H2控制台 
    spring.h2.console.enable=true
  • 浏览器访问:localhost:8080/h2-console
  • JDBC URL:jdbc:h2:mem:testdb

四、数据持久化到MySQL数据库

1. 修改application.properties

#DataSource
spring.datasource.url=jdbc:mysql://localhost/blog?useSSL=false&serverTimezone=UTC&characterEncoding=utf-8
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver#JPA
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=create-drop

2.运行项目

  • 启动MySQL Server
  • 创建blog数据库
  • 运行项目

五、全文搜索

1.全文搜索简介

  • 数据结构

    • 结构化:指具有固定格式或有限长度的数据,如数据库,元数据等。
    • 非结构化:指不定长或无固定格式的数据,如邮件,word文档等。
  • 非结构化数据的检索
    • 顺序扫描法(Serial Scanning)
    • 全文搜索(Full-text Search):将非结构化的数据转为结构化的数据。
  • 全文搜索实现原理
    • 建立文本库
    • 建立索引
    • 执行搜索
    • 过滤结果
  • 基于Java的开源实现
    • Lucene:开源全文搜索引擎
    • ElasticSearch:基于Lucene的全文检索框架,实时搜索效率高
    • Solr:类似ElasticSearch,基于zookeeper的分布式管理

2.ElasticSearch简介

  • 高度可扩展的开源全文搜索和分析引擎
  • 快速地、近实时地对大数据进行存储、搜索和分析
  • 用来支撑有复杂的数据搜索需求的企业级应用

3.ElasticSearch的特点

  • 分布式
  • 高可用
  • 多类型
  • 多API
  • 面向文档
  • 异步写入
  • 近实时
  • 基于Lucene
  • Apache协议

4.ElasticSearch核心概念

  • 近实时:每隔n秒进行刷新,新创建的索引保存在文件系统中,在刷新的时候被存入。
  • 集群:一个或多个节点的集合,保存应用的所有数据。每一个集群都有一个名称。
  • 节点:一个单台服务器,用来保存数据,并参与整个集群的索引和操作。
  • 索引:用来加快搜索速度、是所有文档的集合。
  • 类型:根据文档的属性来划分类型。
  • 文档:进行索引的基本单位,使用json格式表示。
  • 分片:将索引分配到不同的节点中。
  • 副本:为了防止数据丢失,增加吞吐量。

5.Elasticsearch与Spring Boot集成

  • 配置环境

    • Elasticsearch 2.4.4
    • Spring Data Elasticsearch 2.1.3.RELEASE
    • JNA 4.3.9 --->访问操作系统原生应用
  • 修改build.gradle
//依赖关系
dependencies{...//添加 Spring Data ElasticSearch的依赖compile('org.springframework.boot:spring-boot-starter-data-elasticsearch')//添加JNA的依赖compile('net.java.dev.jna:jna:4.3.0')...
}

6.Elasticsearch实战

  • 修改application.properties
# Elasticsearch服务地址
spring.data.elasticsearch.cluster-nodes=localhost:9300
# 设置连接超时时间
spring.data.elasticsearch.properties.transport.tcp.connect_timeout=120s
  • 后台编码:

    • 文档 EsBlog
    • 资源库EsBlogRepository
    • 资源库测试用例 EsBlogRepositoryTest
    • 控制器 BlogController
  • EsBlog

    package com.zhuyong.domain.es;import org.springframework.data.elasticsearch.annotations.Document;import javax.persistence.Id;import java.io.Serializable;/*** @Author: zy* @Description: * @Date: 2018/6/19_14:19**/@Document(indexName = "blog",type = "blog")   //文档public class EsBlog implements Serializable{private static final long serialVersionUID=1L;@Id   //主键private String id;private String title;private String summary; //摘要private String content; //正文内容protected EsBlog(){   //JPA 规范要求,防止直接使用}public EsBlog(String title,String summary,String content){this.title=title;this.summary=summary;this.content=content;}public String getId() {return id;}public void setId(String id) {this.id = id;}public String getTitle() {return title;}public void setTitle(String title) {this.title = title;}public String getSummary() {return summary;}public void setSummary(String summary) {this.summary = summary;}public String getContent() {return content;}public void setContent(String content) {this.content = content;}@Overridepublic String toString(){return String.format("EsBlog[id='%s',title='%s',summary='%s'],content='%s'",id,title,summary,content);}}
  • EsBlogRepository
    package com.zhuyong.repository.es;import com.zhuyong.domain.es.EsBlog;import org.springframework.data.domain.Page;import org.springframework.data.domain.Pageable;import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;/*** @Author: zy* @Description: EsBlog Repository 接口* @Date: 2018/6/19_13:48**/public interface EsBlogRepository extends ElasticsearchRepository<EsBlog,String> {/*** @Author: zy* @Description: 分页查询博客(去重)* @Date: 2018/6/20_16:26**/Page<EsBlog>  findDistinctEsBlogByTitleContainingOrSummaryContainingOrContentContaining(String title, String summary, String content, Pageable pageable);}
  • EsBlogRepositoryTest
    package com.zhuyong.repository.es;import com.zhuyong.domain.es.EsBlog;import org.junit.Before;import org.junit.Test;import org.junit.runner.RunWith;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.test.context.SpringBootTest;import org.springframework.data.domain.Page;import org.springframework.data.domain.PageRequest;import org.springframework.data.domain.Pageable;import org.springframework.test.context.junit4.SpringRunner;import static org.assertj.core.api.Assertions.assertThat;/*** @Author: zy* @Description: EsBlogRepository接口测试* @Date: 2018/6/20_16:29**/@RunWith(SpringRunner.class)@SpringBootTestpublic class EsBlogRepositoryTest {@Autowiredprivate EsBlogRepository esBlogRepository;@Beforepublic void initRepositoryData(){//清除所有数据esBlogRepository.deleteAll();esBlogRepository.save(new EsBlog("登鹳雀楼","王之涣的登鹳雀楼","白日依山尽,黄河入海流。欲穷千里目,更上一层楼。"));esBlogRepository.save(new EsBlog("相思","王维的相思","红豆生南国,春来发几枝。愿君多采撷,此物最相思。"));esBlogRepository.save(new EsBlog("静夜思","李白的静夜思","床前明月光,疑是地上霜。举头望明月,低头思故乡。"));}@Testpublic void findDistinctEsBlogByTitleContainingOrSummaryContainingOrContentContaining() throws Exception {Pageable pageable=new PageRequest(0,20);String title="思";String summary="相思";String content="相思";Page<EsBlog> page=esBlogRepository.findDistinctEsBlogByTitleContainingOrSummaryContainingOrContentContaining(title,summary,content,pageable);assertThat(page.getTotalElements()).isEqualTo(2);System.out.println("----------------start 1");for(EsBlog blog:page.getContent()){System.out.println(blog.toString());}System.out.println("----------------end 1");}}
  • BlogController
    package com.zhuyong.controller;import com.zhuyong.domain.es.EsBlog;import com.zhuyong.repository.es.EsBlogRepository;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.data.domain.Page;import org.springframework.data.domain.PageRequest;import org.springframework.data.domain.Pageable;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.bind.annotation.RestController;import java.util.List;/*** @Author: zy* @Description: Blog 控制器* @Date: 2018/6/20_17:02**/@RestController@RequestMapping("/blogs")public class BlogController {@Autowiredprivate EsBlogRepository esBlogRepository;@GetMapping()public List<EsBlog> list(@RequestParam(value="title") String title,@RequestParam(value="summary") String summary,@RequestParam(value="content") String content,@RequestParam(value="pageIndex",defaultValue= "0") int pageIndex,@RequestParam(value="pageSize",defaultValue = "10") int pageSize){//数据在Test中初始化Pageable pageable=new PageRequest(pageIndex,pageSize);Page<EsBlog> page=esBlogRepository.findDistinctEsBlogByTitleContainingOrSummaryContainingOrContentContaining(title,summary,content,pageable);return page.getContent();}}

企业级博客项目笔记(二)相关推荐

  1. 初出茅庐的小李第113篇博客项目笔记之机智云智能浇花器实战(2)-基础Demo实现

    初出茅庐的小李第112篇博客项目笔记之机智云智能浇花器实战(1)-基础Demo实现 接(1) 继电器实现 继电器原理图 继电器采用的是5V继电器,控制端是RELAY-1 继电器代码实现 #includ ...

  2. Node.js从零开发Web Server博客项目笔记

    代码运行流程 首先开启服务器,在npm run dev的时候运行了bin目录下的www.js文件,启动http服务 当前端进行访问的时候,经过app.js文件 App.js是整个项目的入口文件,首先判 ...

  3. 初出茅庐的小李第114篇博客项目笔记之机智云智能浇花器实战(3)-基础Demo实现

    机智云智能浇花器实战(3)-基础Demo实现 链接:机智云智能浇花器实战(2)-基础Demo实现 BH1750光照传感器原理图 BH1750传感器代码 #include "bh1750.h& ...

  4. 初出茅庐的小李第112篇博客项目笔记之机智云智能浇花器实战(1)-基础Demo实现

    项目文件夹框架 API文件夹---------------------------------------放置各种传感器驱动代码文件夹 CMSIS文件夹------------------------ ...

  5. NET使用ABP框架搭建博客项目(二) 用户模块

    首先我们先来设计下用户模块,简单用户模块设计涵盖两个类,用户表以及角色表.如下图: 我们在Core项目中增加一个文件夹Domain,在Domain增加Customers文件夹,添加一个枚举Passwo ...

  6. 博客项目学习笔记十二:登录注册功能(登录)

    博客项目目录: 请戳这里 准备 需求:实现用户登录功能,登录之后,跳转到首页,并且页面信息由游客状态变为用户状态 1.引入shiro依赖包 <dependency><groupId& ...

  7. 基于 abp vNext 和 .NET Core 开发博客项目 - Blazor 实战系列(二)

    基于 abp vNext 和 .NET Core 开发博客项目 - Blazor 实战系列(二) 转载于:https://github.com/Meowv/Blog 上一篇搭建了 Blazor 项目并 ...

  8. 基于 abp vNext 和 .NET Core 开发博客项目 - 博客接口实战篇(二)

    基于 abp vNext 和 .NET Core 开发博客项目 - 博客接口实战篇(二) 转载于:https://github.com/Meowv/Blog 上篇文章完成了两个接口:文章列表页.文章详 ...

  9. 基于 abp vNext 和 .NET Core 开发博客项目 - 定时任务最佳实战(二)

    基于 abp vNext 和 .NET Core 开发博客项目 - 定时任务最佳实战(二) 转载于:https://github.com/Meowv/Blog 本篇继续来完成一个全网各大平台的热点新闻 ...

最新文章

  1. Linux中与命令相关的命令
  2. 【Android 应用开发】Android 网络编程 API笔记 - java.net 包相关 接口 api
  3. 下面中???该如何填写,才可以正确执行强制类型转换? int (*monthp)[31]; monthp = (???)malloc(31);
  4. jquery2.0.3 全部源码
  5. Linux 操作系统基础知识
  6. 阿里云原生数据库POLARDB压力测试报告
  7. 电线电缆行业MES解决方案
  8. Win11怎么添加pdf虚拟打印机
  9. 达梦数据库报网络通讯异常排查步骤
  10. 【DVB】【Cert】DVD相关认证简介
  11. c++面试常见问题2019-10-03
  12. 阿里云自建k8s存储插件csi安装使用
  13. 数字电路的一些基本知识
  14. 基于中台的公共图书馆数据服务研究
  15. 千锋教育+计算机四级网络-计算机网络学习-02
  16. Rust学习第九天——控制测试运行
  17. HDU2955 01背包
  18. poj-2491-Scavenger Hunt
  19. ICN(Information-Centric Networking)初步介绍
  20. 推广图书赚佣金,10个就够一套《大话计算机》

热门文章

  1. kubernetes 集群状态异常 [ connect: connection refused ]
  2. 张一鸣:每个逆袭的年轻人,都具备的底层能力(转)
  3. ubuntu下evince中文乱码解决方法
  4. 自考本科税收筹划可以带计算机吗,2015年4月湖南自考本科:05175 税收筹划最新考前资料...
  5. 化妆品致敏成分识别——python图像处理之文字识别+匹配
  6. kafka工作原理介绍
  7. Spring Boot Ajax实例(十六)
  8. UGC内容平台的全栈式内容风控
  9. 【转载】/usr/bin/ld: cannot find -lxxx 问题总结
  10. Ngxin禁止IP+端口号访问系统,设置只能通过域名访问