JPA 与 hibernate 与Spring Data JPA 的关系
JPA是一套规范,内部是有接口和抽象类组成的。hibernate是一套成熟的ORM框架,而且Hibernate实现了JPA规范,所以也可以称hibernate为JPA的一种实现方式,我们使用JPA的API编程,意味着站在更高的角度上看待问题(面向接口编程)
Spring Data JPA是Spring提供的一套对JPA操作更加高级的封装,是在JPA规范下的专门用来进行数据持久化的解决方案。
2.resources下的Spring 配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans....约束...">
<!--spring 和 spring data jpa的配置-->
<!-- 1.创建entityManagerFactory对象交给spring容器管理-->
<bean id="entityManagerFactoty" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<!--配置的扫描的包(实体类所在的包) -->
<property name="packagesToScan" value="com.wyc.domain" />
<!-- jpa的实现厂家 -->
<property name="persistenceProvider">
<bean class="org.hibernate.jpa.HibernatePersistenceProvider"/>
</property>
<!--jpa的供应商适配器 -->
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<!--配置是否自动创建数据库表 -->
<property name="generateDdl" value="false" />
<!--指定数据库类型 -->
<property name="database" value="MYSQL" /> 必须大写
<!--数据库方言:支持的特有语法 -->
<property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect" /> ORACLE也有
<!--是否显示sql -->
<property name="showSql" value="true" />
</bean>
</property>
<!--jpa的方言 :高级的特性 -->
<property name="jpaDialect" >
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
</property>
</bean>
<!--2.创建数据库连接池 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="user" value="root"></property>
<property name="password" value="123"></property>
<property name="jdbcUrl" value="jdbc:mysql:///test" ></property>
<property name="driverClass" value="com.mysql.cj.jdbc.Driver"></property>
</bean>
<!--3.整合spring dataJpa-->
<jpa:repositories base-package="com.wyc.dao" transaction-manager-ref="transactionManager"
entity-manager-factory-ref="entityManagerFactoty" ></jpa:repositories>
<!--4.配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactoty"></property>
</bean>
<!-- 6. 配置包扫描-->
<context:component-scan base-package="com.wyc" ></context:component-scan>
</beans>
3.在Dao层只需 继承 JpaRepository<Customer,Long>, 实体类中主键的类型 JpaSpecificationExecutor<Customer>
public interface CustomerDao extends JpaRepository<Customer,Long>, JpaSpecificationExecutor<Customer> {
}
然后就可以使用其中已经实现的 简单操作方法 其中findOne 与 getOne 立即加载 与延迟加载
底层通过 JdkDynamicAopProxy 创建代理对象 SimpleJpaRepository 配置文件中配置了 整合Spring data jpa需要加强的dao
通过 entityManager 实体管理器 完成操作
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class jpaTest {
@Autowired
private CustomerDao customerDao;
@Test
public void testFinOne(){ //立即加载 底层是jpa的findOne
Customer customer = customerDao.findOne(1L);
System.out.println(customer);
}
@Test
public void testGetOne(){ //延迟加载 底层是jpa的getReference
Customer customer = customerDao.getOne(1L);
System.out.println(customer);
}
@Test
public void testSave(){
Customer customer = new Customer();
customer.setCustName("hahah");
customer.setCustName("66666");
customerDao.save(customer);
}
@Test
public void testUpdate(){
Customer customer = new Customer();
customer.setCustId(1L); //当设置了主键后 会先查询,如果有save就是更新
customer.setCustName("heihei");
customer.setCustName("666333");
customerDao.save(customer);
}
@Test
public void testDelete(){
customerDao.delete(1L); //底层也是先执行查询对象,再删除
}
@Test
public void testFindAll(){
List<Customer> customers = customerDao.findAll();
System.out.println(customers);
}
@Test
public void testCount(){
long count = customerDao.count();
System.out.println(count);
}
@Test
public void testExists() {
boolean exists = customerDao.exists(4L); //select count(*) as from cst_customer id=? and 1=1
System.out.println("id为4的客户 是否存在:"+exists);
}
}
Spring Data Jpa 使用JPQL 与SQL
使用 @Query注解 属性 1.value 写JPQL 或 SQL表达式 2. nativeQuery =true 表示 使用SQL表达式,默认false
public interface CustomerDao extends JpaRepository<Customer,Long>, JpaSpecificationExecutor<Customer> {
@Query(value="from Customer where custName = ?")
public Customer findJpql(String custName);
@Query(value = "from Customer where custName = ?2 and custId = ?1")
public Customer findCustNameAndId(Long id,String name);
@Query(value = " update Customer set custName = ?2 where custId = ?1 ")
@Modifying
public void updateCustomer(long custId,String custName);
//@Query(value = " select * from cst_customer" ,nativeQuery = true)
@Query(value="select * from cst_customer where cust_name like ?1",nativeQuery = true)
public List<Object [] > findSql(String name);
}
注意 1. 其中 有多个参数时,可以使用 update Customer set custName = ?2 where custId = ?1 指定参数的位置
2. 更新操作 需要加上注解@Modifying 测试类中 或service 层中需要 加上事务 和指定不回滚
@Test
@Transactional //添加事务的支持
@Rollback(value = false)
public void testUpdateCustomer() {
customerDao.updateCustomer(4l,"黑马程序员");
}
Spring Data Jpa使用方法名查询
方法名的约定:
1. findBy : 表示查询
2. 查询条件: findBy + 实体类中的属性名(首字母大写) 表示查询的条件 默认情况 : 使用 等于的方式查询
3.模糊查询: findBy + 属性名称 + 查询方式(Like | isnull) findByCustNameLike 表示模糊查询
4.多条件查询: findBy + 属性名 + “查询方式” + “多条件的连接符(and|or)” + 属性名 + “查询方式”
原理: 再springdataJpa的运行阶段 会根据方法名称进行解析 findBy from (实体类) (and|or . ..) like ?
public interface CustomerDao extends JpaRepository<Customer,Long>, JpaSpecificationExecutor<Customer> {
public Customer findByCustName(String custName);
public List<Customer> findByCustNameLike(String custName);
//使用客户名称模糊匹配和客户所属行业精准匹配的查询
public Customer findByCustNameLikeAndCustIndustry(String custName,String custIndustry);
}
多个参数时,必须对应上位置