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++中思考对象的内存管理的思路是一致的。

posted @ 2015-07-10 16:24  Tony_DFS  阅读(325)  评论(0编辑  收藏  举报