属性文件application.yml编辑

其实这里配置文件也可以是application.properties,但是个人感觉application.yml的配置结构更加清晰

1
2
3
4
5
6
7
8
9
10
11
spring:
datasource:
username: root
password: root
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost/test?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true
jpa:
hibernate:
ddl-auto: update #有则改,无则建
show-sql: true
database-platform: org.hibernate.dialect.MySQL5Dialect # hibernate 5.5 方言

这里的ddl-auto配置项属性有四种:

  • create
    每次加载hibernate时都会删除上一次的生成的表,然后根据你的model类再重新来生成新表,哪怕两次没有任何改变也要这样执行,这就是导致数据库表数据丢失的一个重要原因。
  • create-drop
    每次加载hibernate时根据model类生成表,但是sessionFactory一关闭,表就自动删除。
  • update
    最常用的属性,第一次加载hibernate时根据model类会自动建立起表的结构(前提是先建立好数据库),以后加载hibernate时根据 model类自动更新表结构,即使表结构改变了但表中的行仍然存在不会删除以前的行。要注意的是当部署到服务器后,表结构是不会被马上建立起来的,是要等 应用第一次运行起来后才会。
  • validate
    每次加载hibernate时,验证创建数据库表结构,只会和数据库中的表进行比较,不会创建新表,但是会插入新值。

复合主键实现案例

博主这里的需求是这样的:我有一张产品表(Product),但是产品表的主键是两个:品牌名称(name)和品牌类型(type),所以这里提出者两个属性作为复合主键新建一个类叫Goods。

Product表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
package club.hdqyf.demo04.springbootdemo04.entity;

import javax.persistence.EmbeddedId;
import javax.persistence.Entity;

/**
* 商品库存
*
* @author Garen
*/
@Entity
public class Product {
/**
* 商品主键
*/
@EmbeddedId //嵌入主键标识
private Goods goods;

/**
* 商品数量
*/
private int number;

public Goods getGoods() {
return goods;
}

public void setGoods(Goods goods) {
this.goods = goods;
}

public int getNumber() {
return number;
}

public void setNumber(int number) {
this.number = number;
}

public Product(Goods goods, int number) {
this.goods = goods;
this.number = number;
}

public Product() {
}

@Override
public String toString() {
return "Product{" +
"goods=" + goods +
", number=" + number +
'}';
}
}
主要就是注意这里的@EmbeddedId注解,他就是用来标识我们的复合主键的

Goods表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
package club.hdqyf.demo04.springbootdemo04.entity;

import javax.persistence.Embeddable;
import java.io.Serializable;

/**
* 商品主键
*
* @author Garen
*/
@Embeddable //标注复合主键
public class Goods implements Serializable {
/**
* 商品品牌
*/
private String name;

/**
* 商品类型
*/
private String type;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getType() {
return type;
}

public void setType(String type) {
this.type = type;
}

public Goods(String name, String type) {
this.name = name;
this.type = type;
}

public Goods() {
}
}
这里需要注意的有两点:

  1.类顶部加上@Embeddable注解标识这是一个复合主键类
  2.需要引入序列化接口Serializable

测试运行查看

因为我们配置文件配置了
jpa:
 hibernate:
  ddl-auto: update #有则改,无则建
所以这里如果我们数据库有product表,则更新这张表,如果没有则新建这张表
目前我们是没有这张表的,所以运行会新建一个product表


扩展——复合主键的查找

其实复合主键的查找并没有想象的那么困难,和普通查找其实是一样的,再加上JPA框架实现数据操作比较简单

这里我们编写一个ProductDao接口来进行数据操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package club.hdqyf.demo04.springbootdemo04.dao;

import club.hdqyf.demo04.springbootdemo04.entity.Goods;
import club.hdqyf.demo04.springbootdemo04.entity.Product;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

import java.util.List;

/**
* Product表的dao操作接口
* @author Garen
*/
public interface ProductDao extends JpaRepository<Product, Goods> {
/**
* 统计某个品牌的个数
* @param name 品牌名称
* @return 返回个数
*/
@Query("select count(goods.name) from Product where goods.name = :name")
public int CountByName(@Param(value = "name") String name);

/**
* 查找某个品牌下的各个类型详情
* @param name 品牌名称
* @return Product对象信息数组
*/
@Query("select goods.name,goods.type,number from Product where goods.name = :name")
public List<Object> findByName(@Param(value = "name") String name);
}
因为我们运用到了JPA框架,所以这里需要让dao接口类继承JpaRepository<T, ID>

如果你要使用自己的sql语句,不使用JPA所提供的,也很简单你只需要在SQL语句结束后,nativeQuery = true,就像这样:

1
2
@Query(value = "select name,type,number from product where name = :name",nativeQuery = true)
public List<Object> findByName(@Param(value = "name") String name);

在测试类简单做个测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
package club.hdqyf.demo04.springbootdemo04;

import club.hdqyf.demo04.springbootdemo04.dao.ProductDao;
import club.hdqyf.demo04.springbootdemo04.entity.Goods;
import club.hdqyf.demo04.springbootdemo04.entity.Product;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.List;

@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringbootDemo04ApplicationTests {
@Autowired
ProductDao productDao;

@Test
public void contextLoads() {
productDao.save(new Product(new Goods("小米","9"),50));
productDao.save(new Product(new Goods("小米","8"),100));

System.out.println("----------------------------------------");
System.out.println("小米总数为"+productDao.CountByName("小米"));
System.out.println("----------------------------------------");

System.out.println("--------------小米各品牌详情--------------");
List<Object> list = productDao.findByName("小米");

for (Object product: list ) {
Object[] os = (Object[]) product;
for (Object o1: os) {
System.out.print(o1);
System.out.println(",");
}
System.out.println();
}
}
}

结果:


ps:因作者能力有限,有错误的地方请见谅

  • 喜欢这篇文章的话可以用快捷键 Ctrl + D 来收藏本页

最后更新: 2018年09月19日 16:03

原始链接: https://blog.hdqyf.club/2018/05/25/20180525-SpringBoot—复合主键/

× 请我吃糖~
打赏二维码