映射单向多对一的关联关系
Customer
@Table(name = "customer2")
@Entity
public class Customer {
private Integer id;
private String lastName;
private String email;
private int age;
private Date createdTime;
private Date birth;
.......
}
Order
@Table(name = "order2")
@Entity
public class Order {
private Integer id;
private String orderName;
private Customer customer;
/**
* 映射单向多对一的关联关系:
* 1.使用@ManyToOne
* 2.使用JoinColumn来映射外键
* 使用name属性来映射外键列的字段名
* 3.可使用 @ManyToOne 的 fetch 属性来修改默认的关联属性的加载策略
*/
@ManyToOne
@JoinColumn(name = "customer_id")
public Customer getCustomer() {
return customer;
}
}
测试
/**
* 保存多对一时, 建议先保存 1 的一端, 后保存多的一端, 这样不会多出额外的 UPDATE 语句.
*/
@Test
public void testManyToOnePersist() {
Customer customer = new Customer();
customer.setAge(18);
customer.setBirth(new Date());
customer.setCreatedTime(new Date());
customer.setEmail("gg@163.com");
customer.setLastName("GG");
Order order1 = new Order();
order1.setOrderName("G-GG-1");
Order order2 = new Order();
order2.setOrderName("G-GG-2");
order1.setCustomer(customer);
order2.setCustomer(customer);
entityManager.persist(customer);
entityManager.persist(order1);
entityManager.persist(order2);
}
@Test
public void testManyToOneFind(){
Order order = entityManager.find(Order.class, 1);
System.out.println(order.getOrderName());
System.out.println(order.getCustomer().getLastName());
}
@Test
public void testManyToOneRemove(){
Customer customer = entityManager.find(Customer.class, 7);
entityManager.remove(customer);
}
@Test
public void testManyToOneUpdate(){
Order order = entityManager.find(Order.class, 2);
order.getCustomer().setLastName("FFF");
}
映射单向一对多的关联关系(跟前面是类似的)
Customer
@Table(name = "customer2")
@Entity
public class Customer2 {
private Integer id;
private String lastName;
private String email;
private int age;
private Date createdTime;
private Date birth;
private Set<Order> orders = new HashSet<>();
<!--
使用 @OneToMany 来映射 1-n 的关联关系
使用 @JoinColumn 来映射外键列的名称
可以使用 @OneToMany 的 fetch 属性来修改默认的加载策略
这里的外键还是在多的一方生成的
可以通过 @OneToMany 的 cascade 属性来修改默认的删除策略.
-->
@OneToMany
@JoinColumn(name = "customer_id")
public Set<Order> getOrders() {
return orders;
}
Order
@Table(name = "order2")
@Entity
public class Order2 {
private Integer id;
private String orderName;
.......
}
测试
//单向 1-n 关联关系执行保存时, 一定会多出 UPDATE 语句.
//因为 n 的一端在插入时不会同时插入外键列.
@Test
public void testOneToManyPersist(){
Customer customer = new Customer()
customer.setAge(18)
customer.setBirth(new Date())
customer.setCreatedTime(new Date())
customer.setEmail("mm@163.com")
customer.setLastName("MM")
Order order1 = new Order()
order1.setOrderName("O-MM-1")
Order order2 = new Order()
order2.setOrderName("O-MM-2")
//建立关联关系
customer.getOrders().add(order1)
customer.getOrders().add(order2)
order1.setCustomer(customer)
order2.setCustomer(customer)
//执行保存操作
entityManager.persist(customer)
entityManager.persist(order1)
entityManager.persist(order2)
}
//默认对关联的多的一方使用懒加载的加载策略.
//可以使用 @OneToMany 的 fetch 属性来修改默认的加载策略
@Test
public void testOneToManyFind(){
Customer customer = entityManager.find(Customer.class, 9)
System.out.println(customer.getLastName())
System.out.println(customer.getOrders().size())
}
//默认情况下, 若删除 1 的一端, 则会先把关联的 n 的一端的外键置空, 然后进行删除.
//可以通过 @OneToMany 的 cascade 属性来修改默认的删除策略.
@Test
public void testOneToManyRemove(){
Customer customer = entityManager.find(Customer.class, 8)
entityManager.remove(customer)
}
@Test
public void testUpdate(){
Customer customer = entityManager.find(Customer.class, 10)
customer.getOrders().iterator().next().setOrderName("O-XXX-10")
}
映射双向多对一的关联关系()
双方默认都维护外键(外键在多的一方)
Customer
@Table(name="JPA_CUTOMERS")
@Entity
public class Customer {
private Integer id;
private String lastName;
private String email;
private int age;
private Date createdTime;
private Date birth;
private Set<Order> orders = new HashSet<>();
@JoinColumn(name="CUSTOMER_ID")
@OneToMany(fetch=FetchType.LAZY,cascade={CascadeType.REMOVE})
public Set<Order> getOrders() {
return orders;
}
..........
}
Order
@Table(name="JPA_ORDERS")
@Entity
public class Order {
private Integer id;
private String orderName;
private Customer customer;
@JoinColumn(name="CUSTOMER_ID")
@ManyToOne(fetch=FetchType.LAZY)
public Customer getCustomer() {
return customer;
}
.......
}
测试
//若是双向 1-n 的关联关系, 执行保存时
//因为双方都维护外键所以肯定有多余的sql语句,所以我们需要由一方放弃维护
//双向1-多关联关系,建议放弃1的一方维护外键(学生记老师的名字比老师记学生的要方便)
//放弃维护关联关系:使用 @OneToMany中的mapperBy属性,属性值name="多的一方中本类的引用"
//注意:如果使用 mappedBy 属性并指明让谁来维护外键,所以自己维护外键的JoinColumn要删除
@Test
public void testOneToManyPersist(){
Customer customer = new Customer()
customer.setAge(18)
customer.setBirth(new Date())
customer.setCreatedTime(new Date())
customer.setEmail("mm@163.com")
customer.setLastName("MM")
Order order1 = new Order()
order1.setOrderName("O-MM-1")
Order order2 = new Order()
order2.setOrderName("O-MM-2")
//建立关联关系
customer.getOrderSet().add(order1)
customer.getOrderSet().add(order2)
order1.setCustomer(customer)
order2.setCustomer(customer)
//执行保存操作
entityManager.persist(customer)
entityManager.persist(order1)
entityManager.persist(order2)
}
//双向关联find()方法默认都是懒加载
//可以使用 @OneToMany 的 fetch 属性来修改默认的加载策略
@Test
public void testOneToManyFind(){
Customer customer = entityManager.find(Customer.class, 2)
System.out.println(customer.getLastName())
System.out.println("---------------------")
System.out.println(customer.getOrderSet().size())
System.out.println("+++++++++++++++++++++++++++++++")
Order order = entityManager.find(Order.class, 2)
System.out.println(order.getOrderName())
System.out.println("------------------------")
System.out.println(order.getCustomer())
}
//默认情况下, 若删除 1 的一端, 则会先把关联的 n 的一端的外键置空, 然后进行删除.
//但是如果要删除的哪一方放弃了外键维护那么就删除不了会报错(外键约束)
@Test
public void testOneToManyRemove(){
Customer customer = entityManager.find(Customer.class, 1)
entityManager.remove(customer)
}
@Test
public void testUpdate(){
Customer customer = entityManager.find(Customer.class, 2)
customer.getOrderSet().iterator().next().setOrderName("dddd")
// customer.getOrderSet().iterator().next().setOrderName("O-XXX-10")
}
映射双向一对一的关联关系
Manager
@Table(name = "managers")
@Entity
public class Manager {
private Integer id;
private String name;
private Department department;
@OneToOne(mappedBy = "manager")
public Department getDepartment() {
return department;
}
}
DepartMent
@Table(name = "department")
@Entity
public class Department {
private Integer id;
private String deptName;
private Manager manager;
@OneToOne()
@JoinColumn(name = "user_id",unique = true)
public Manager getManager() {
return manager;
}
}
测试
@Test
public void testOneToOnePersistence(){
Manager mgr = new Manager();
mgr.setName("M-BB");
Department dept = new Department();
dept.setDeptName("D-BB");
mgr.setDepartment(dept);
dept.setManager(mgr);
entityManager.persist(mgr);
entityManager.persist(dept);
}
@Test
public void testOneToOneFind2(){
Manager mgr = entityManager.find(Manager.class, 1);
System.out.println(mgr.getName());
System.out.println(mgr.getDepartment().getClass().getName());
}
@Test
public void testOneToOneFind(){
Department dept = entityManager.find(Department.class, 1);
System.out.println(dept.getDeptName());
System.out.println(dept.getManager().getClass().getName());
}
}
映射双向多对多的关联关系(由一方放弃主键维护)
Item
@Table(name = "items")
@Entity
public class Item {
@Id
@GeneratedValue
private Integer id;
@Column(name = "item_name")
private String itemName;
/**
* 使用@JoinTable来映射中间表:
* @JoinTable(name="中间表名称",
* joinColumns=@joinColumn(name="本类的外键",
* referencedColumnName="本类与外键对应的主键"),
* inversejoinColumns=@JoinColumn(name="对方类的外键",
* referencedColunName="对方类与外键对应的主键")
* )
*
*/
@ManyToMany
@JoinTable(name = "item_category",
joinColumns = @JoinColumn(name = "item_id", referencedColumnName = "id"),
inverseJoinColumns = @JoinColumn(name = "category_id", referencedColumnName = "id")
)
private Set<Category> categories = new HashSet<>();
Category
@Table(name = "category")
@Entity
public class Category {
@Id
@GeneratedValue
private Integer id;
@Column(name = "category_name")
private String categoryName;
@ManyToMany(mappedBy = "categories")
private Set<Item> items = new HashSet<>();
}
测试(跟hibernate一样)
//多对所的保存
@Test
public void testManyToManyPersist(){
Item i1 = new Item()
i1.setItemName("i-1")
Item i2 = new Item()
i2.setItemName("i-2")
Category c1 = new Category()
c1.setCategoryName("C-1")
Category c2 = new Category()
c2.setCategoryName("C-2")
//设置关联关系
i1.getCategories().add(c1)
i1.getCategories().add(c2)
i2.getCategories().add(c1)
i2.getCategories().add(c2)
c1.getItems().add(i1)
c1.getItems().add(i2)
c2.getItems().add(i1)
c2.getItems().add(i2)
//执行保存
entityManager.persist(i1)
entityManager.persist(i2)
entityManager.persist(c1)
entityManager.persist(c2)
}
//对于关联的集合对象, 默认使用懒加载的策略.
//使用维护关联关系的一方获取, 还是使用不维护关联关系的一方获取, SQL 语句相同.
@Test
public void testManyToManyFind(){
// Item item = entityManager.find(Item.class, 5)
// System.out.println(item.getItemName())
//
// System.out.println(item.getCategories().size())
Category category = entityManager.find(Category.class, 3)
System.out.println(category.getCategoryName())
System.out.println(category.getItems().size())
}