Spring Data JPA 入门篇
Spring Data JPA是什么
它是Spring基于ORM框架(如hibernate,Mybatis等)、JPA规范(Java Persistence API)封装的一套 JPA应用框架,可使开发者用极简的代码即可实现对数据的访问和操作。他提供了包括增删改查在内的常用功能,且易于扩展!学习并使用Spring Data JPA可以极大提高开发效率。
Spring Data JPA有什么
主要看看SpringDataJPA提供的编程接口
- Repository:最顶层的接口,是一个空接口,目的是为了统一所有的Repository的类型,且能让组件扫描的时候自动识别。
- CrudRepository:Repository的子接口,提供CRUD的功能
- PagingAndSortingRepository:CrudRepository的子接口,添加分页排序的功能
- JpaRepository:PagingAndSortingRepository的子接口,增加批量操作等功能
- JPASpecificationExecutor:用来做复杂查询的接口
建立项目:用户管理
配置文件persistent.xml
<?xml version="1.0" encoding="UTF-8"?> <persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0"> <persistence-unit name="userPU" transaction-type="RESOURCE_LOCAL"> <!--jpa的提供者--> <provider>org.hibernate.ejb.HibernatePersistence</provider> <properties> <!--声明数据库连接的驱动--> <property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/> <!--jdbc数据库的连接地址--> <property name="hibernate.connection.url" value="jdbc:mysql://localhost:3306/test"/> <property name="hibernate.connection.username" value="root"/> <property name="hibernate.connection.password" value="123456"/> <!--配置方言--> <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect"/> <!--激活查询日志功能--> <property name="hibernate.show_sql" value="true"/> <!--优雅地输出Sql--> <property name="hibernate.format_sql" value="true"/> <!--添加一条解释型标注--> <property name="hibernate.use_sql_comments" value="false"/> <!--配置如何根据java模型生成数据库表结构,常用update,validate--> <property name="hibernate.hbm2ddl.auto" value="update"/> </properties> </persistence-unit> </persistence>
applicationContext.xml
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jpa="http://www.springframework.org/schema/data/jpa" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd" default-lazy-init="true"> <!--第一步--> <!--定义服务层代码存放的包扫描路径--> <context:component-scan base-package="com.jike.usermanage.service" /> <!--第二步--> <!--定义实体的工厂bean--> <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="persistenceUnitName" value="userPU" /> <property name="persistenceXmlLocation" value="classpath:persistence.xml"></property> </bean> <!--第三步--> <!--定义事务管理器--> <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> <property name="entityManagerFactory" ref="entityManagerFactory"/> </bean> <!--第四步--> <!--定义repository接口的存放目录--> <!--定义接口实现的后缀,通常用Impl--,如果我们不想使用JPA提供的方法,我们可以自己实现,文件后缀为Impl> <!--定义实体工厂的引用--> <!--定义事务管理器的引用--> <jpa:repositories base-package="com.jike.usermanage.repository" repository-impl-postfix="Impl" entity-manager-factory-ref="entityManagerFactory" transaction-manager-ref="transactionManager"/> <!--第五步--> <!--声明采用注解的方式申明事务--> <tx:annotation-driven transaction-manager="transactionManager"/> </beans>
实体类User.java
package com.jike.usermanage.model; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.Table; @Entity @Table(name="user") public class User { @Id @GeneratedValue private Integer id; private String name; private String address; private String phone; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } }
Dao层UserRepository.java:这个类需要继承JpaRepository<User,Integer>,Integer表示User表中的主键类型
package com.jike.usermanage.repository; import java.util.List; import org.springframework.data.domain.Sort; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; import com.jike.usermanage.model.User; public interface UserRepository extends JpaRepository<User, Integer> { // 查询需求: 从数据库中查询电话号码(phone)以指定字符串开始(例如:136)的,并且地址(address)中包含指定字符串(例如:路)的记录 // select * from user where phone like '136%' and address like '%路%' order // by phone desc limit 0,2 List<User> findTop2ByPhoneStartingWithAndAddressContainingOrderByPhoneDesc( String phone, String address); List<User> findTop2ByPhoneStartingWithAndAddressContaining(String phone, String address, Sort sort); Page<User> findByPhoneStartingWithAndAddressContaining(String phone, String address, Pageable pageable); }
Service层:
package com.jike.usermanage.service; import java.util.List; import org.springframework.data.domain.Page; import com.jike.usermanage.exception.UserNotFound; import com.jike.usermanage.model.User; public interface UserService { // 添加用户 public void addUser(User user); // 修改用户 public User updateUser(User user) throws UserNotFound; // 删除用户,根据用户编号删除 public User deleteUser(int id) throws UserNotFound; // 查询单个用户 public User getUser(int id); // 查询所有用户 public List<User> getUsers(); // 不分页带条件查询 public List<User> getUsersByConditionNoPage(String phone, String address); // 带分页条件查询(需要得到用户列表并且得到分页信息) public Page<User> getUsersByConditionWithPage(String phone, String address, Integer page, Integer pageSize); // 带分页条件查询(得到用户列表) // public List<User> getUsersByCondition(String phone,String address,Integer // page,Integer pageSize); }
ServiceImpl
package com.jike.usermanage.service; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.stereotype.Service; import com.jike.usermanage.exception.UserNotFound; import com.jike.usermanage.model.User; import com.jike.usermanage.repository.UserRepository; @Service("userService") public class UserServiceImpl implements UserService { @Autowired private UserRepository userRepository; @Override public void addUser(User user) { userRepository.save(user); } @Override public User updateUser(User user) throws UserNotFound { User userUpdate = userRepository.findOne(user.getId()); if (userUpdate == null) throw new UserNotFound(); if (user.getName() != null) userUpdate.setName(user.getName()); if (user.getAddress() != null) userUpdate.setAddress(user.getAddress()); if (user.getPhone() != null) userUpdate.setPhone(user.getPhone()); userRepository.save(userUpdate); return userUpdate; } @Override public User deleteUser(int id) throws UserNotFound { User userDelete = userRepository.findOne(id); if (userDelete == null) throw new UserNotFound(); userRepository.delete(userDelete); return userDelete; } @Override public User getUser(int id) { return userRepository.findOne(id); } @Override public List<User> getUsers() { return userRepository.findAll(); } @Override public Page<User> getUsersByConditionWithPage(String phone, String address, Integer page, Integer pageSize) { // 不排序 Page<User> userPage = userRepository .findByPhoneStartingWithAndAddressContaining(phone, address, new PageRequest(page, pageSize)); // 排序 // 第一种排序方式 // Page<User> userPage = // userRepository.findByPhoneStartingWithAndAddressContaining(phone,address,new // PageRequest(page, pageSize,new Sort(Direction.ASC,"name","phone"))); // 第二种排序方式 // Order order = new Order(Direction.ASC,"phone"); // Page<User> userPage = // userRepository.findByPhoneStartingWithAndAddressContaining(phone,address,new // PageRequest(page, pageSize,new Sort(order)); // 第三种排序方式 // List<Order> orders = new ArrayList<Order>(); // orders.add(new Order(Direction.DESC,"name")); // orders.add(new Order(Direction.ASC,"phone")); // Page<User> userPage = // userRepository.findByPhoneStartingWithAndAddressContaining(phone,address,new // PageRequest(page, pageSize,new Sort(orders)); return userPage; } @Override public List<User> getUsersByConditionNoPage(String phone, String address) { return userRepository .findTop2ByPhoneStartingWithAndAddressContainingOrderByPhoneDesc( phone, address); // return // userRepository.findTop2ByPhoneStartingWithAndAddressContaining(phone, // address, new Sort(Direction.ASC,"phone")); // Order order = new Order(Direction.ASC,"phone"); // return // userRepository.findTop2ByPhoneStartingWithAndAddressContaining(phone, // address, new Sort(order)); // List<Order> orders = new ArrayList<Order>(); // orders.add(new Order(Direction.DESC,"name")); // orders.add(new Order(Direction.ASC,"phone")); // return // userRepository.findTop2ByPhoneStartingWithAndAddressContaining(phone, // address, new Sort(orders); } }
异常类:
package com.jike.usermanage.exception; public class UserNotFound extends Exception { }
JpaRepository接口方法:
delete删除或批量删除
findAll查找所有
findOne查找单个
save保存单个或批量保存
saveAndFlush保存并刷新到数据库
查询操作的基本实现----基于方法名解析
JpaRepository支持接口规范方法名查询。意思是如果在接口中定义的查询方法符合他的命名规则,就可以不用写实现。
例如:findByName这个方法表示从数据库中查询Name这个属性等于XXX的所有记录,类似于SQL语句:select * from xxTable where name=xxx这种形式
1. 方法名需要在接口中设定
2.必须符合一定的命名规范
find+全局修饰+By+实体的属性名称+限定词+连接词+...(其他属性实体)+OrderBy+排序属性+排序方向
例如:findDistinctByFirstNameIgnoreCaseAndLastNameOrderByAgeDesc(String firstName,String lastName){....}
其中:Distinct是全局修饰(非必须),FirstName和LastName是实体的属性名,And是连接词,IgnoreCase是限定词,Age是排序属性,Dest是排序方向,限定词和连接词统称为"关键词"
常用词如下:
全局修饰:Distinct,Top,First
关键词:IsNull,InNotNull,Like,NotLike,Containing,In,NotIn,IgnoreCase,Betwwen,Equals,LessThan,GreaterThan,After,Before
排序方向:Asc,Desc
连接词:And,Or
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步