SpringBoot 中的数据访问
Docker
CentOS安装命令
sudo yum update
sudo yum install docker
Ubuntu安装命令
sudo apt-get update
sudo apt-get docker.io
Windows下安装
windows运行Docker是通过Boot2Docker(https://github.com/boot2docker/windows-installer/releases/latest)实现的
这个软件包含一个VirtualBox,只适合开发测试,不适合生产环境
安装前确认电脑的BIOS设置中的CPU虚拟化技术支持已经开启
Docker的镜像都是放在Docker官网https://registry.hub.docker.com
docker search redis # 检索redis
docker pull redis # 下载redis镜像
docker images #查看本地镜像列表
docker rmi image-id #删除指定镜像
docker rmi ${docker images -q} #删除所有镜像
docker run --name test-redis -d redis #运行一个Redis容器
docker ps #查看运行中的容器列表
docker ps -a #查看运行和停止状态的容器
docker stop test-redis #停止redis容器
docker start test-redis #启动redis容器
docker rm container-id #删除指定id的容器
docker rm $(docker ps -a -q) #删除所有容器
docker logs container-name/container-id #查看当前容器日志
#例如查看redis容器的日志
docker logs port-redis
# 映射容器的6379端口到本机的6378端口
docker run -d -p 6378:6379 --name port-redis redis
docker exec -it container-id/container-name bash #登录并访问当前容器,通过exit命令退出登录
# 将容器的Oracle XE管理界面的8080端口映射为本机的9090端口,将Oracle XE的1521端口映射为 本机的1521端口
docker run -d -p 9090:8080 -p 1521:1521 wnameless/oracle-xe-llg
容器:
hostname:localhost
端口:1521
SID:XE
username:system/sys
password:oracle
管理界面:
url: http://localhost:9090/apes
workspace:internal
username:admin
password:oracle
Spring Data JPA
属于Spring Data的一个子项目,通过提供基于JPA的Repository减少了JPA作为数据访问方案的代码量
①、继承JpaRepository意味着默认有了数据访问的操作方法
public interface PersonRepository extends JpaRepository<Person,Long>{
//定义数据访问操作的方法
}
②、配置使用Spring Data JPA
@Configuration
@EnableJpaRepositories("com.wisely.repos")//开启JPA,并扫描包下接口
public class JpaConfiguration{
@Bean
public EntityManagerFactory entityManagerFactory(){
}
}
③、定义查询方法
表——实体类
Ⅰ、根据属性名查询
public interface PersonRepository extends JpaRepository<Person,Long>{
//select p from Person p where p.name=?1
List<Person> findByName(String name);
//select p from Person p where p.name like ?1
List<Person> findByNameLike(String name);
//select p from Person p where p.name=?1 and p.address=?2
List<Person> findByNameAndAddress(String name,String address);
//获得符合查询条件的钱10条数据
List<Person> findFirst10ByName(String name);
//获得符合查询条件的前30条数据
List<Person> findTop30ByName(String name);
}
Ⅱ、使用JPA的NamedQuery查询
即一个名称映射一个查询语句
@Entity
@NamedQuery(name="Person.findByName",query="select p from Person p where p.name=?1")
public class Person{
}
public interface PersonRepository extends JpaRepository<>{
//使用NamedQuery里定义的查询语句,而不是根据方法名查询
List<Person> findByName(String name);
}
Ⅲ、使用@Query查询
public interface PersonRepository extends JpaRepository<Person,Long>{
//使用参数索引查询
@Query("select p from Peron p where p.address=?1")
List<Person> findByAddress(String address);
//使用命名参数
@Query("select p from Person p where p.address=:address")
List<Person> findByAddress(@Param("address") String address);
//@Modifying和@Query组合注解来更新查询,返回值表示影响的行数
@Modifying
@Transactional
@Query("update Person p set p.name=?1")
int setName(String name);
}
Ⅳ、Specification规范接口构造条件查询
//接口必须实现JpaSpecificationExecutor
public interface PersonRepository extends JpaRepository<Person,Long>,JpaSpecificationExecutor<Person>{
}
//定义Criterial查询
public class CustomerSpecs{
public static Specification<Person> personFromHefei(){
//使用Root获取需要查询的属性,查询所有来自合肥的人
@Override
public Predicate toPredicate(Root<Person> root,CriteriaQuery<?> query,CriteriaBuilder cb){
return cb.equal(root.get("address"),"合肥");
}
}
}
List<Person> people = personRespository.findAll(personFromHefei());
Ⅴ、排序与分页
//定义
public interface PersonRepository extends JpaRepository<Person,Long>{
List<Person> findByName(String name,Sort sort);
Page<Person> findByName(String name,Pageable pageable);
}
//使用排序
List<Person> people = personRepository.findByName("xx",new Sort(Direction.ASC,"age"));
Sort(Direction.ASC,"age")
//使用分页(获得当前页面的记录、总页数、总记录数、是否有上一页或下一页)
Page<Person> people2 = personRespository.findByName("xx",new PageRequest(0,10));
一、新建项目
依赖:spring-boot-starter-data-jpa spring-boot-starter-web ojdbc6 guava(包含Java常用工具类)
Maven中心库没有OracleJDBC驱动,需要通过Maven进行打包到本地仓库
Oracle官网下载ojdbc6.jar 通过控制台命令mvn install:install-file -DgroupId=com.oracle “-DartifactId=ojdbc6” -Dversion=11.2.0.2.0" “-Dpackaging=jar” “-Dfile=E:\odjbc6.jar”
- -DgroupId=com.oracle 指定当钱包的groupId为com.oracle
- -DartifactId=odjbc6 指定当前包的artifactfactId为ojdbc6
- -Dversion=11.2.0.2.0 指定当钱包version为11.2.0.2.0
- -Dfile=E:\odjbc6.jar 指定要打包的jar文件位置
新建一个data.sql放置在src/main/resources下,内容向表中增加一些数据
二、配置基本属性
appliation.properties里配置数据源和jpa的相关属性
spring.datasource.driverClassName=oracle.jdbc.OracleDriver
spring.datasource.url=jdbc\:oracle\:thin\:@localhost\:1521\:xe
spring.datasource.username=boot
spring.datasource.password=boot
#hibernate提供根据实体类自动维护数据表结构的功能(create create-drop update validate none)
spring.jpa.hibernate.ddl-auto=update
#控制台现实sql
spring.jpa.show-sql=true
#控制器输出json字符串格式
spring.jackson.serialization.indent_output=true
三、定义实体类映射
@Entity //指明实体类
@NamedQuery(name="Person.withNameAndAddressNamedQuery",query="select p from Person p where p.name=?1 and address=?2")
public class Person {
@Id//指明这个属性映射为数据库的主键
@GeneratedValue//默认主键生成方式为自增,hibernate会自动生成一个名为HIBERNATE_SEQUENCE的序列
private Long id;
private String name;
private Integer age;
private String address;
//省略无参、有参构造和get/set方法
}
四、数据访问接口
public interface PersonRepository extends JpaRepository<Person,Long>{
List<Person> findByAddress(String name);//使用方法名查询
Person findByNameAndAddress(String name,String address);
//使用@Query查询
@Query("select p from Person p where p.name=:name and p.address=:address")
Person withNameAndAddressQuery(@Param("name")String name,@Param("address")String address);
//使用@NamedQuery查询,实体类中做@NamedQuery定义
List<Person> withNameAndAddressNameQuery(String name,String address);
}
五、控制器
@RestController
public class DataController{
//spring data JPA自动注册bean
@Autowired
PersonRepository personRepository;
@RequestMapping("/save")
public Person save(String name,String address,Integer age){
Person p = personRepository.save(new Person(null,name,age,address));
return p;
}
@RequestMapping("/q1")
public List<Person> q1(String address){
List<Person> people = personRepository.findByAddress(address);
return people;
}
@RequestMapping("/q2")
public Person q2(String name,String address){
Person people = personRepository.findByNameAndAddress(name,address);
return people;
}
@RequestMapping("/q3")
public Person q3(String name,String address){
Person p =personRepository.withNameAndAddressQuery(name,address);
return p;
}
@RequestMapping("/q4")
public Person q4(String name,String address){
Person p = personRepository.withNameAndAddressNamedQuery(name,address);
return p;
}
@RequestMapping("/sort")
public List<Person> sort(){
List<Person> people = personRepository.findAll(new Sort(Direction.ASC,"age"));
return people;
}
@RequestMapping("/page")
public Page<Person> page(){
Page<Person> pagePeople = personRepository.findAll(new PageReqeust(1,2));
return pagePeople;
}
}
六、自定义Repository实现自动模糊查询
①、定义Specification
public class CustomerSpecs{
public static <T> Specification<T> byAuto(final EntityManager entityManager,final T example){//
final Class<T> type = (Class<T>) example.getClass();//
return new Specification<T>(){
@Override
public Predicate toPredicate(Root<T> root,CriteriaQuery<?> query,CriteriaBuilder cb){
List<Predicate> predicates = new ArrayList<>();//
EntityType<T> entity = entityManager.getMetaModel().entity(type);//
for(Attribute<T,?> attr:entity.getDeclaredAttributes()){//
Object attrValue = getValue(example,attr);//
if(attrValue != null){
if(attr.getJavaType() == String.class){//
if(!StringUtils.isEmpty(attrValue)){//
predicates.add(cb.like(root.get(attriute(entity,attr.getName(),String.class)),
pattern((String)strValue)));//
}
}else{
predicates.add(cb.equal(root.get(attribute(entity,attr.getName(),attrValue.getClass())),attrValue));
}
}
}
return predicates.isEmpty()?cb.conjunction():cb.and(toArray(predicates,Predicate.class));//
}
private <T> Object getValue(T example,Attribute<T,?> attr){
return ReflectionUtils.getField((Field) attr.getJavaMember(),example);
}
//
private<E,T> SingularAttribute<T,E> attribute(EntityType<T> entity,String filedName,Class<E> fieldClass){
return entity.getDeclaredSingularAttribute(filedName,fieldClass);
}
};
}
//
static private String pattern(String str){
return "%" + str + "%";
}
}
②、定义接口
@NoRepositoryBean
public interface CustomRepository<T,ID extends Serializable> extends JpaRepository<T,ID>,JpaSpecificationExecutor<T>{
Page<T> findByAuto(T example,Pageable pageable);
}
③、定义实现
public class CustomRepositoryImpl<T,ID extends Serializable> extends SimpleJpaRepository<T,ID>
implements CustomRepository<T,ID>{
private final EntityManager entityManager;
public CustomRepositoryImpl(Class<T> domainClass,EntityManager entityManager){
super(domainClass,entityManager);
this.entityManager = entityManager;
}
@Override
public Page<T> findByAuto(T example,Pageable pageable){//构造查询条件,提供分页功能
return finalAll(byAuto(entityManager,example),pageable);
}
}
④、repositoryFactoryBean
public class CustomRepositoryFactoryBean<T extends JpaRepository<S,I>,S,ID extends Serializable>
extends JpaRepositoryFactoryBean<T,S,ID>{
@Override
protected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager){
return new CustomRepositoryFactory(entityManager);
}
private static class CustomRepositoryFactory extends JpaRepositoryFactory{
public CustomRepositoryFactory(EntityManager entityManager){
super(entityManager);
}
@Override
@SupprssWarnings({"unchecked"})
protected <T,ID extends Serializable> SimpleJpaRepository<?,?> getTargetRepository(RepositoryInformation information,
EntityManager entityManager){
return new CustomRepositoryImpl<T,ID>((Class<T>)information.getDomainType(),entityManager);
}
@Override
protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata){
return CustomRepositoryImpl.class;
}
}
}
⑤、使用
只需要让实体类Repository继承自定义的Repository接口,即可使用自定义Repository中实现的功能
public interface PersonRepository
推荐阅读
-
基于 Springboot + Vue 的高校学术交流平台(含源代码数据库)
-
TopK 算法在大数据重复性数据分析中的应用与挑战
-
Matlab 编程示例 24:freexyn 在 b-site 中读取手写 mnist 数据集的 Matlab 代码 -4. 读取和转换 mnist 数据集的 Matlab 程序代码
-
SpringBoot 中的数据访问
-
yolov8/9/11 模型在中医舌象分类中的应用 [代码 + 数据集 + python 环境 + GUI 系统]。
-
在线远程考试|基于 SpringBoot 的在线远程考试系统设计与实施(含项目源代码 + 论文 + 数据库)
-
Nagle 算法:优化 TCP 网络中的小数据包传输
-
Redis 中的其他一些数据类型和渐进式遍历
-
回归预测 | Matlab 基于 SABO-SVR 减平均算法的支持向量机在多输入单输出数据回归预测中的应用优化
-
均衡评估中的数据安全风险评估:企业实践