Hibernate框架学习之一(关系模型)
Hibernate是一种orm技术框架,处于领域对象和数据库的中间层次
一、概述
1. 作为面向对象的思考者,希望最理想的情况是在使用对象的时候,最少的关注数据库
2. 对象与关系型数据库在领域概念上却又有着天然的不一致
(1)领域概念应对成对象是需要有行为的 (2) 对象的概念在数据的表中不是完全一样的
下面就总结一下对象的关系在数据库中的样子,同时引出Hibernate的几种表达关系注解的使用方式
@OneToOne @OneToMany @ManyToOne @ManyToMany
二、具体
1、对象之间的一对一关系
对象领域:一个对象指向另一个对象的指针
数据库领域: 一个表的外键关联另一个表的主键
我们使用@OneToOne的方式进行一对一关联
@Entity @Table(name = "orders") public class Order { @Id @GeneratedValue(strategy = GenerationType.AUTO) private int id; private String name; @OneToOne @JoinColumn(name = "productId") private Product product; public Order() { // TODO Auto-generated constructor stub } public Order(String name) { this.name = name; } @Override public String toString() { return "Order [id=" + id + ", name=" + name + "]"; } }
解释:@OneToOne 是关系的标记,@JoinColum是主动定义外键的名称,如果不定义,会默认搜索Product对应的表的名称默认定义为tablename_id
Product的定义
@Entity @Table(name = "products") public class Product { @Id @GeneratedValue(strategy = GenerationType.AUTO) private int id; private String name; public Product(String name) { this.name = name; } public Product() { // TODO Auto-generated constructor stub } @Override public String toString() { return "Product [name=" + name + "]"; } }
在这种情况下,对应的数据库表是:
补充:
如果希望在面向对象的领域product也能找到order,就需要在Product类中保存一个指向Order的指针,如果还是用@OneToOne就会在product中额外加一个外键
为了避免数据库再加外键,如何实现呢? 使用mappedBy
//product指的是对方的product属性 @OneToOne(mappedBy = "product") private Order order;
mappedby的
关于级联处理理解,下面是对象的依赖关系:
A ---> B --->C
1. A是关系维护者
下面我们可以使用实例来证明一下:
@Test public void testSaveOrder() { Order order = new Order("dfp"); Product product = new Product("machine"); order.setProduct(product); orderdao.save(order); System.out.println(order.toString()); }
上面的代码,product被设置到了order中,当order被保存到数据库中的时候,是否会同步保存product呢?
如果需要同步保存produt需要将其cascade选项设置为CASCADE.ALL
@OneToOne(cascade = CascadeType.ALL) @JoinColumn(name = "productId") private Product product;
2. 对象之间多对一的关系
最简单的情况: 比如多个商品可以关联一个品牌
领域代码如下:
@Entity @Table(name = "productItems") public class ProductItem { @Id @GeneratedValue(strategy = GenerationType.AUTO) private int id; private String name; @ManyToOne @JoinColumn(name = "lableName") private Lable lable; public ProductItem() { // TODO Auto-generated constructor stub } public ProductItem(String name) { this.name = name; } public void setLable(Lable lable) { this.lable = lable; } @Override public String toString() { return "ProductItem [name=" + name + ", lable=" + lable + "]"; } }
@Entity @Table(name = "lables") public class Lable { @Id @GeneratedValue(strategy = GenerationType.AUTO) private int id; private String name; public Lable(String name) { this.name = name; } public Lable() { // TODO Auto-generated constructor stub } @Override public String toString() { return "Lable [name=" + name + "]"; } }
测试用例中的使用
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = {"classpath:config/databaseContext.xml"}) public class TestLabelAndProductItem_ManyToOne { @Autowired ProductRepository productRepository; @Autowired LableRepository lableRepository; @Before public void setup(){ } @Test public void test() { Lable lable = new Lable("Addidas"); lableRepository.save(lable); ProductItem productItem1 = new ProductItem("xie"); ProductItem productItem2 = new ProductItem("frute"); productItem1.setLable(lable); productItem2.setLable(lable); productRepository.save(productItem1); productRepository.save(productItem2); } }
用例的执行结果:
3. 对象之间的一对多的关系(包含反向的多对一)
对象模型: ShoppingCard (1)---- product(n) (那么 ShoppingCard 对应 product 是1对多的关系product 对应 ShoppingCard 是多对一的关系)
数据库模型:
(1) 选取ShoppingCard和product的主键,建立起一个新表ShoppingCards_products
对应的代码如下:
@Entity @Table(name = "shoppingCards") public class ShoppingCard { @Id @GeneratedValue(strategy = GenerationType.AUTO) private int id; public ShoppingCard() { // TODO Auto-generated constructor stub } @OneToMany(cascade = CascadeType.ALL) private List<Product> products = new ArrayList<Product>(); public void addProduct(Product product){ products.add(product); } }
@Entity @Table(name = "products") public class Product { @Id @GeneratedValue(strategy = GenerationType.AUTO) private int id; private String name; //product指的是对方的product属性 @OneToOne(mappedBy = "product") private Order order; public Product(String name) { this.name = name; } public Product() { // TODO Auto-generated constructor stub } @Override public String toString() { return "Product [name=" + name + "]"; } }
(2) product的外键对应的是shoppingcard的主键
建立product的多对一的关联,同时建立外键
@ManyToOne @JoinColumn(name = "shopppingcard") private ShoppingCard card;
建立数据库模型如下
多生成了一个shoppingCards和products的联合的表:如下图的shoppingCards_products
向领域对象(关系中的“一”)中添加mappedby
@OneToMany(cascade = CascadeType.ALL, mappedBy = "card") private List<Product> products = new ArrayList<Product>();
对象 “多”不变
@ManyToOne @JoinColumn(name = "shopppingcard") @NotNull private ShoppingCard card;
四、多对多的关系
未完待续
作为多年的C++程序员,最近在看java的hibernate时发现考虑级联问题的思维方式同c++中思考对象的内存管理的思路是一致的。