RDBMS : Relational database management system
Object | RDBMS | |
---|---|---|
粒度 | 类 | 表 |
继承 | 有 | 无 |
唯一性 |
a==b a.equals(b) |
主键 |
关联 | 引用 | 外键 |
数据访问 | 逐级访问 | SQL数量要少 |
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> <version>2.1.7.RELEASE</version> </dependency>
@Data // 没有@Table注解,表名即为Product @Entity(name = "Product") public class Product { @Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequence-generator") @SequenceGenerator(name = "sequence-generator", sequenceName = "product_sequence") private Long id; @Column(name = "product_name") private String name; }
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.joda</groupId> <artifactId>joda-money</artifactId> <version>1.0.1</version> </dependency> <dependency> <groupId>org.jadira.usertype</groupId> <artifactId>usertype.core</artifactId> <version>6.0.1.GA</version> </dependency>
@MappedSuperclass @Data @NoArgsConstructor @AllArgsConstructor public class BaseEntity implements Serializable { @Id // 如果strategy采用GenerationType.IDENTITY,使用数据库的自增主键,不会生成sequence表 @GeneratedValue private Long id; @Column(updatable = false) @CreationTimestamp private Date createTime; @UpdateTimestamp private Date updateTime; }
@Entity @Table(name = "T_MENU") @Builder @Data @ToString(callSuper = true) @NoArgsConstructor @AllArgsConstructor @EqualsAndHashCode(callSuper = true) public class Coffee extends BaseEntity { private String name; @Column @Type(type = "org.jadira.usertype.moneyandcurrency.joda.PersistentMoneyMinorAmount", parameters = {@org.hibernate.annotations.Parameter(name = "currencyCode", value = "CNY")}) private Money price; }
@Entity @Table(name = "T_ORDER") @Builder @Data @ToString(callSuper = true) @NoArgsConstructor @AllArgsConstructor @EqualsAndHashCode(callSuper = true) public class Order extends BaseEntity { private String customer; @ManyToMany @JoinTable(name = "T_ORDER_COFFEE") // 映射表 private List<Coffee> items; @Enumerated // 映射成integer @Column(nullable = false) private OrderState state; } public enum OrderState { INIT, PAID, BREWING, BREWED, TAKEN, CANCELLED }
spring.jpa.hibernate.ddl-auto=create-drop spring.jpa.properties.hibernate.show_sql=true spring.jpa.properties.hibernate.format_sql=true
Hibernate: drop table t_menu if exists Hibernate: drop table t_order if exists Hibernate: drop table t_order_coffee if exists Hibernate: drop sequence if exists hibernate_sequence
Hibernate: create sequence hibernate_sequence start with 1 increment by 1 Hibernate: create table t_menu ( id bigint not null, create_time timestamp, update_time timestamp, name varchar(255), price bigint, primary key (id) ) Hibernate: create table t_order ( id bigint not null, create_time timestamp, update_time timestamp, customer varchar(255), state integer not null, primary key (id) ) Hibernate: create table t_order_coffee ( order_id bigint not null, items_id bigint not null ) Hibernate: alter table t_order_coffee add constraint FKj2swxd3y69u2tfvalju7sr07q foreign key (items_id) references t_menu Hibernate: alter table t_order_coffee add constraint FKjnvwi9aq5s71k7dru924mleq7 foreign key (order_id) references t_order
Hibernate: drop table t_menu if exists Hibernate: drop table t_order if exists Hibernate: drop table t_order_coffee if exists Hibernate: drop sequence if exists hibernate_sequence
@EnableJpaRepositories JpaRepository<T, ID> extends PagingAndSortingRepository<T, ID> PagingAndSortingRepository<T, ID> extends CrudRepository<T, ID> CrudRepository<T, ID> extends Repository<T, ID>
public interface CoffeeRepository extends CrudRepository<Coffee, Long> { }
public interface OrderRepository extends CrudRepository<Order, Long> { }
@Slf4j @EnableJpaRepositories @SpringBootApplication public class SpringDataJpaApplication implements ApplicationRunner { @Autowired private CoffeeRepository coffeeRepository; @Autowired private OrderRepository orderRepository; public static void main(String[] args) { SpringApplication.run(SpringDataJpaApplication.class, args); } @Override public void run(ApplicationArguments args) throws Exception { initOrders(); } private void initOrders() { Coffee espresso = Coffee.builder().name("espresso") .price(Money.of(CurrencyUnit.of("CNY"), 20.0)).build(); coffeeRepository.save(espresso); log.info("Coffee: {}", espresso); Coffee latte = Coffee.builder().name("latte") .price(Money.of(CurrencyUnit.of("CNY"), 30.0)).build(); coffeeRepository.save(latte); log.info("Coffee: {}", latte); Order order = Order.builder().customer("zhongmingmao") .items(Arrays.asList(espresso)) .state(OrderState.INIT).build(); orderRepository.save(order); log.info("Order: {}", order); order = Order.builder().customer("zhongmingmao") .items(Arrays.asList(espresso, latte)) .state(OrderState.INIT).build(); orderRepository.save(order); log.info("Order: {}", order); } }
Hibernate: call next value for hibernate_sequence Hibernate: insert into t_menu (create_time, update_time, name, price, id) values (?, ?, ?, ?, ?) Coffee: Coffee(super=BaseEntity(id=1, createTime=Sat Aug 31 14:27:26 CST 2019, updateTime=Sat Aug 31 14:27:26 CST 2019), name=espresso, price=CNY 20.00)
Hibernate: call next value for hibernate_sequence Hibernate: insert into t_menu (create_time, update_time, name, price, id) values (?, ?, ?, ?, ?) Coffee: Coffee(super=BaseEntity(id=2, createTime=Sat Aug 31 14:27:26 CST 2019, updateTime=Sat Aug 31 14:27:26 CST 2019), name=latte, price=CNY 30.00)
Hibernate: call next value for hibernate_sequence Hibernate: insert into t_order (create_time, update_time, customer, state, id) values (?, ?, ?, ?, ?) Hibernate: insert into t_order_coffee (order_id, items_id) values (?, ?) Order: Order(super=BaseEntity(id=3, createTime=Sat Aug 31 14:27:26 CST 2019, updateTime=Sat Aug 31 14:27:26 CST 2019), customer=zhongmingmao, items=[Coffee(super=BaseEntity(id=1, createTime=Sat Aug 31 14:27:26 CST 2019, updateTime=Sat Aug 31 14:27:26 CST 2019), name=espresso, price=CNY 20.00)], state=INIT)
Hibernate: call next value for hibernate_sequence Hibernate: insert into t_order (create_time, update_time, customer, state, id) values (?, ?, ?, ?, ?) Hibernate: insert into t_order_coffee (order_id, items_id) values (?, ?) Hibernate: insert into t_order_coffee (order_id, items_id) values (?, ?) Order: Order(super=BaseEntity(id=4, createTime=Sat Aug 31 14:27:26 CST 2019, updateTime=Sat Aug 31 14:27:26 CST 2019), customer=zhongmingmao, items=[Coffee(super=BaseEntity(id=1, createTime=Sat Aug 31 14:27:26 CST 2019, updateTime=Sat Aug 31 14:27:26 CST 2019), name=espresso, price=CNY 20.00), Coffee(super=BaseEntity(id=2, createTime=Sat Aug 31 14:27:26 CST 2019, updateTime=Sat Aug 31 14:27:26 CST 2019), name=latte, price=CNY 30.00)], state=INIT)
@NoRepositoryBean // 告知Spring无需为BaseRepository创建Bean public interface BaseRepository<T, ID> extends PagingAndSortingRepository<T, ID> { List<T> findTop3ByOrderByUpdateTimeDescIdAsc(); }
public interface CoffeeRepository extends BaseRepository<Coffee, Long> { }
public interface OrderRepository extends BaseRepository<Order, Long> { List<Order> findByCustomerOrderById(String customer); List<Order> findByItems_Name(String name); }
private void findOrders() { coffeeRepository.findAll(Sort.by(Sort.Direction.DESC, "id")) .forEach(coffee -> log.info("Loading {}", coffee)); List<Order> orders = orderRepository.findTop3ByOrderByUpdateTimeDescIdAsc(); log.info("findTop3ByOrderByUpdateTimeDescIdAsc: {}", getJoinedOrderId(orders)); orders = orderRepository.findByCustomerOrderById("zhongmingmao"); log.info("findByCustomerOrderById: {}", getJoinedOrderId(orders)); // 不开启事务会因为没有Session而报LazyInitializationException // run方法加上@Transactional注解 orders.forEach(order -> { log.info("Order: {}", order.getId()); order.getItems().forEach(coffee -> log.info(" Item {}", coffee)); }); orders = orderRepository.findByItems_Name("latte"); log.info("findByItems_Name: {}", getJoinedOrderId(orders)); } private String getJoinedOrderId(List<Order> orders) { return orders.stream().map(order -> order.getId().toString()).collect(Collectors.joining(",")); }
Hibernate: select coffee0_.id as id1_0_, coffee0_.create_time as create_t2_0_, coffee0_.update_time as update_t3_0_, coffee0_.name as name4_0_, coffee0_.price as price5_0_ from t_menu coffee0_ order by coffee0_.id desc Loading Coffee(super=BaseEntity(id=2, createTime=Sat Aug 31 15:03:49 CST 2019, updateTime=Sat Aug 31 15:03:49 CST 2019), name=latte, price=CNY 30.00) Loading Coffee(super=BaseEntity(id=1, createTime=Sat Aug 31 15:03:49 CST 2019, updateTime=Sat Aug 31 15:03:49 CST 2019), name=espresso, price=CNY 20.00)
Hibernate: select order0_.id as id1_1_, order0_.create_time as create_t2_1_, order0_.update_time as update_t3_1_, order0_.customer as customer4_1_, order0_.state as state5_1_ from t_order order0_ order by order0_.update_time desc, order0_.id asc limit ? findTop3ByOrderByUpdateTimeDescIdAsc: 4,3
Hibernate: select order0_.id as id1_1_, order0_.create_time as create_t2_1_, order0_.update_time as update_t3_1_, order0_.customer as customer4_1_, order0_.state as state5_1_ from t_order order0_ where order0_.customer=? order by order0_.id asc findByCustomerOrderById: 3,4 Order: 3 Item Coffee(super=BaseEntity(id=1, createTime=Sat Aug 31 15:03:49 CST 2019, updateTime=Sat Aug 31 15:03:49 CST 2019), name=espresso, price=CNY 20.00) Order: 4 Item Coffee(super=BaseEntity(id=1, createTime=Sat Aug 31 15:03:49 CST 2019, updateTime=Sat Aug 31 15:03:49 CST 2019), name=espresso, price=CNY 20.00) Item Coffee(super=BaseEntity(id=2, createTime=Sat Aug 31 15:03:49 CST 2019, updateTime=Sat Aug 31 15:03:49 CST 2019), name=latte, price=CNY 30.00)
Hibernate: select order0_.id as id1_1_, order0_.create_time as create_t2_1_, order0_.update_time as update_t3_1_, order0_.customer as customer4_1_, order0_.state as state5_1_ from t_order order0_ left outer join t_order_coffee items1_ on order0_.id=items1_.order_id left outer join t_menu coffee2_ on items1_.items_id=coffee2_.id where coffee2_.name=? findByItems_Name: 4