1、值类型的集合
集合元素是普通类型
(1)、数据存放类型
Set
HashSet 无序,不重复
List
有序,可重复
Map
键值对
HashMap 无序,不重复(以key为准)
-----------------------------------------------
数组
Bag
无序,可重复
List
集合映射的表结构学习路线图:
(2)、映射集合属性——set
Set
HashSet 无序,不重复
User实体:
private Integer id;
private String name;
private Set addressSet = new HashSet();
User.hbm.xml:
private static SessionFactory sessionFactory;
//初始化工厂
static {
Configuration configuration = new Configuration();
//读取指定的配置文件
configuration.configure();
//configuration.buildSessionFactory();
ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build();
sessionFactory = configuration.buildSessionFactory(serviceRegistry);
}
@Test
public void testSave(){
User user = new User();
user.setName("张三");
user.getAddressSet().add("江苏省");
user.getAddressSet().add("江苏省");
user.getAddressSet().add("南京市");
//获取session
Session session = sessionFactory.openSession();
//开启事务
Transaction tx =session.beginTransaction();
session.save(user);
//提交事务
tx.commit();
//关闭session,释放资源
session.close();
}
由于set是不重复的,所以只会存在一个“江苏省”
(3)、映射集合属性——list
List
有序,可重复
User.hbm.xml:
user.getAddressList().add("江苏省");
user.getAddressList().add("南京市");
user.getAddressList().add("南京市");
由于list是允许重复的,因此会有两个”南京市“
(4)、映射集合属性——数组
User.hbm.xml:
// >> 数组
user.setAddressArray(new String[] { "御富科贸园", "棠东东路" });
System.out.println(Arrays.toString(user.getAddressArray()));
(5)、映射集合属性——MAP
User.hbm.xml:
// >> Map集合
user.getAddressMap().put("公司", "御富科贸园");
user.getAddressMap().put("家庭", "棠东东路");
(6)、映射集合属性——BAG
Bag
无序,可重复
List
User实体:
private List addressBag = new ArrayList();
User.hbm.xml:
测试app:
// >> Bag集合
user.getAddressBag().add("御富科贸园");
user.getAddressBag().add("棠东东路");
user.getAddressBag().add("棠东东路");
使用集合属性时,一定要使用接口,而不能声明为具体的实现类。
因为经过Session操作后,集合就变成了Hibernate自己的集合实现类。
(7)、sort属性——set、map(效率低,不常用)
使用sort属性要使用有序set,TreeSet。
测试app:
sort属性:"unsorted|natural|comparatorClass"
默认为:unsorted
内存排序
User.hbm.xml:
User user = new User();
user.setName("张三");
user.setAddressSet(new TreeSet());
user.getAddressSet().add("3江苏省");
user.getAddressSet().add("3江苏省");
user.getAddressSet().add("1南京市");
(8)、order-by属性
order-by属性:写的是order by 子句,是SQL语句,是操作的集合表。DESC降序,ASC升序。
这是在查询数据时指定orderby子句。
测试app:
User.hbm.xml:
集合元素是另一个实体
(1)、一对多关联关系
只需要两张表
对于一对多的关系,需要考虑的操作:
- 保存,有关联关系
- 获取,可以获取到关联的对方
- 解除关联关系
- 删除对象,对关联对象的影响
没有外键的可以放弃维护,有外键的必须维护。被依赖的要先保存,不被依赖的后保存。
Department.hbm.xml:
package cn.itcast.f_hbm_oneToMany;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.junit.Test;
public class App {
private static SessionFactory sessionFactory = new Configuration()//
.configure()//
.addClass(Department.class)// 添加Hibernate实体类(加载对应的映射文件)
.addClass(Employee.class)// 添加Hibernate实体类(加载对应的映射文件)
.buildSessionFactory();
// 保存,有关联关系
@Test
public void testSave() throws Exception {
Session session = sessionFactory.openSession();
session.beginTransaction();
// --------------------------------------------
// 新建对象
Department department = new Department();
department.setName("开发部");
Employee employee1 = new Employee();
employee1.setName("张三");
Employee employee2 = new Employee();
employee2.setName("李四");
// 关联起来
employee1.setDepartment(department);
employee2.setDepartment(department);
department.getEmployees().add(employee1);
department.getEmployees().add(employee2);
// 保存
// session.save(employee1);
// session.save(employee2);
session.save(department); // 保存部门
// --------------------------------------------
session.getTransaction().commit();
session.close();
}
// 获取,可以获取到关联的对方
@Test
public void testGet() throws Exception {
Session session = sessionFactory.openSession();
session.beginTransaction();
// --------------------------------------------
// 获取一方,并显示另一方信息
Department department = (Department) session.get(Department.class, 1);
System.out.println(department);
System.out.println(department.getEmployees());
// Employee employee = (Employee) session.get(Employee.class, 1);
// System.out.println(employee);
// System.out.println(employee.getDepartment());
// --------------------------------------------
session.getTransaction().commit();
session.close();
}
// 解除关联关系
@Test
public void testRemoveRelation() throws Exception {
Session session = sessionFactory.openSession();
session.beginTransaction();
// --------------------------------------------
// // 从员工方解除
// Employee employee = (Employee) session.get(Employee.class, 1);
// employee.setDepartment(null);
// 从部门方解除(与inverse有关系,为false时可以解除)
Department department = (Department) session.get(Department.class, 1);
department.getEmployees().clear();
// --------------------------------------------
session.getTransaction().commit();
session.close();
}
// 删除对象,对关联对象的影响
@Test
public void testDelete() throws Exception {
Session session = sessionFactory.openSession();
session.beginTransaction();
// --------------------------------------------
// // 删除员工方(多方),对对方没有影响
// Employee employee = (Employee) session.get(Employee.class,2);
// session.delete(employee);
// 删除部门方(一方)
// a, 如果没有关联的员工:能删除。
// b, 如果有关联的员工且inverse=true,由于不能维护关联关系,所以会直接执行删除,就会有异常
// c, 如果有关联的员工且inverse=false,由于可以维护关联关系,他就会先把关联的员工的外键列设为null值,再删除自己。
Department department = (Department) session.get(Department.class, 4);
session.delete(department);
// --------------------------------------------
session.getTransaction().commit();
session.close();
}
}
级联:用于一对多,一对一;不用于多对多,多对一
维护关联关系:
对于一对多:
就是设置
外键列的值。
对于多对多:
就是插入或删除
中间表中的记录。
(2)、多对多关联关系
需要三张表,多出一张中间表,两个外键
Student.hbm.xml:
package cn.itcast.g_hbm_manyToMany;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.junit.Test;
public class App {
private static SessionFactory sessionFactory = new Configuration()//
.configure()//
.addClass(Student.class)// 添加Hibernate实体类(加载对应的映射文件)
.addClass(Teacher.class)// 添加Hibernate实体类(加载对应的映射文件)
.buildSessionFactory();
// 保存,有关联关系
@Test
public void testSave() throws Exception {
Session session = sessionFactory.openSession();
session.beginTransaction();
// --------------------------------------------
// 新建对象
Student student1 = new Student();
student1.setName("王同学");
Student student2 = new Student();
student2.setName("李同学");
Teacher teacher1 = new Teacher();
teacher1.setName("赵老师");
Teacher teacher2 = new Teacher();
teacher2.setName("蔡老师");
// 关联起来
student1.getTeachers().add(teacher1);
student1.getTeachers().add(teacher2);
student2.getTeachers().add(teacher1);
student2.getTeachers().add(teacher2);
teacher1.getStudents().add(student1);
teacher1.getStudents().add(student2);
teacher2.getStudents().add(student1);
teacher2.getStudents().add(student2);
// 保存
session.save(student1);
session.save(student2);
session.save(teacher1);
session.save(teacher2);
// --------------------------------------------
session.getTransaction().commit();
session.close();
}
// 获取,可以获取到关联的对方
@Test
public void testGet() throws Exception {
Session session = sessionFactory.openSession();
session.beginTransaction();
// --------------------------------------------
// 获取一方,并显示另一方信息
Teacher teacher = (Teacher) session.get(Teacher.class, 3L);
System.out.println(teacher);
System.out.println(teacher.getStudents());
// --------------------------------------------
session.getTransaction().commit();
session.close();
}
// 解除关联关系
@Test
public void testRemoveRelation() throws Exception {
Session session = sessionFactory.openSession();
session.beginTransaction();
// --------------------------------------------
// 如果inverse=false就可以解除,如果为true就不可以解除
Teacher teacher = (Teacher) session.get(Teacher.class, 3L);
teacher.getStudents().clear();
// --------------------------------------------
session.getTransaction().commit();
session.close();
}
// 删除对象,对关联对象的影响
@Test
public void testDelete() throws Exception {
Session session = sessionFactory.openSession();
session.beginTransaction();
// --------------------------------------------
// a, 如果没有关联的对方:能删除。
// b, 如果有关联的对方且inverse=false,由于可以维护关联关系,他就会先删除关联关系,再删除自己。
// c, 如果有关联的对方且inverse=true,由于不能维护关联关系,所以会直接执行删除自己,就会有异常。
Teacher teacher = (Teacher) session.get(Teacher.class, 9L);
session.delete(teacher);
// --------------------------------------------
session.getTransaction().commit();
session.close();
}
}
双向关联
单向关联:
单向多对一
单向一对多
单向多对多
3、对象的状态
临时状态测试(transient):
与数据库没有对应,跟Session没有关联。
一般是新new出的对象。
Department department = new Department();
department.setName("研发部");
System.out.println(department.getId());
session.save(department);
System.out.println(department.getId());
刚开始得到的ID为null,后面得到的ID为11;
save()的过程就是将临时状态进行持久化!
持久化状态(Persist):
对象在Session的管理之中,最终会有对应的数据库记录。
特点:
(1)、有OID(唯一标识符)
(2)、对对象的修改会同步到数据库。
在session内的代码:
//获取一方
Employee employee = (Employee) session.get(Employee.class, 9);
System.out.println(employee);
employee.setName("i");
会直接修改掉数据库中的数据
游离状态测试(Detached):
数据库中有对应记录,但对象不在Session管理之中。
修改此状态对象时数据库不会有变化。
删除状态(Removed):
执行了delete()后的对象。
- save():把临时状态变为持久化状态(交给Sessioin管理) 会生成:insert into ...
- update():把游离状态变为持久化状态 会生成:update ...
- saveOrUpdate():把临时或游离状态转为持久化状态 会生成:insert into 或 update ...
- delete():把持久化或游离转为删除状态 会生成:delete ...
- get():获取数据,是持久化状态 会生成:select ... where id=?
- load():获取数据,是持久化状态 会生成:select ... where
一、操作实体对象的
save()
update()
saveOrUpdate()
delete()
二、操作缓存的
clear()
evict() 驱逐单个对象
flush() 执行sql语句,提交事务默认先进行flush。save和查询get比较特殊会直接flush
三、查询实体对象的
get()
load()
createQuery()
createCriteria()
加载方式 返回值 如果数据不存在
------------------------------------------------------------------------------
get 立即加载 真实对象或null 返回null
load 延迟加载 代理对象 抛异常
package cn.itcast.h_session_method;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.junit.Test;
public class App {
private static SessionFactory sessionFactory = new Configuration()//
.configure()//
.addClass(User.class)// 添加Hibernate实体类(加载对应的映射文件)
.buildSessionFactory();
// save():把临时状态变为持久化状态(交给Sessioin管理)
// 会生成:insert into ...
@Test
public void testSave() throws Exception {
Session session = sessionFactory.openSession();
session.beginTransaction();
// --------------------------------------------
User user = new User(); // 临时状态
user.setName("test");
session.save(user); // 变为了持久化状态
// --------------------------------------------
session.getTransaction().commit();
session.close();
user.setName("李四"); // 游离状态
System.out.println(user.getName()); // 游离状态
}
// update():把游离状态变为持久化状态
// 会生成:update ...
// 在更新时,对象不存在就报错
@Test
public void testUpdate() throws Exception {
Session session = sessionFactory.openSession();
session.beginTransaction();
// --------------------------------------------
User user = (User) session.get(User.class, 1);
System.out.println(user.getName()); // 持久化状态
// session.clear(); // 清除Session中所有的对象
session.evict(user); // 清除Session中一个指定的对象
user.setName("newname3");
session.update(user);
System.out.println("----");
// session.flush(); // 刷出到数据库
// --------------------------------------------
session.getTransaction().commit(); //
session.close();
}
// saveOrUpdate():把临时或游离状态转为持久化状态
// 会生成:insert into 或 update ...
// 在更新时,对象不存在就报错
// 本方法是根据id判断对象是什么状态的:如果id为原始值(对象的是null,原始类型数字是0)就是临时状态,如果不是原始值就是游离状态。
@Test
public void testSaveOrUpdate() throws Exception {
Session session = sessionFactory.openSession();
session.beginTransaction();
// --------------------------------------------
User user = new User();
user.setId(3); // 自己生成一个游离状态对象
user.setName("newName");
session.saveOrUpdate(user);
// --------------------------------------------
session.getTransaction().commit();
session.close();
}
// delete():把持久化或游离转为删除状态
// 会生成:delete ...
// 如果删除的对象不存在,就会抛异常
@Test
public void testDelete() throws Exception {
Session session = sessionFactory.openSession();
session.beginTransaction();
// --------------------------------------------
// User user = (User) session.get(User.class, 2); // 持久化
User user = new User();
user.setId(300);
session.delete(user);
session.flush();
System.out.println("---");
// --------------------------------------------
session.getTransaction().commit();
session.close();
}
// get():获取数据,是持久化状态
// 会生成:select ... where id=?
// 会马上执行sql语句
// 如果数据不存在,就返回null
@Test
public void testGet() throws Exception {
Session session = sessionFactory.openSession();
session.beginTransaction();
// --------------------------------------------
User user = (User) session.get(User.class, 5); // 持久化
System.out.println(user.getClass());
// System.out.println("---");
// System.out.println(user.getName());
// --------------------------------------------
session.getTransaction().commit();
session.close();
}
// load():获取数据,是持久化状态
// 会生成:select ... where id=?
// load()后返回的是一个代理对象,要求类不能是final的,否则不能生成子类代理,就不能使用懒加载功能了。
// 让懒加载失效的方式:一、把实体写成final的;二、在hbm.xml中写
// 不会马上执行sql语句,而是在第1次使用非id或class属性时执行sql。
// 如果数据不存在,就抛异常:ObjectNotFoundException
@Test
public void testLoad() throws Exception {
Session session = sessionFactory.openSession();
session.beginTransaction();
// --------------------------------------------
User user = (User) session.load(User.class, 5);
System.out.println(user.getClass());
System.out.println("---");
System.out.println(user.getId());
System.out.println(user.getName());
// System.out.println(user.getName());
// --------------------------------------------
session.getTransaction().commit();
session.close();
}
// 操作大量数据,要防止Session中对象过多而内存溢出
@Test
public void testBatchSave() throws Exception {
Session session = sessionFactory.openSession();
session.beginTransaction();
// --------------------------------------------
for (int i = 0; i < 30; i++) {
User user = new User();
user.setName("测试");
session.save(user);
if (i % 10 == 0) {
session.flush(); // 先刷出
session.clear(); // 再清空
}
}
// --------------------------------------------
session.getTransaction().commit();
session.close();
}
}
4、回顾
一、集合映射。
类型 Java中声明 映射元素
-------------------------------------------------------
Set Set
List List
Map Map
一些重要的属性:
inverse:
是否放弃维护关联关系。
默认是false,表示可以维护。
实体类型的集合映射中可以使用(一对多、多对多)。
sort:
在内存中排序(类似于TreeSet)
默认为unsorted,即不排序。
在无序的集合映射中可以使用。
order-by:
使用数据库排序,即在SQL中增加orderby子句(类似于LinkedHashSet)。
默认不排序,这里指定的是sql语句中的orderby子句。
在无序的集合映射中可以使用。
cascade:
级联。
默认为none。
在所有的关联关系映射中可以使用。
常用的值:all, save-update, delete, none.
三、Session中的方法。
对象的状态:
Session中 数库中
---------------------------------------------------
临时 无 无
持久化 有 最终会有
游离 无 有
删除 调用了delete()方法后
1,操作实体对象的
save()
update()
saveOrUpdate()
delete()
2,操作缓存的
clear() 清空Session缓存,不会执行sql语句。
evict()
flush() 马上执行sql语句,不会清楚Session缓存。
3,查询实体对象的
get()
load()
createQuery()
createCriteria()