文章目录
JPA第二章
一、SpringDataJpa入门
1、需求
使用SpringDataJpa实现数据库的CRUD
2、创建数据库
还是使用Customer表实现数据增删改查
3、开发步骤
1)创建一个maven工程
2)添加jar包
mysql的数据库驱动
数据库连接池。
Hibernate的jar包
SpringDataJpa
Spring相关的jar包
-
<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <spring.version>5.0.2.RELEASE</spring.version> <hibernate.version>5.0.7.Final</hibernate.version> <slf4j.version>1.6.6</slf4j.version> <log4j.version>1.2.12</log4j.version> <c3p0.version>0.9.1.2</c3p0.version> <mysql.version>5.1.6</mysql.version> </properties> <dependencies> <!-- junit单元测试 --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <!-- spring beg --> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.6.8</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${spring.version}</version> </dependency> <!-- spring end --> <!-- hibernate beg --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>${hibernate.version}</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-entitymanager</artifactId> <version>${hibernate.version}</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>5.2.1.Final</version> </dependency> <!-- hibernate end --> <!-- c3p0 beg --> <dependency> <groupId>c3p0</groupId> <artifactId>c3p0</artifactId> <version>${c3p0.version}</version> </dependency> <!-- c3p0 end --> <!-- log end --> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>${log4j.version}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>${slf4j.version}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>${slf4j.version}</version> </dependency> <!-- log end --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${mysql.version}</version> </dependency> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-jpa</artifactId> <version>2.0.7.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>${spring.version}</version> </dependency> <!-- el beg 使用spring data jpa 必须引入 --> <dependency> <groupId>javax.el</groupId> <artifactId>javax.el-api</artifactId> <version>2.2.4</version> </dependency> <dependency> <groupId>org.glassfish.web</groupId> <artifactId>javax.el</artifactId> <version>2.2.4</version> </dependency> <!-- el end --> </dependencies>
3)创建配置文件,spring和SpringDataJpa整合的配置文件
applicationContext.xml
配置框架整合:
员(数据源)工(工厂类对象)是(事务)爹(Dao包扫描器)
数据源:数据库连接池
工厂类对象:EntityManagerFactory对象,spring包装之后的。
事务:事务管理器、可以使用切面。
dao包扫描器:扫描dao接口
-
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jpa="http://www.springframework.org/schema/data/jpa" xmlns:task="http://www.springframework.org/schema/task" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd"> <!-- 1.dataSource 配置数据库连接池--> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="com.mysql.jdbc.Driver"/> <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/jpa_sgw?characterEncoding=utf8"/> <property name="user" value="root"/> <property name="password" value="root"/> </bean> <!--2.工厂类对象--> <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <!--配置数据源--> <property name="dataSource" ref="dataSource"/> <!--实体类的包扫描器--> <property name="packagesToScan" value="cn.sgwks.jpa.entity"/> <!--配置供应商适配器--> <property name="jpaVendorAdapter"> <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> <!--是否向控制台输出sql语句--> <property name="showSql" value="true"/> <!--是否自动创建表 如果是true:相当于update,hibernate.hbm2ddl.auto属性配置成update 如果是false:相当于none --> <property name="generateDdl" value="true"/> <!--使用的数据库类型--> <property name="database" value="MYSQL"/> </bean> </property> </bean> <!--3配置事务--> <!-- 3.1 JPA事务管理器 --> <bean id="txManager" class="org.springframework.orm.jpa.JpaTransactionManager"> <property name="entityManagerFactory" ref="entityManagerFactory"/> </bean> <!-- 3.2.txAdvice--> <tx:advice id="txAdvice" transaction-manager="txManager"> <tx:attributes> <tx:method name="get*" read-only="true"/> <tx:method name="find*" read-only="true"/> <tx:method name="query*" read-only="true"/> <tx:method name="*" propagation="REQUIRED"/> </tx:attributes> </tx:advice> <!-- 3.3.aop--> <aop:config> <!-- <aop:pointcut id="pointcut" expression="execution(* cn.sgwks.jpa.service.*.*(..))"/>--> <!-- pointcut-ref="pointcut" --> <aop:advisor advice-ref="txAdvice" pointcut="execution(* cn.sgwks.jpa.service.*.*(..))"/> </aop:config> <!--4.dao的包扫描器--> <jpa:repositories base-package="cn.sgwks.jpa.dao" transaction-manager-ref="txManager" entity-manager-factory-ref="entityManagerFactory"/> </beans>
4)创建实体类
-
package cn.sgwks.jpa.entity; import javax.persistence.*; //代表是一个jpa的实体类 @Entity //配置实体类和数据库中表的映射关系 name对应的表名 @Table(name = "cst_customer") public class Customer { //配置主键的生成策略 /** * 1: @GeneratedValue(strategy = GenerationType.IDENTITY)====>自增长 * 2: @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "cust_seq")====>使用序列生成主键 * @SequenceGenerator(name = "cust_seq", sequenceName = "cust_sequence") * 3: @GeneratedValue(strategy = GenerationType.TABLE, generator = "tab_gen")====>使用表生成主键 * @TableGenerator(name = "tab_gen", table = "ids_gen", pkColumnName = "ids", valueColumnName = "vals", pkColumnValue = "customer", allocationSize = 1) * 4: @GeneratedValue(strategy = GenerationType.AUTO) */ //在主键字段使用@Id标注 @Id //配置属性和字段的映射关系 @Column(name = "cust_id") //GenerationType.IDENTITY是自增长 @GeneratedValue(strategy = GenerationType.IDENTITY) private Long custId; //客户姓名 @Column(name = "cust_name") private String custName; //客户来源 @Column(name = "cust_source") private String custSource; //客户所属行业 @Column(name = "cust_industry") private String custIndustry; //客户级别 @Column(name = "cust_level") private String custLevel; //客户所住地址 @Column(name = "cust_address") private String custAddress; //客户联系电话 @Column(name = "cust_phone") private String custPhone; public Long getCustId() {return custId;} public void setCustId(Long custId) {this.custId = custId;} public String getCustName() {return custName;} public void setCustName(String custName) {this.custName = custName;} public String getCustSource() {return custSource;} public void setCustSource(String custSource) {this.custSource = custSource;} public String getCustIndustry() {return custIndustry;} public void setCustIndustry(String custIndustry) {this.custIndustry = custIndustry;} public String getCustLevel() {return custLevel;} public void setCustLevel(String custLevel) {this.custLevel = custLevel;} public String getCustAddress() {return custAddress;} public void setCustAddress(String custAddress) {this.custAddress = custAddress;} public String getCustPhone() {return custPhone;} public void setCustPhone(String custPhone) {this.custPhone = custPhone;} }
5)创建dao,创建接口即可。要求接口继承JpaRepository接口。
-
package cn.sgwks.jpa.dao; import cn.sgwks.jpa.entity.Customer; import org.springframework.data.jpa.repository.JpaRepository; /** * Customer管理的Dao * 只需要创建一个接口即可,需要继承JpaRepository接口。 * 泛型: * dao关联的Entity类 * 对应表的主键的数据类型 */ public interface CustomerDao extends JpaRepository<Customer,Long> {}
6)编写测试程序。
应该是使用dao实现增删改查。
1、初始化spring容器
2、从容器中获得Dao的代理对象。
3、使用dao实现增删改查
4、测试方法上:
-
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:applicationContext.xml") public class JpaFirst { @Autowired private CustomerDao customerDao; }
-
添加数据:save
-
/** * 通过容器获取代理对象 */ @Test public void addCustomer(){ ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); CustomerDao customerDao = context.getBean(CustomerDao.class); Customer customer = new Customer(); customer.setCustName("张帅"); customer.setCustSource("美女推荐"); customer.setCustIndustry("吃货"); customer.setCustLevel("农民"); customer.setCustAddress("河南省南阳市"); customer.setCustPhone("16677889900"); //插入数据 customerDao.save(customer); }
-
sql结果:
Hibernate: insert into cst_customer (cust_address, cust_industry, cust_level, cust_name, cust_phone, cust_source) values (?, ?, ?, ?, ?, ?)
-
-
删除:delete
-
/** * 删除指定数据 */ @Test public void deleteCustomer() { customerDao.delete(9L); }
-
sql结果:
Hibernate: select customer0_.cust_id as cust_id1_0_0_, customer0_.cust_address as cust_add2_0_0_, customer0_.cust_industry as cust_ind3_0_0_, customer0_.cust_level as cust_lev4_0_0_, customer0_.cust_name as cust_nam5_0_0_, customer0_.cust_phone as cust_pho6_0_0_, customer0_.cust_source as cust_sou7_0_0_ from cst_customer customer0_ where customer0_.cust_id=? Hibernate: delete from cst_customer where cust_id=?
-
-
修改:save
-
根据id查询一条数据,返回一个对象
-
修改对象的属性
-
把修改结果更新到数据库
-
/** * 修改指定数据 */ @Test public void updateCustomer() { //根据id查询一条数据,返回一个对象 Customer customer = customerDao.findOne(10L); //修改对象的属性 customer.setCustPhone("12345678901"); customer.setCustSource("jpa学习"); //把修改结果更新到数据库 customerDao.save(customer); }
-
sql结果:
Hibernate: select customer0_.cust_id as cust_id1_0_0_, customer0_.cust_address as cust_add2_0_0_, customer0_.cust_industry as cust_ind3_0_0_, customer0_.cust_level as cust_lev4_0_0_, customer0_.cust_name as cust_nam5_0_0_, customer0_.cust_phone as cust_pho6_0_0_, customer0_.cust_source as cust_sou7_0_0_ from cst_customer customer0_ where customer0_.cust_id=? Hibernate: select customer0_.cust_id as cust_id1_0_0_, customer0_.cust_address as cust_add2_0_0_, customer0_.cust_industry as cust_ind3_0_0_, customer0_.cust_level as cust_lev4_0_0_, customer0_.cust_name as cust_nam5_0_0_, customer0_.cust_phone as cust_pho6_0_0_, customer0_.cust_source as cust_sou7_0_0_ from cst_customer customer0_ where customer0_.cust_id=? Hibernate: update cst_customer set cust_address=?, cust_industry=?, cust_level=?, cust_name=?, cust_phone=?, cust_source=? where cust_id=?
-
-
查询:
findOne:根据id查询-
/** * 查询指定id数据 */ @Test public void findById() { Customer customer = customerDao.findOne(3L); System.out.println(customer); }
-
Hibernate: select customer0_.cust_id as cust_id1_0_0_, customer0_.cust_address as cust_add2_0_0_, customer0_.cust_industry as cust_ind3_0_0_, customer0_.cust_level as cust_lev4_0_0_, customer0_.cust_name as cust_nam5_0_0_, customer0_.cust_phone as cust_pho6_0_0_, customer0_.cust_source as cust_sou7_0_0_ from cst_customer customer0_ where customer0_.cust_id=?
-
二、SpringDataJpa的原理
底层还是使用jpa的原生api来实现。
实现封装在SimpleJpaRepository类中,由此类提供dao的支持。
三、SpringDataJpa中的查询
1、使用dao提供的方法查询
-
1)根据id查询
-
findOne:根据id查询,即时加载
@Test public void testFindOne() { Customer customer = customerDao.findOne(3L); System.out.println("================"); System.out.println(customer); } --sql结果: Hibernate: select customer0_.cust_id as cust_id1_0_0_, customer0_.cust_address as cust_add2_0_0_, customer0_.cust_industry as cust_ind3_0_0_, customer0_.cust_level as cust_lev4_0_0_, customer0_.cust_name as cust_nam5_0_0_, customer0_.cust_phone as cust_pho6_0_0_, customer0_.cust_source as cust_sou7_0_0_ from cst_customer customer0_ where customer0_.cust_id=? ================ Customer{custId=3, custName='sgw', custSource='电话营销', custIndustry='程序员', custLevel='码农', custAddress='AB市', custPhone='12345678901'}
-
getOne:根据id查询,懒加载,底层调用的就是getReference方法实现查询。
@Test /*这里开启事务,保证会话在方法结束前不会销毁,否则会报:org.hibernate.LazyInitializationException: could not initialize proxy - no Session 异常 */ @Transactional public void testGetOne() { Customer customer = customerDao.getOne(3l); System.out.println("================"); System.out.println(customer); } --sql结果: ================ Hibernate: select customer0_.cust_id as cust_id1_0_0_, customer0_.cust_address as cust_add2_0_0_, customer0_.cust_industry as cust_ind3_0_0_, customer0_.cust_level as cust_lev4_0_0_, customer0_.cust_name as cust_nam5_0_0_, customer0_.cust_phone as cust_pho6_0_0_, customer0_.cust_source as cust_sou7_0_0_ from cst_customer customer0_ where customer0_.cust_id=? Customer{custId=3, custName='石国旺', custSource='电话营销', custIndustry='程序员', custLevel='码农', custAddress='贵州省安顺市', custPhone='18208533574'}
-
-
2)查询全部数据
-
1、可以使用findAll方法查询。
@Test public void testFindAll() { List<Customer> customerList = customerDao.findAll(); for (Customer customer : customerList) { System.out.println(customer); } } --sql结果: Hibernate: select customer0_.cust_id as cust_id1_0_, customer0_.cust_address as cust_add2_0_, customer0_.cust_industry as cust_ind3_0_, customer0_.cust_level as cust_lev4_0_, customer0_.cust_name as cust_nam5_0_, customer0_.cust_phone as cust_pho6_0_, customer0_.cust_source as cust_sou7_0_ from cst_customer customer0_
-
2、查询全部数据带分页:
@Test public void testFindAllWithPage() { //参数1:页面从0开始 //参数2:每页的行数 //在Pageable对象中设置分页信息 /* 需要使用PageRquest类创建对象 page:页码,从0开始 size:每页的行数 */ Pageable pageable = new PageRequest(1, 5); //需要使用带参数的findAll(Pageable pageable) Page<Customer> page = customerDao.findAll(pageable); /* 返回一个Page对象: totalElements:总记录数 totalPages:总页数 content:结果列表 */ System.out.println("总记录数:" + page.getTotalElements()); System.out.println("总页数:" + page.getTotalPages()); List<Customer> list = page.getContent(); for (Customer customer : list) { System.out.println(customer); } } --sql结果: Hibernate: select count(customer0_.cust_id) as col_0_0_ from cst_customer customer0_ Hibernate: select customer0_.cust_id as cust_id1_0_, customer0_.cust_address as cust_add2_0_, customer0_.cust_industry as cust_ind3_0_, customer0_.cust_level as cust_lev4_0_, customer0_.cust_name as cust_nam5_0_, customer0_.cust_phone as cust_pho6_0_, customer0_.cust_source as cust_sou7_0_ from cst_customer customer0_ limit ?, ? 总记录数:7 总页数:2
-
3、查询全部带排序处理
findAll(Sort)@Test public void testFindAllWithSort() { //创建一个sort对象 //参数1:排序方式 //参数2:排序的字段,应该是实体类的属性名 Sort sort = new Sort(Sort.Direction.DESC, "custId"); List<Customer> list = customerDao.findAll(sort); for (Customer customer : list) { System.out.println(customer); } } --sql结果: Hibernate: select customer0_.cust_id as cust_id1_0_, customer0_.cust_address as cust_add2_0_, customer0_.cust_industry as cust_ind3_0_, customer0_.cust_level as cust_lev4_0_, customer0_.cust_name as cust_nam5_0_, customer0_.cust_phone as cust_pho6_0_, customer0_.cust_source as cust_sou7_0_ from cst_customer customer0_ order by customer0_.cust_id desc
-
-
3)其他查询方法
-
count:统计
@Test public void testcount() { long count = customerDao.count(); System.out.println(count); } --sql结果: Hibernate: select count(*) as col_0_0_ from cst_customer customer0_ 7
-
exists:判断记录是否存在。
@Test public void testExists() { boolean exists = customerDao.exists(1l); System.out.println(exists); } --sql结果: Hibernate: select count(*) as col_0_0_ from cst_customer customer0_ where customer0_.cust_id=? and 1=1 true
-
2、使用jpql查询
使用方法:
1)在dao接口中定义一个方法。使用方法的参数设置jpql的参数,使用方法的返回值接收查询结果。
2)在方法上添加一个@Query注解。
3)在注解中编写jpql。
4)测试
-
使用jpql查询全部数据。
-
jpql: from Customer
//接口 @Query("from Customer") List<Customer> getAllCustomer(); //测试方法 @Test public void getAllCustomer(){ List<Customer> customerList = customerDao.getAllCustomer(); for (Customer customer : customerList) { System.out.println(customer); } } --sql结果: Hibernate: select customer0_.cust_id as cust_id1_0_, customer0_.cust_address as cust_add2_0_, customer0_.cust_industry as cust_ind3_0_, customer0_.cust_level as cust_lev4_0_, customer0_.cust_name as cust_nam5_0_, customer0_.cust_phone as cust_pho6_0_, customer0_.cust_source as cust_sou7_0_ from cst_customer customer0_
-
查询分页:在查询方法中添加一个参数Pageable,可以实现分页
//接口 @Query("from Customer") List<Customer> getAllCustomerByPage(Pageable pageable); //测试方法 @Test public void getAllCustomerByPage(){ PageRequest pageRequest = new PageRequest(0, 3); List<Customer> customerList = customerDao.getAllCustomerByPage(pageRequest); for (Customer customer : customerList) { System.out.println(customer); } } --sql结果: Hibernate: select customer0_.cust_id as cust_id1_0_, customer0_.cust_address as cust_add2_0_, customer0_.cust_industry as cust_ind3_0_, customer0_.cust_level as cust_lev4_0_, customer0_.cust_name as cust_nam5_0_, customer0_.cust_phone as cust_pho6_0_, customer0_.cust_source as cust_sou7_0_ from cst_customer customer0_ limit ?
-
根据客户名称和地址查询:
sql:SELECT * FROM `cst_customer` WHERE cust_name LIKE '%会%' and cust_address LIKE '%界%' jpql:from Customer where custName like ? and custAddress like ?
//接口 //@Query("from Customer where custName like ? and custAddress like ?") //List<Customer> getCustList(String name, String address); @Query("from Customer where custName like ?2 and custAddress like ?1") List<Customer> getCustList(String address, String name); //测试方法 @Test public void getCustList(){ //List<Customer> customerList = customerDao.getCustList("%会%", "%界%"); List<Customer> customerList = customerDao.getCustList("%界%", "%会%"); for (Customer customer : customerList) { System.out.println(customer); } } --sql结果: Hibernate: select customer0_.cust_id as cust_id1_0_, customer0_.cust_address as cust_add2_0_, customer0_.cust_industry as cust_ind3_0_, customer0_.cust_level as cust_lev4_0_, customer0_.cust_name as cust_nam5_0_, customer0_.cust_phone as cust_pho6_0_, customer0_.cust_source as cust_sou7_0_ from cst_customer customer0_ where (customer0_.cust_name like ?) and (customer0_.cust_address like ?)
-
使用jpql执行更新操作:可以执行更新、删除操作。
sql:UPDATE cst_customer set cust_source = '互联网' where cust_id = 3 jpql: update Customer set custSource = ? where custId = ? 使用方法: 1)在dao接口中定义一个方法。 2)在方法上添加@Query注解,在注解中编写jpql语句 3)在方法上添加@Modifying注解 4)测试
//接口 @Query("update Customer set custSource = ? where custId = ?") @Modifying @Transactional void updateSource(String source, long id); //测试方法 @Test /*@Transactional @Commit*/ public void updateSource(){ customerDao.updateSource("互联网", 11L); } --sql结果: Hibernate: update cst_customer set cust_source=? where cust_id=?
-
3、使用原生的sql语句
使用方法:
1)在dao中定义一个方法
2)在方法上添加@Query注解
3)在注解中添加原生的sql语句,添加一个属性nativeQuery=true
-
//接口 @Query(value = "select * from cst_customer where cust_name LIKE ?", nativeQuery = true) List<Customer> getCustomerListByNative(String name); //测试方法 @Test public void getCustomerListByNative(){ List<Customer> customerList = customerDao.getCustomerListByNative("%国%"); for (Customer customer : customerList) { System.out.println(customer); } } --sql结果: Hibernate: select * from cst_customer where cust_name LIKE ?
4、方法命名规则查询(推荐使用,重点)
通过一定的规则定义一个方法,框架就可以根据方法名生成一个sql语句进行查询。
规则:
1)应该使用findBy开头
2)查询某个字段,findBy后跟实体类的属性的名称,默认是等于
3)如果有多个条件,就在方法后加And+实体类的属性名。
4)方法的参数对应查询定义。
5)返回值根据返回的数据类型定义。
如果需要分页在方法中添加一个参数Pageable即可。
-
//接口 Customer findByCustId(Long custId); //测试方法 @Test public void testfindByCustId(){ Customer customer = customerDao.findByCustId(3L); System.out.println(customer); } --sql结果: Hibernate: select customer0_.cust_id as cust_id1_0_, customer0_.cust_address as cust_add2_0_, customer0_.cust_industry as cust_ind3_0_, customer0_.cust_level as cust_lev4_0_, customer0_.cust_name as cust_nam5_0_, customer0_.cust_phone as cust_pho6_0_, customer0_.cust_source as cust_sou7_0_ from cst_customer customer0_ where customer0_.cust_id=?
-
//接口 List<Customer> findByCustNameLikeAndCustAddressLike(String name, String address); //测试方法 @Test public void testfindByCustNameLikeAndCustAddressLike(){ List<Customer> customerList = customerDao.findByCustNameLikeAndCustAddressLike("%会%","%界%"); for (Customer customer : customerList) { System.out.println(customer); } } --sql结果: Hibernate: select customer0_.cust_id as cust_id1_0_, customer0_.cust_address as cust_add2_0_, customer0_.cust_industry as cust_ind3_0_, customer0_.cust_level as cust_lev4_0_, customer0_.cust_name as cust_nam5_0_, customer0_.cust_phone as cust_pho6_0_, customer0_.cust_source as cust_sou7_0_ from cst_customer customer0_ where (customer0_.cust_name like ?) and (customer0_.cust_address like ?)
-
//接口 Page<Customer> findByCustAddressLike(String address, Pageable pageable); //测试方法 @Test public void testfindByCustAddressLike(){ Page<Customer> page = customerDao.findByCustAddressLike("%阳%", new PageRequest(0, 5)); System.out.println("查到的记录数: "+page.getTotalElements()); System.out.println("查到的总页数: "+page.getTotalPages()); List<Customer> content = page.getContent(); for (Customer customer : content) { System.out.println(customer); } } --sql结果: Hibernate: select count(customer0_.cust_id) as col_0_0_ from cst_customer customer0_ where customer0_.cust_address like ? Hibernate: select customer0_.cust_id as cust_id1_0_, customer0_.cust_address as cust_add2_0_, customer0_.cust_industry as cust_ind3_0_, customer0_.cust_level as cust_lev4_0_, customer0_.cust_name as cust_nam5_0_, customer0_.cust_phone as cust_pho6_0_, customer0_.cust_source as cust_sou7_0_ from cst_customer customer0_ where customer0_.cust_address like ? limit ?
5、使用Specification方式进行查询
说明书方式查询。
最强大的查询方式,最复杂的查询方式。
使用方法:
1)需要dao继承JpaSpecificationExecutor接口
-
public interface CustomerDao extends JpaRepository<Customer,Long>, JpaSpecificationExecutor<Customer> {}
2)使用JpaSpecificationExecutor接口中提供方法进行查询。
每个方法都需要使用Specification对象作为参数。
接口:JpaSpecificationExecutor
其中有三个方法:
findOne:查询一条记录
-
//测试 @Test public void testFindByIdSpecification() { Customer customer = customerDao.findOne(new Specification<Customer>() { /** * @param root 代表sql语句的根节点。相当于sql语句中from后的表名。 * @param query 查询对象。sql语句中的关键字包含在其中。例如:where,order by,group by,having等 * @param cb 就是 where 条件后面的条件查询,工具对象。 * @return */ @Override public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query, CriteriaBuilder cb) { /** * Root<Customer> * 参数1:字段名称,就是实体类指定的属性名 * 参数2:字段的值,设置实体类指定属性的值 */ Predicate predicate = cb.equal(root.get("custId"), 3L); return predicate; } }); System.out.println(customer); } --sql结果: Hibernate: select customer0_.cust_id as cust_id1_0_, customer0_.cust_address as cust_add2_0_, customer0_.cust_industry as cust_ind3_0_, customer0_.cust_level as cust_lev4_0_, customer0_.cust_name as cust_nam5_0_, customer0_.cust_phone as cust_pho6_0_, customer0_.cust_source as cust_sou7_0_ from cst_customer customer0_ where customer0_.cust_id=3 //简洁版(Lambda)->一个接口有且仅有一个实现的方法,而且是jdk1.8版本新的内容! @Test public void testFindByIdSpecificationEasy() { //customerDao.findOne((root, query, cb) -> { // Predicate predicate = cb.equal(root.get("custId"), 3L); // return predicate; //}); Customer customer = customerDao.findOne((root, query, cb) -> cb.equal(root.get("custId"), 3L)); System.out.println(customer); }
findAll:查询多条记录
-
//测试 @Test public void testFincByNameAndAddress() { List<Customer> customerList = customerDao.findAll(new Specification<Customer>() { @Override public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query, CriteriaBuilder cb) { //创建根据名称模糊查询的条件,第一个参数实体类的属性名,第二个参数是属性的值 Predicate predicate1 = cb.like(root.get("custName"),"%会%"); //创建一个根据地址模糊查询的条件 Predicate predicate2 = cb.like(root.get("custAddress"), "%界%"); //组合两个条件and Predicate predicate = cb.and(predicate1, predicate2); //返回组合之后的条件 return predicate; } }); for (Customer customer : customerList) { System.out.println(customer); } //customerDao.findAll((root, query, cb)->cb.equal(root.get("custId"), 3L)).forEach(System.out::println); } --sql结果: Hibernate: select customer0_.cust_id as cust_id1_0_, customer0_.cust_address as cust_add2_0_, customer0_.cust_industry as cust_ind3_0_, customer0_.cust_level as cust_lev4_0_, customer0_.cust_name as cust_nam5_0_, customer0_.cust_phone as cust_pho6_0_, customer0_.cust_source as cust_sou7_0_ from cst_customer customer0_ where (customer0_.cust_name like ?) and (customer0_.cust_address like ?) //简洁版 @Test public void testFincByNameAndAddressEasy() { customerDao.findAll((root, query, cb) -> cb.and(cb.like(root.get("custName"), "%会%"),cb.like(root.get("custAddress"), "%界%"))).forEach(System.out::println);}
page:查询全部+分页
-
//测试 @Test public void testFincByNameAndAddressWithPage() { Page<Customer> page = customerDao.findAll(new Specification<Customer>() { @Override public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query, CriteriaBuilder cb) { //创建根据名称模糊查询的条件,第一个参数实体类的属性名,第二个参数是属性的值 Predicate predicate1 = cb.like(root.get("custName"), "%帅%"); //创建一个根据地址模糊查询的条件 Predicate predicate2 = cb.like(root.get("custAddress"), "%阳%"); //组合两个条件and Predicate predicate = cb.and(predicate1, predicate2); //返回组合之后的条件 return predicate; } }, new PageRequest(0, 3)); System.out.println("查询到的总记录数:"+page.getTotalElements()); System.out.println("查询到的总页数"+page.getTotalPages()); List<Customer> content = page.getContent(); for (Customer customer : content) { System.out.println(customer); } } --sql结果: Hibernate: select count(customer0_.cust_id) as col_0_0_ from cst_customer customer0_ where (customer0_.cust_name like ?) and (customer0_.cust_address like ?) Hibernate: select customer0_.cust_id as cust_id1_0_, customer0_.cust_address as cust_add2_0_, customer0_.cust_industry as cust_ind3_0_, customer0_.cust_level as cust_lev4_0_, customer0_.cust_name as cust_nam5_0_, customer0_.cust_phone as cust_pho6_0_, customer0_.cust_source as cust_sou7_0_ from cst_customer customer0_ where (customer0_.cust_name like ?) and (customer0_.cust_address like ?) limit ? --简洁版 customerDao.findAll((root,query, cb)->cb.and(cb.like(root.get("custName"), "%会%"),cb.like(root.get("custAddress"), "%阳%")),new PageRequest(0, 3)).getContent().forEach(System.out::println);
sort:排序
-
//测试 @Test public void testFindCustomerWithSort() { List<Customer> customerList = customerDao.findAll(new Specification<Customer>() { @Override public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query, CriteriaBuilder cb) { Predicate predicate = cb.like(root.get("custName"), "%帅%"); return predicate; } }, new Sort(Sort.Direction.DESC, "custId")); for (Customer customer : customerList) { System.out.println(customer); } } --sql结果: Hibernate: select customer0_.cust_id as cust_id1_0_, customer0_.cust_address as cust_add2_0_, customer0_.cust_industry as cust_ind3_0_, customer0_.cust_level as cust_lev4_0_, customer0_.cust_name as cust_nam5_0_, customer0_.cust_phone as cust_pho6_0_, customer0_.cust_source as cust_sou7_0_ from cst_customer customer0_ where customer0_.cust_name like ? order by customer0_.cust_id desc
sort2:排序
-
//测试 @Test public void testFindCustomerWithSort2() { List<Customer> customerList = customerDao.findAll(new Specification<Customer>() { //根据sql语句: select * from cst_customer where cust_name like '%帅%' order by 'cust_id' @Override public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query, CriteriaBuilder cb) { Predicate predicate = cb.like(root.get("custName"), "%帅%"); //添加排序 Predicate result = query.where(predicate).orderBy(cb.desc(root.get("custId"))).getRestriction(); return result; } }); for (Customer customer : customerList) { System.out.println(customer); } } --sql结果: Hibernate: select customer0_.cust_id as cust_id1_0_, customer0_.cust_address as cust_add2_0_, customer0_.cust_industry as cust_ind3_0_, customer0_.cust_level as cust_lev4_0_, customer0_.cust_name as cust_nam5_0_, customer0_.cust_phone as cust_pho6_0_, customer0_.cust_source as cust_sou7_0_ from cst_customer customer0_ where customer0_.cust_name like ? order by customer0_.cust_id desc
-
Specification:
-
toPredicate:返回一个查询条件。在方法中应该创建一个查询条件并返回。
返回值: Predicate:查询条件。 参数: Root:代表sql语句的根节点。相当于sql语句中from后的表名。 CriteriaQuery: 查询对象。sql语句中的关键字包含在其中。 where order by group by having CriteriaBuilder:工具对象。 所有的条件的生成都是使用CriteriaBuilder。 只要涉及判断都需要使用CriteriaBuilder对象。 主要使用CriteriaBuilder创建条件。
-
四、总结
1、入门程序
1)框架整合
员(数据源)工(工厂类对象)是(事务)爹(dao包扫描器)
2)Entity
3)dao
定义接口即可,要求接口继承JpaRepository
2、使用dao实现CRUD(重点)
添加:save
修改:save
删除:delete
查询:findOne、getOne
3、查询方法
1)使用dao提供的方法
findOne、getOne
findAll
可以分页、排序
2)使用jpql查询
查询@Query注解
更新、删除也支持:需要添加注解@Modifying注解
3)原生的sql
使用@Query注解,添加属性nativeQuery=true
4)方法命名规则查询(重点)
5)使用Specification方式查询
dao继承JpaSpecificationExecutor接口。