企业级博客项目笔记(二)
企业级博客项目笔记(二)
一、数据持久化
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();}}
企业级博客项目笔记(二)相关推荐
- 初出茅庐的小李第113篇博客项目笔记之机智云智能浇花器实战(2)-基础Demo实现
初出茅庐的小李第112篇博客项目笔记之机智云智能浇花器实战(1)-基础Demo实现 接(1) 继电器实现 继电器原理图 继电器采用的是5V继电器,控制端是RELAY-1 继电器代码实现 #includ ...
- Node.js从零开发Web Server博客项目笔记
代码运行流程 首先开启服务器,在npm run dev的时候运行了bin目录下的www.js文件,启动http服务 当前端进行访问的时候,经过app.js文件 App.js是整个项目的入口文件,首先判 ...
- 初出茅庐的小李第114篇博客项目笔记之机智云智能浇花器实战(3)-基础Demo实现
机智云智能浇花器实战(3)-基础Demo实现 链接:机智云智能浇花器实战(2)-基础Demo实现 BH1750光照传感器原理图 BH1750传感器代码 #include "bh1750.h& ...
- 初出茅庐的小李第112篇博客项目笔记之机智云智能浇花器实战(1)-基础Demo实现
项目文件夹框架 API文件夹---------------------------------------放置各种传感器驱动代码文件夹 CMSIS文件夹------------------------ ...
- NET使用ABP框架搭建博客项目(二) 用户模块
首先我们先来设计下用户模块,简单用户模块设计涵盖两个类,用户表以及角色表.如下图: 我们在Core项目中增加一个文件夹Domain,在Domain增加Customers文件夹,添加一个枚举Passwo ...
- 博客项目学习笔记十二:登录注册功能(登录)
博客项目目录: 请戳这里 准备 需求:实现用户登录功能,登录之后,跳转到首页,并且页面信息由游客状态变为用户状态 1.引入shiro依赖包 <dependency><groupId& ...
- 基于 abp vNext 和 .NET Core 开发博客项目 - Blazor 实战系列(二)
基于 abp vNext 和 .NET Core 开发博客项目 - Blazor 实战系列(二) 转载于:https://github.com/Meowv/Blog 上一篇搭建了 Blazor 项目并 ...
- 基于 abp vNext 和 .NET Core 开发博客项目 - 博客接口实战篇(二)
基于 abp vNext 和 .NET Core 开发博客项目 - 博客接口实战篇(二) 转载于:https://github.com/Meowv/Blog 上篇文章完成了两个接口:文章列表页.文章详 ...
- 基于 abp vNext 和 .NET Core 开发博客项目 - 定时任务最佳实战(二)
基于 abp vNext 和 .NET Core 开发博客项目 - 定时任务最佳实战(二) 转载于:https://github.com/Meowv/Blog 本篇继续来完成一个全网各大平台的热点新闻 ...
最新文章
- Linux中与命令相关的命令
- 【Android 应用开发】Android 网络编程 API笔记 - java.net 包相关 接口 api
- 下面中???该如何填写,才可以正确执行强制类型转换? int (*monthp)[31]; monthp = (???)malloc(31);
- jquery2.0.3 全部源码
- Linux 操作系统基础知识
- 阿里云原生数据库POLARDB压力测试报告
- 电线电缆行业MES解决方案
- Win11怎么添加pdf虚拟打印机
- 达梦数据库报网络通讯异常排查步骤
- 【DVB】【Cert】DVD相关认证简介
- c++面试常见问题2019-10-03
- 阿里云自建k8s存储插件csi安装使用
- 数字电路的一些基本知识
- 基于中台的公共图书馆数据服务研究
- 千锋教育+计算机四级网络-计算机网络学习-02
- Rust学习第九天——控制测试运行
- HDU2955 01背包
- poj-2491-Scavenger Hunt
- ICN(Information-Centric Networking)初步介绍
- 推广图书赚佣金,10个就够一套《大话计算机》
热门文章
- kubernetes 集群状态异常 [ connect: connection refused ]
- 张一鸣:每个逆袭的年轻人,都具备的底层能力(转)
- ubuntu下evince中文乱码解决方法
- 自考本科税收筹划可以带计算机吗,2015年4月湖南自考本科:05175 税收筹划最新考前资料...
- 化妆品致敏成分识别——python图像处理之文字识别+匹配
- kafka工作原理介绍
- Spring Boot Ajax实例(十六)
- UGC内容平台的全栈式内容风控
- 【转载】/usr/bin/ld: cannot find -lxxx 问题总结
- Ngxin禁止IP+端口号访问系统,设置只能通过域名访问