配置數(shù)據(jù)庫及實現(xiàn) Hibernate 的查改增刪
1. pom.xml 新增數(shù)據(jù)庫的相關依賴
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
2. 配置數(shù)據(jù)庫的信息
spring:
datasource;
username: root
driver-class-name: com.mysql.jdbc.Driver
password: 123456
url: jdbc:mysql://192.168.31.157:3306/wxorder_sell?characterEncoding=utf-8&useSSL=false
jpa:
show-sql:true
3. 配置 entity,映射 mysql 表結(jié)構(gòu)
新建 dataobject/ProductCategory
Note: 不需要把所有的表字段映射到類屬性,比如 createTime / updateTime ,這種不寫也照常運行。
//映射 mysql
@Entity
// 當類名與表名不一致時,使用此注解
@Table(name = "wxorder_product_category")
// lombok 的注解,使用此注解自動添加 get/set 方法
@Data
//@DynamicUpdate
public class ProductCategory{
@Id
@GenerateValue
//@GenerateValue(strategy = GenerationType.IDENTITY)
private Integer categoryId;
private String categoryName;
private Integer categoryType;
//private Date createTime;
// private Date updateTIme;
}
4. 配置DAO層
新建 repository/ProductCategoryRepository
// Integer 是 ProductCategory 映射的表的主鍵類型
public interface ProductCategoryRepositoy extends JpaRepository<ProductCategory, Integer>
5. 測試 Hibernate 的查改增刪
右鍵 ProductCategoryRepository , goto,自動創(chuàng)建ProductCategoryRepositoryTest
(1)查詢
// 這兩個注解必填
@RunWith(SpringRunner.class)
@SpringBootTest
public class ProductCategoryRepositoryTest{
// 接口對接了許多方法,所以必須引入
@AutoWired
private ProductCategoryRepository repository;
@Test
public void findOneTest(){
Optional<ProductCategory> productCategory = repository.findById(1);
System.out.println(productCategory);
}
}
版本問題踩的坑
- 原來根據(jù)主鍵查詢,findOne,現(xiàn)在是
Optional<ProductCategory> productCategory = repository.findById(1);
ProductCategory productCategory = repository.findById(1).get();
如果依舊使用findOne()的寫法,會報錯
Inferred type 'S' for type parameter 'S' is not within its bound; should extends com.example.demo.Girl
這類錯誤
- java9 的錯誤,由于模塊化導致了一些錯誤
Caused by: java.lang.ClassNotFoundException: javax.xml.bind.JAXBException
需要在 maven 中添加一些依賴
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.2.11</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-core</artifactId>
<version>2.2.11</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.2.11</version>
</dependency>
(2)插入/insert
@Test
public void insertTest(){
ProductCategory productCategory = new ProductCategory();
productCategory.setCategoryName("冬日甜品");
productCategory.setCategoryType(7);
repository.save(productCategory);
}
這時會拋出一個異常,具體的解釋請看Spring 中使用Hibernate,修改 ProductCategory 的 categoryId 的注解
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Integer categoryId;
(3) update
update operation is like insert operation except update operation needs specify the primary key
- update directly
@Test
public void updateDirectly(){
ProductCategory productCategory = new ProductCategory();
productCategory.setCategoryId(2);
productCategory.setCategoryName("圣誕特供");
repository.save(productCategory);
}
- 先查詢再更新
這種操作很常見,在很多場景中我們需要先查詢信息,然后根據(jù)查詢的信息做一些判斷然后再更新。
這部分主要是想講注解@DynamicUpdate的作用,所以先在 ProductCategory 上添加2個屬性
private Date createTime;
private Date updateTime;
先注意一下表中id為2 的update time,然后進行更新操作
@Test
public void updateAfterQuery(){
ProductCategory productCategory = repository.findById(2).get();
productCategory.setCategoryType(20);
repository.save(productCategory);
}
這時發(fā)現(xiàn)數(shù)據(jù)更新了,但是updateTime沒有更新。sql 日志為
Hibernate: select productcat0_.category_id as category1_0_0_, productcat0_.category_name as category2_0_0_, productcat0_.category_type as category3_0_0_, productcat0_.create_time as create_t4_0_0_, productcat0_.update_time as update_t5_0_0_ from wxorder_product_category productcat0_ where productcat0_.category_id=?
Hibernate: select productcat0_.category_id as category1_0_0_, productcat0_.category_name as category2_0_0_, productcat0_.category_type as category3_0_0_, productcat0_.create_time as create_t4_0_0_, productcat0_.update_time as update_t5_0_0_ from wxorder_product_category productcat0_ where productcat0_.category_id=?
Hibernate: update wxorder_product_category set category_name=?, category_type=?, create_time=?, update_time=? where category_id=?
在 ProductCategory 上添加注解 @DynamicUpdate,再次執(zhí)行,發(fā)現(xiàn)只有查詢?nèi)罩?/p>
Hibernate: select productcat0_.category_id as category1_0_0_, productcat0_.category_name as category2_0_0_, productcat0_.category_type as category3_0_0_, productcat0_.create_time as create_t4_0_0_, productcat0_.update_time as update_t5_0_0_ from wxorder_product_category productcat0_ where productcat0_.category_id=?
Hibernate: select productcat0_.category_id as category1_0_0_, productcat0_.category_name as category2_0_0_, productcat0_.category_type as category3_0_0_, productcat0_.create_time as create_t4_0_0_, productcat0_.update_time as update_t5_0_0_ from wxorder_product_category productcat0_ where productcat0_.category_id=?
這說明Hibernate 沒有進行 update 操作,why?因為我們更新的數(shù)據(jù)和表中的數(shù)據(jù)相同,這說明當更新的數(shù)據(jù)和表中的數(shù)據(jù)相同的時候,Hibernate是不會進行操作的。
修改代碼中更新的數(shù)據(jù),
@Test
public void updateAferQuery(){
ProductCategory productCategory = repository.findById(2).get();
productCategory.setCategoryType(12);
repository.save(productCategory);
}
這時再次觀察sql日志
Hibernate: select productcat0_.category_id as category1_0_0_, productcat0_.category_name as category2_0_0_, productcat0_.category_type as category3_0_0_, productcat0_.create_time as create_t4_0_0_, productcat0_.update_time as update_t5_0_0_ from wxorder_product_category productcat0_ where productcat0_.category_id=?
Hibernate: select productcat0_.category_id as category1_0_0_, productcat0_.category_name as category2_0_0_, productcat0_.category_type as category3_0_0_, productcat0_.create_time as create_t4_0_0_, productcat0_.update_time as update_t5_0_0_ from wxorder_product_category productcat0_ where productcat0_.category_id=?
Hibernate: update wxorder_product_category set category_type=? where category_id=?
看,添加上@DynamicUpdate后,Hibernate 的更新語句發(fā)生了變化。
(4) 刪除/delete
刪除操作非常簡單,只要刪除就ok了
@Test
public void deleteTest(){
repository.deleteById(1);
}
(5) 執(zhí)行完成后回滾
為了讓數(shù)據(jù)庫中不產(chǎn)生臟數(shù)據(jù),可以使用@Transactional注解
@Test
@Transactional
public void transacational(){
ProductCategory productCategory = new ProductCategory();
productCategory.setCategoryName("男生最愛");
productCategory.setCategoryType(123);
repository.save(productCategory);
}
(6) Hibernate 使用CategoryType 來查詢一組數(shù)據(jù)
- 需要在接口里定義一個接口,注意此接口必須符合一定的格式
public interface ProductCategoryRepository extends JpaRepository<ProductCategory, Integer>{
List<ProductCategory> findByCategoryTypeIn(List<Integer> categoryType);
}
- 測試方法
@Test
public void findByCategoryTypeInTest(){
List<Integer> list = Arrays.asList(3, 70);
List<ProductCategory> result = repository.findByCategoryTypeIn(list);
Assert.assertNotEquals(0, result.size());
}