image.png
文件目錄技巧
配置文件
<?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">
<!--spring 和 spring data jpa的配置-->
<!-- 1.創(chuàng)建entityManagerFactory對象交給spring容器管理-->
<bean id="entityManagerFactoty" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<!--配置的掃描的包(實(shí)體類所在的包) -->
<property name="packagesToScan" value="cn.itcast.domain" />
<!-- jpa的實(shí)現(xiàn)廠家 -->
<property name="persistenceProvider">
<bean class="org.hibernate.jpa.HibernatePersistenceProvider"/>
</property>
<!--jpa的供應(yīng)商適配器 -->
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<!--配置是否自動(dòng)創(chuàng)建數(shù)據(jù)庫表 -->
<property name="generateDdl" value="false" />
<!--指定數(shù)據(jù)庫類型 -->
<property name="database" value="MYSQL" />
<!--數(shù)據(jù)庫方言:支持的特有語法 -->
<property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect" />
<!--是否顯示sql -->
<property name="showSql" value="true" />
</bean>
</property>
<!--jpa的方言 :高級的特性 -->
<property name="jpaDialect" >
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
</property>
</bean>
<!--2.創(chuàng)建數(shù)據(jù)庫連接池 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="user" value="root"></property>
<property name="password" value="root"></property>
<property name="jdbcUrl" value="jdbc:mysql:///" ></property>
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
</bean>
<!--3.整合spring dataJpa-->
<jpa:repositories base-package="cn.itcast.dao" transaction-manager-ref="transactionManager"
entity-manager-factory-ref="entityManagerFactoty" ></jpa:repositories>
<!--4.配置事務(wù)管理器 -->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactoty"></property>
</bean>
<!-- 4.txAdvice-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="save*" propagation="REQUIRED"/>
<tx:method name="insert*" propagation="REQUIRED"/>
<tx:method name="update*" propagation="REQUIRED"/>
<tx:method name="delete*" propagation="REQUIRED"/>
<tx:method name="get*" read-only="true"/>
<tx:method name="find*" read-only="true"/>
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<!-- 5.aop-->
<aop:config>
<aop:pointcut id="pointcut" expression="execution(* cn.itcast.service.*.*(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut" />
</aop:config>
<!--5.聲明式事務(wù) -->
<!-- 6. 配置包掃描-->
<context:component-scan base-package="cn.itcast" ></context:component-scan>
</beans>
DAO層封裝
/**
* 符合SpringDataJpa的dao層接口規(guī)范
* JpaRepository<操作的實(shí)體類類型利虫,實(shí)體類中主鍵屬性的類型>
* * 封裝了基本CRUD操作
* JpaSpecificationExecutor<操作的實(shí)體類類型>
* * 封裝了復(fù)雜查詢(分頁)
*/
public interface CustomerDao extends JpaRepository<Customer,Long> ,JpaSpecificationExecutor<Customer> {
/**
* 案例:根據(jù)客戶名稱查詢客戶
* 使用jpql的形式查詢
* jpql:from Customer where custName = ?
*
* 配置jpql語句码泛,使用的@Query注解
*/
@Query(value="from Customer where custName = ?")
public Customer findJpql(String custName);
/**
* 案例:根據(jù)客戶名稱和客戶id查詢客戶
* jpql: from Customer where custName = ? and custId = ?
*
* 對于多個(gè)占位符參數(shù)
* 賦值的時(shí)候忠蝗,默認(rèn)的情況下,占位符的位置需要和方法參數(shù)中的位置保持一致
*
* 可以指定占位符參數(shù)的位置
* ? 索引的方式,指定此占位的取值來源
*/
@Query(value = "from Customer where custName = ?2 and custId = ?1")
public Customer findCustNameAndId(Long id,String name);
/**
* 使用jpql完成更新操作
* 案例 : 根據(jù)id更新,客戶的名稱
* 更新4號客戶的名稱怠堪,將名稱改為“黑馬程序員”
*
* sql :update cst_customer set cust_name = ? where cust_id = ?
* jpql : update Customer set custName = ? where custId = ?
*
* @Query : 代表的是進(jìn)行查詢
* * 聲明此方法是用來進(jìn)行更新操作
* @Modifying
* * 當(dāng)前執(zhí)行的是一個(gè)更新操作
*
*/
@Query(value = " update Customer set custName = ?2 where custId = ?1 ")
@Modifying
public void updateCustomer(long custId,String custName);
/**
* 使用sql的形式查詢:
* 查詢?nèi)康目蛻? * sql : select * from cst_customer;
* Query : 配置sql查詢
* value : sql語句
* nativeQuery : 查詢方式
* true : sql查詢
* false:jpql查詢
*
*/
//@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);
/**
* 方法名的約定:
* findBy : 查詢
* 對象中的屬性名(首字母大寫) : 查詢的條件
* CustName
* * 默認(rèn)情況 : 使用 等于的方式查詢
* 特殊的查詢方式
*
* findByCustName -- 根據(jù)客戶名稱查詢
*
* 再springdataJpa的運(yùn)行階段
* 會根據(jù)方法名稱進(jìn)行解析 findBy from xxx(實(shí)體類)
* 屬性名稱 where custName =
*
* 1.findBy + 屬性名稱 (根據(jù)屬性名稱進(jìn)行完成匹配的查詢=)
* 2.findBy + 屬性名稱 + “查詢方式(Like | isnull)”
* findByCustNameLike
* 3.多條件查詢
* findBy + 屬性名 + “查詢方式” + “多條件的連接符(and|or)” + 屬性名 + “查詢方式”
*/
public Customer findByCustName(String custName);
public List<Customer> findByCustNameLike(String custName);
//使用客戶名稱模糊匹配和客戶所屬行業(yè)精準(zhǔn)匹配的查詢
public Customer findByCustNameLikeAndCustIndustry(String custName,String custIndustry);
}
實(shí)體類封裝
/**
* 1.實(shí)體類和表的映射關(guān)系
* @Eitity
* @Table
* 2.類中屬性和表中字段的映射關(guān)系
* @Id
* @GeneratedValue
* @Column
*/
@Entity
@Table(name="cst_customer")
public class Customer {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="cust_id")
private Long custId;
@Column(name="cust_address")
private String custAddress;
@Column(name="cust_industry")
private String custIndustry;
@Column(name="cust_level")
private String custLevel;
@Column(name="cust_name")
private String custName;
@Column(name="cust_phone")
private String custPhone;
@Column(name="cust_source")
private String custSource;
public Long getCustId() {
return custId;
}
public void setCustId(Long custId) {
this.custId = custId;
}
public String getCustAddress() {
return custAddress;
}
public void setCustAddress(String custAddress) {
this.custAddress = custAddress;
}
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 getCustName() {
return custName;
}
public void setCustName(String custName) {
this.custName = custName;
}
public String getCustPhone() {
return custPhone;
}
public void setCustPhone(String custPhone) {
this.custPhone = custPhone;
}
public String getCustSource() {
return custSource;
}
public void setCustSource(String custSource) {
this.custSource = custSource;
}
@Override
public String toString() {
return "Customer{" +
"custId=" + custId +
", custAddress='" + custAddress + '\'' +
", custIndustry='" + custIndustry + '\'' +
", custLevel='" + custLevel + '\'' +
", custName='" + custName + '\'' +
", custPhone='" + custPhone + '\'' +
", custSource='" + custSource + '\'' +
'}';
}
}
測試類完成
@RunWith(SpringJUnit4ClassRunner.class) //聲明spring提供的單元測試環(huán)境
@ContextConfiguration(locations = "classpath:applicationContext.xml")//指定spring容器的配置信息
public class CustomerDaoTest {
@Autowired
private CustomerDao customerDao;
/**
* 根據(jù)id查詢
*/
@Test
public void testFindOne() {
Customer customer = customerDao.findOne(2l);
System.out.println(customer);
}
/**
* save : 保存或者更新
* 根據(jù)傳遞的對象是否存在主鍵id,
* 如果沒有id主鍵屬性:保存
* 存在id主鍵屬性名眉,根據(jù)id查詢數(shù)據(jù)粟矿,更新數(shù)據(jù)
*/
@Test
public void testSave() {
Customer customer = new Customer();
customer.setCustName("黑馬程序員");
customer.setCustLevel("vip");
customer.setCustIndustry("it教育");
customerDao.save(customer);
}
@Test
public void testUpdate() {
Customer customer = new Customer();
customer.setCustId(4l);
customer.setCustName("黑馬程序員很厲害");
customerDao.save(customer);
}
@Test
public void testDelete () {
customerDao.delete(3l);
}
/**
* 查詢所有
*/
@Test
public void testFindAll() {
List<Customer> list = customerDao.findAll();
for(Customer customer : list) {
System.out.println(customer);
}
}
/**
* 測試統(tǒng)計(jì)查詢:查詢客戶的總數(shù)量
* count:統(tǒng)計(jì)總條數(shù)
*/
@Test
public void testCount() {
long count = customerDao.count();//查詢?nèi)康目蛻魯?shù)量
System.out.println(count);
}
/**
* 測試:判斷id為4的客戶是否存在
* 1. 可以查詢以下id為4的客戶
* 如果值為空,代表不存在损拢,如果不為空陌粹,代表存在
* 2. 判斷數(shù)據(jù)庫中id為4的客戶的數(shù)量
* 如果數(shù)量為0,代表不存在福压,如果大于0掏秩,代表存在
*/
@Test
public void testExists() {
boolean exists = customerDao.exists(4l);
System.out.println("id為4的客戶 是否存在:"+exists);
}
/**
* 根據(jù)id從數(shù)據(jù)庫查詢
* @Transactional : 保證getOne正常運(yùn)行
*
* findOne:
* em.find() :立即加載
* getOne:
* em.getReference :延遲加載
* * 返回的是一個(gè)客戶的動(dòng)態(tài)代理對象
* * 什么時(shí)候用或舞,什么時(shí)候查詢
*/
@Test
@Transactional
public void testGetOne() {
Customer customer = customerDao.getOne(4l);
System.out.println(customer);
}
}
SpringDataJPA原理圖片分析
源碼分析
描述: springDataJpa的運(yùn)行過程和原理剖析
1.通過JdkDynamicAopProxy的invoke方法創(chuàng)建了一個(gè)動(dòng)態(tài)代理對象
2.SimpleJpaRepository當(dāng)中封裝了JPA的操作(借助JPA的api完成數(shù)據(jù)庫的CRUD)
3.通過hibernate完成數(shù)據(jù)庫操作(封裝了jdbc)
i.借助接口中的定義好的方法完成查詢
findOne(id):根據(jù)id查詢
ii.jpql的查詢方式
jpql : jpa query language (jpq查詢語言)
特點(diǎn):語法或關(guān)鍵字和sql語句類似
查詢的是類和類中的屬性
* 需要將JPQL語句配置到接口方法上
1.特有的查詢:需要在dao接口上配置方法
2.在新添加的方法上,使用注解的形式配置jpql查詢語句
3.注解 : @Query
iii.sql語句的查詢
1.特有的查詢:需要在dao接口上配置方法
2.在新添加的方法上蒙幻,使用注解的形式配置sql查詢語句
3.注解 : @Query
value :jpql語句 | sql語句
nativeQuery :false(使用jpql查詢) | true(使用本地查詢:sql查詢)
是否使用本地查詢
iiii.方法名稱規(guī)則查詢
*是對jpql查詢映凳,更加深入一層的封裝
*我們只需要按照SpringDataJpa提供的方法名稱規(guī)則定義方法,不需要再配置jpql語句邮破,完成查詢
*
findBy開頭: 代表查詢
對象中屬性名稱(首字母大寫)
*含義:根據(jù)屬性名稱進(jìn)行查詢
延遲加載和立即加載
em.find() :立即加載
getOne:
* em.getReference :延遲加載
* * 返回的是一個(gè)客戶的動(dòng)態(tài)代理對象
* * 什么時(shí)候用诈豌,什么時(shí)候查詢
/**
* 根據(jù)id從數(shù)據(jù)庫查詢
* @Transactional : 保證getOne正常運(yùn)行
*
* findOne:
* em.find() :立即加載
* getOne:
* em.getReference :延遲加載
* * 返回的是一個(gè)客戶的動(dòng)態(tài)代理對象
* * 什么時(shí)候用,什么時(shí)候查詢
*/
@Test
@Transactional
public void testGetOne() {
Customer customer = customerDao.getOne(4l);
System.out.println(customer);
}
注意2:測試jpql的更新操作
1 需要增加Transactional 添加事務(wù)支持
2 需要 設(shè)置自動(dòng)提交 默認(rèn)會自動(dòng)回滾
/**
* 測試jpql的更新操作
* * springDataJpa中使用jpql完成 更新/刪除操作
* * 需要手動(dòng)添加事務(wù)的支持
* * 默認(rèn)會執(zhí)行結(jié)束之后抒和,回滾事務(wù)
* @Rollback : 設(shè)置是否自動(dòng)回滾
* false | true
*/
@Test
@Transactional //添加事務(wù)的支持
@Rollback(value = false)
public void testUpdateCustomer() {
customerDao.updateCustomer(4l,"黑馬程序員");
}