Spring框架学习(四)SpringData

说是SpringData,其实其中包含了太多内容,同样开始看的一头雾水,其实现在还是有很多不了解的地方。

官方文档还是讲的不错的,一开始看会比较迷茫,但是稍微看一些以后,有些疑问在里面有说明。这是地址

这里都是基于SpringBoot的自动配置进行的,所以大部分配置比较简单。

spring jdbc

jdbc是java原有的数据访问组件,创建连接、创建查询、执行查询、结果通过ResultSet逐个读取转换。

当前面加上spring名头后,指的是spring的jdbc框架(或者叫模块?)。通过spring-boot-starter-data-jdbc依赖,使spring程序中可以得到一个注入得jdbctemplate对象,而不再依赖DriverMaanger,而且简化了访问方法。当然底层还是用的jdbc

当然jdbc并非ORM,因为还是面向与sql执行结果得,结果也需要手工转换为实体类(或者通过RowMapper)。

配置

配置比较少,基本使用只要配置DataSource就好了。

其实DataSource并非jdbc的概念,它代表一个数据库的配置,后面SpringJPA也要用到。

同样有代码和文件的配置方式,这是使用文件的方式进行配置的:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">

	<bean name="dataSource"
		class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="url"
			value="jdbc:mysql://localhost:3306/testdb?serverTimezone=Asia/Shanghai&amp;characterEncoding=utf8" />
		<property name="username" value="root" />
		<property name="password" value="123456" />
	</bean>
</beans>

对于这个配置文件多说两句:

  1. 网上教程需要配置driver这个property,比如指向mysql,但是我用的时候,会有日志说不用配,会自动加载,我试了的确如此
  2. 注意连接字符串里的serverTimezone=Asia/Shanghai这个配置,可能是jdbc版本原因,如果不加这个,数据库连接会报时区不对的错误。

注意在springboot入口,需要添加对这个配置文件的依赖:

@SpringBootApplication
@ImportResource("classpath:jdbc-config.xml")
public class App {
	public static void main(String[] args) {
		new SpringApplicationBuilder(App.class).run(args);
	}
}

也可以使用代码的方式,两者相同:

    @Bean
    public DataSource getDataSource() {
        DataSourceBuilder dataSourceBuilder = DataSourceBuilder.create();
        dataSourceBuilder.url("jdbc:mysql://localhost:3306/testdb?serverTimezone=Asia/Shanghai");
        dataSourceBuilder.username("root");
        dataSourceBuilder.password("123456");
        return dataSourceBuilder.build();
    }

配置就是这样,很简单

使用jdbcTemplate

repository需要通过注解标记,主要为了

  • 被识别为bean
  • 特殊处理其中抛出的数据库异常
@Repository
public class EmployeeRepository {
	@Autowired
	NamedParameterJdbcTemplate jdbc;

	public void createEmployee(Employee employee) {
		jdbc.execute("insert into employees (name,email) values (:name,:email)",
				new BeanPropertySqlParameterSource(employee), (pc) -> {
					pc.execute();
					return null;
				});
	}

	public void updateEmployee(long id, Employee employee) {
		jdbc.update("update employees set name=:name, email=:email where id=:id", new MapSqlParameterSource()
				.addValue("id", id).addValue("name", employee.getName()).addValue("email", employee.getEmail()));
	}

	public Employee getEmployee(long id) {
		return jdbc.queryForObject("select * from employees where id=:id", new MapSqlParameterSource("id", id),
				new EmployeeRowMapeer());
	}
}

class EmployeeRowMapeer implements RowMapper<Employee> {
	@Override
	public Employee mapRow(ResultSet rs, int rownumber) throws SQLException {
		Employee e = new Employee();
		e.setId(rs.getInt(1));
		e.setName(rs.getString(2));
		e.setEmail(rs.getString(3));
		return e;
	}
}

这里

  1. 注册了NamedParameterJdbcTemplate,相比普通的JdbcTemplate,可以支持MapSqlParameterSourceBeanPropertySqlParameterSource两个类作为结构化参数传入
  2. 使用了update/execute等方法执行数据库操作
  3. 定义了RowMapper来转换返回结果到实体类

spring jpa

前言

有一种说法是spring jpa下面使用了jdbc,不过我没有找到相关的资料。

在spring jpa之前,同样的也有一个JPA,它时操作EnitityManager来进行ORM操作,同样有类似JDBC的复杂性,而SpringJPA封装了这个类到Repository中,使用方便了。

不过在了解SpringJPA前,JPA也有一些概念,比如JPA有一个需要通过EntityManagerFactory创建EntityManager,而EntityManager内部由各种实现(比如hibernate)维护一个Persistance Context,里面跟踪了所有的Entity情况。

spring jpa定义了一套接口规范,具体有一些实现组件,比如spring默认的似乎是hibernate。

SpringJPA在使用上以Repository为基础,有下面这些内容(部分)。

SpringJPA使用spring-boot-starter-data-jpa作为开始依赖。

实体类

  • 通过@Entity定义实体类,所以JPA是一种ORM框架,可以将实体与数据库表关联
@Entity
@Table(name = "employees")
public class Employee {
	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	long id;
	String name;
	String email;
  //省略getter setter
}

Repository类

定义了Repository接口,接口有两个模板参数,一个是实体类,一个是实体类的id类型,通过这个信息,找到Repository使用的表。

public interface Repository<T, ID> {
}

直接定义接口名称,Repository可以自动生成实现,比如定义List<Employee> findByName(String name);,就不用写方法实现,JPA内部会自动生成查询方法,并将参数传入

public interface EmployeeRepository extends Repository<Employee, Long> {

	List<Employee> findByName(String name);
}

方法里传入的SortPageable参数也能被正确转换为所需的排序或者分页信息。

预定义的Repository

提供了类似CrudRepository接口,定义了常用的findAll,count,findById等方法;提供了PagingAndSortingRepository,进一步增加了携带SortPageable的相关方法。

应用的Repository集成这些类,常用的CRUD可以不用定义直接使用。

public interface EmployeeRepository extends PagingAndSortingRepository<Employee, Long> {}

使用时可以直接使用save方法:


	@Autowired
	EmployeeRepository repo;

	@Override
	public void createEmployee(Employee employee) {
		repo.save(employee);

	}

自定义方法实现:

当通过名称实现不满足要求时,支持JPQLSQL自定义方法。

JPQL

JPQL是JPA定义的SQL,会在Repository初始化的时候就进行预处理,如果其中有错误,这时就会报错。

这是通过JPQL查询的方法:

	@Query("select e from #{#entityName} e where name like %?1%")
	List<Employee> CustomQuery(String name, Pageable page);
  • 参数可以通过位置符号?1替代,这里被替换为了name
  • #{#entityName}被自动替代为实体名字,这样不用写死在代码中
  • Pageable参数可以被SpringJPA自动识别并加入到最后的查询中
  • 注意这是一个Like语句,百分号周围没有加单引号,如果加了就得不到想要的结果了,推测应该是ORM框架自动加的
原生sql

同样可以通过原生SQL:

	@Query(value = "SELECT * FROM #{#entityName} WHERE name like %:name%", nativeQuery = true)
	List<Employee> NativeQuery(@Param("name") String name);

这里通过nativeQuery标识标明sql被数据库直接执行。

在此之前,同样可以进行参数替换,这里使用了命名参数的方式@Param("name") 对应到sql中的:name

实体名称替换( #{#entityName})同样有效。

同样也需要注意

EntityManager

可以回到java JPA中EntityManager中的方法,对比可以看出来SpringJPA帮忙省略的细节。

注意这里扩展的方法需要实现,所以额外定义一个Cusom接口和Impl类

public interface EmployeeRepository extends PagingAndSortingRepository<Employee, Long>, EmployeeRepositoryCustom {

//	@Query(value = "SELECT * FROM #{#entityName} WHERE name like %:name%", nativeQuery = true)
//	List<Employee> NativeQuery(@Param("name") String name);
}

interface EmployeeRepositoryCustom {

	public List<Employee> NativeQuery(String name);
}

class EmployeeRepositoryImpl implements EmployeeRepositoryCustom {

	@PersistenceContext
	EntityManager entityManager;

	public List<Employee> NativeQuery(String name) {
		javax.persistence.Query query = entityManager.createNativeQuery("select * from employees where name like ?1",
				Employee.class);
		query.setParameter(1, name + "%");
		List<Employee> list = query.getResultList();
		return list;
	}
}

相比较之前的Native SQL方式,这里同样是创建原生SQL,只是代码要复杂许多,因为暴露出来的接口EmployeeRepository还需要扩展自自定义的接口EmployeeRepositoryCustom

原文地址:https://www.cnblogs.com/mosakashaka/p/12609127.html

时间: 2024-11-02 18:24:46

Spring框架学习(四)SpringData的相关文章

spring框架学习(四)自动装配

spring框架学习(四)自动装配 set注入和构造注入有时在做配置时比较麻烦.所以框架为了提高开发效率,提供自动装配功能,简化配置.Spring框架式默认不支持自动装配的,要想使用自动装配需要修改spring配置文件中<bean>标签的autowire属性 自动装配属性有6个值可选,分别代表不同的含义. 1,byName 从Spring环境中获取目标对象时,目标对象中的属性会根据名称在整个Spring环境中查找<bean>标签的id属性值.如果有相同的,那么获取这个对象,实现关联

Spring框架学习1

AnonymouL 兴之所至,心之所安;尽其在我,顺其自然 新随笔 管理 Spring框架学习(一) 阅读目录 一. spring概述 核心容器: Spring 上下文: Spring AOP: Spring DAO: Spring ORM: Spring Web 模块: Spring MVC 框架: 二.实例化spring容器 三.利用Spring容器创建javaBean对象 1,用构造器实例化 2,使用静态工厂方法实例化 3,实例工厂实例化 四,容器的IOC应用 4.1)Set注入 4.2)

Spring框架学习总结(上)

目录 1.Spring的概述 2.Spring的入门(IOC) 3.Spring的工厂类 4.Spring的配置 5.Spring的属性注入 6.Spring的分模块开发的配置 @ 1.Spring的概述 在学习SSM框架中,我建议初学者最好先学Spring框架,其次mybatis接着springMVC,先学mybatis当然也是可以的,今天我们就以绝对优雅的姿态闯进Spring世界,系好安全带,准备好了吗,出发了哦!!!咳咳....平时开发接触最多的估计就是IOC容器,它可以装载bean(所谓

Spring框架学习之IOC(一)

Spring框架学习之IOC 先前粗浅地学过Spring框架,但当时忙于考试及后期实习未将其记录,于是趁着最近还有几天的空闲时间,将其稍微整理一下,以备后期查看. Spring相关知识 spring是J2EE应用程序框架,是轻量级的IoC和AOP的容器框架,主要是针对javaBean的生命周期进行管理的轻量级容器.可单独使用,通常也与其他框架整合使用,例如SSH.SSM. IOC:控制反转 控制权由对象本身转向容器:由容器根据配置文件去创建实例并创建各个实例之间的依赖关系.等同于DI依赖注入 A

spring框架学习(二)依赖注入

转自:http://blog.csdn.net/lishuangzhe7047/article/details/20740835 ———————————————————————————————————————————— spring框架为我们提供了三种注入方式,分别是set注入,构造方法注入,接口注入.接口注入不作要求,下面介绍前两种方式. 1,set注入 采用属性的set方法进行初始化,就成为set注入. 1)给普通字符类型赋值. [java] view plaincopyprint? pub

spring框架学习(一)

转自:http://blog.csdn.net/lishuangzhe7047/article/details/20740209 —————————————————————————————————————————————————— 1,什么是spring框架 spring是J2EE应用程序框架,是轻量级的IoC和AOP的容器框架,主要是针对javaBean的生命周期进行管理的轻量级容器,可以单独使用,也可以和Struts框架,ibatis框架等组合使用. 2,架构概述 1)IoC(Inversi

spring框架学习(六)AOP

spring框架学习(六)AOP AOP(Aspect-OrientedProgramming)面向方面编程,与OOP完全不同,使用AOP编程系统被分为方面或关注点,而不是OOP中的对象. AOP的引入 在OOP面向对象的使用中,无可避免的会出现代码重复,而且使用面向对象的编程方式,这种重复无法避免,比如用户权限判断中,根据相应的权限执行相应的方法:在servlet中设置编码格式时,同样相同的代码出现很多次,而且还根业务无关,很容易忘记写,结果运行的时候就出现乱码拉.这种重复代码不仅使编码麻烦,

spring框架学习(五)注解

spring框架学习(五)注解 注解Annotation,是一种类似注释的机制,在代码中添加注解可以在之后某时间使用这些信息.跟注释不同的是,注释是给我们看的,java虚拟机不会编译,注解也是不编译的,但是我们可以通过反射机制去读取注解中的信息.注解使用关键字@interface,继承java.lang.annotition.Annotition spring框架为我们提供了注解功能. 使用注解编程,主要是为了替代xml文件,使开发更加快速.但是,xml文件的使用就是解决修改程序修改源代码,现在

spring框架学习(三)junit单元测试

spring框架学习(三)junit单元测试 单元测试不是头一次听说了,但只是听说从来没有用过.一个模块怎么测试呢,是不是得专门为一单元写一个测试程序,然后将测试单元代码拿过来测试? 我是这么想的.学到spring框架这才知道单元测试原来是这么回事儿. 下面以上一篇文章中set注入的第一个实例为测试对象.进行单元测试. 1,拷贝jar包 junit-3.8.2.jar(4.x主要增加注解应用) 2,写业务类 [java] view plaincopyprint? public class Use

Spring框架学习之IOC(二)

Spring框架学习之IOC(二) 接着昨天的内容,下面开始IOC基于注解装配相关的内容 在 classpath 中扫描组件 <context:component-scan> 特定组件包括: –@Component: 基本注解, 标识了一个受 Spring 管理的组件 –@Respository: 标识持久层组件 –@Service: 标识服务层(业务层)组件 –@Controller: 标识表现层组件 对于扫描到的组件, Spring 有默认的命名策略: 使用非限定类名, 第一个字母小写.