1、Ecplise hibernate插件安装:
下载zip格式的Eclipse插件,(http://sourceforge.net/projects/jboss/files/JBossTools/JBossTools4.1.x/hibernatetools-Update-4.1.1.Final_2013-12-08_01-06-33-B605.zip)
Eclipse-》Help-》Install New Software.. -》add..-》Archive 选择刚才下载的hibernate插件
2、Hibernate开发步骤
1)创建hibernate配置文件(hibernate.cfg.xml):配置数据库相关配置信息和hibernate相关初始化配置信息
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <!-- 数据库连接配置信息 --> <property name="connection.username">root</property> <property name="connection.password">root</property> <property name="connection.driver_class">com.mysql.jdbc.Driver</property> <property name="connection.url"><![CDATA[jdbc:mysql://127.0.0.1:3306/atguigu_hibernate?useUnicode=true&characterEncoding=utf8]]></property> <!-- hibernate基本配置信息 --> <!-- hibernate数据库方言 --> <property name="dialect">org.hibernate.dialect.MySQLInnoDBDialect</property> <!-- 执行操作时,是否在后台打印SQL语句 --> <property name="show_sql">true</property> <!-- 是否对SQL语句进行格式化 --> <property name="format_sql">true</property> <!-- 指定自动生成数据表的策略 --> <!-- create: 会根据*.hbm,xml文件生成新的数据表,每次都会删除上一次的数据表重新生成表 create-drop:会根据*.hbm,xml文件生成新的数据表,但是每次sessionFactory关闭都会删除表 update:最常用的值,会根据*.hbm,xml文件生成新的数据表,如果*.hbm,xml所定义的表结构与数据库中表结果不同,hibernate将更新数据表结构,但不会删除已有的行和列 validate:会和数据库中的表进行比较,如果*.hbm,xml配置文件中的列在数据库中不存在,则抛出异常 --> <property name="hbm2ddl.auto">update</property> <!-- 设置 Hibernate 的事务隔离级别 --> <property name="connection.isolation">2</property> <!-- 删除对象后, 使其 OID 置为 null --> <property name="use_identifier_rollback">true</property> <!-- 配置 C3P0 数据源 --> <property name="hibernate.c3p0.max_size">10</property> <property name="hibernate.c3p0.min_size">5</property> <property name="c3p0.acquire_increment">2</property> <property name="c3p0.idle_test_period">2000</property> <property name="c3p0.timeout">2000</property> <property name="c3p0.max_statements">10</property> <!-- 设定 JDBC 的 Statement 读取数据的时候每次从数据库中取出的记录条数 --> <property name="hibernate.jdbc.fetch_size">100</property> <!-- 设定对数据库进行批量删除,批量更新和批量插入的时候的批次大小 --> <property name="jdbc.batch_size">30</property> <!-- 指定关联的map映射 --> <mapping resource="com/shma/hibernate/entity/User.hbm.xml"/> <mapping resource="com/shma/hibernate/entity/Worker.hbm.xml"/> </session-factory> </hibernate-configuration>
2)创建持久化层实体类
package com.shma.hibernate.entity; import java.sql.Blob; import java.util.Date; public class User { private Integer id; private String name; private Integer age; private Date date; private String oldContent; private Blob image; private String desc; public User() { super(); } public User(String name, Integer age, Date date) { super(); this.name = name; this.age = age; this.date = date; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public Date getDate() { return date; } public void setDate(Date date) { this.date = date; } public String getDesc() { return desc; } public void setDesc(String desc) { this.desc = desc; } public String getOldContent() { return oldContent; } public void setOldContent(String oldContent) { this.oldContent = oldContent; } public Blob getImage() { return image; } public void setImage(Blob image) { this.image = image; } } package com.shma.hibernate.entity; public class Worker { private int id; private String name; private Pay pay; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Pay getPay() { return pay; } public void setPay(Pay pay) { this.pay = pay; } } package com.shma.hibernate.entity; public class Pay { private double monthPay; private double yearPay; private int yearDay; private Worker worker; public double getMonthPay() { return monthPay; } public void setMonthPay(double monthPay) { this.monthPay = monthPay; } public double getYearPay() { return yearPay; } public void setYearPay(double yearPay) { this.yearPay = yearPay; } public int getYearDay() { return yearDay; } public void setYearDay(int yearDay) { this.yearDay = yearDay; } public Worker getWorker() { return worker; } public void setWorker(Worker worker) { this.worker = worker; } }
3)创建对象-关系映射文件
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="com.shma.hibernate.entity"> <!-- class: 1)dynamic-insert:默认为false,如果设置为true,则表示保存一个insert时,动态生成sql语句,仅保存字段不能为空的值 2)dynamic-update:默认为false,如果设置为true,则表示更新一个update时,动态生成sql语句,仅更新修改的字段值 3)select-before-update:在执行update之前,是否执行一次查询,默认为false --> <class name="User" table="USER" select-before-update="true" dynamic-insert="true"> <!-- id: unsaved-value:表示持久化对象的oid如果为该属性值20,则认为是一个临时对象,执行保存操作 type:可以为java类型,也可以设置为hibernate类型 class:设置持久化类设置唯一标识符方式 increment:由hibernate先执行查询max,再+1,并发下不安全 identity:底层数据库自增,底层数据库必须设置为自增,适用于mysql、sqlserver sequence:底层数据库提供序列生成唯一标识符,如oracle hilo:hibernate生成组件,在数据库创建一张表,读取并修改该表保存自增 native:常用,自动识别使用identity、sequence、hilo --> <id name="id" type="java.lang.Integer" unsaved-value="20"> <column name="ID" /> <generator class="native" /> </id> <!-- property: 1) access:制定hibernate默认属性访问策略,默认为property,调用getter和setter方法,若设置为field,则通过反射访问 2) unique:设置属性唯一值 3) index:设置索引 4) length: 设置字段长度 5) scale: 当字段为double或float类型时,指定小数点后保留位数 6) formula: 派生属性,sql表达式,用()括起来 --> <property name="name" type="java.lang.String" access="property" unique="true" index="user_index" length="20"> <column name="NAME" /> </property> <property name="age" type="java.lang.Integer" index="user_index"> <column name="AGE" /> </property> <!-- 在 Java 中, 代表时间和日期的类型包括: java.util.Date 和 java.util.Calendar. 此外, 在 JDBC API 中还提供了 3 个扩展了 java.util.Date 类的子类: java.sql.Date, java.sql.Time 和 java.sql.Timestamp, 这三个类分别和标准 SQL 类型中的 DATE, TIME 和 TIMESTAMP 类型对 应在标准 SQL 中, DATE 类型表示日期, TIME 类型表示时间, TIMESTAMP 类型表示时间戳, 同时包含日期和时间信息 --> <property name="date" type="timestamp"> <column name="DATE" /> </property> <property name="desc" formula="(select concat(name,',',date) from user t where t.id = id)"></property> <!-- 映射大对象 --> <property name="oldContent"> <column name="OLD_CONTENT" sql-type="text"></column> </property> <!-- mysql数据库不支持 <property name="realContent"> <column name="real_Content" sql-type="clob"></column> </property> --> <property name="image"> <column name="image" sql-type="blob"></column> </property> </class> </hibernate-mapping>
4)通过Hibernate API编程访问操作数据库代码
package com.shma.hibernate.entity; import java.sql.Date; import java.text.ParseException; import java.text.SimpleDateFormat; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; import org.hibernate.service.ServiceRegistry; import org.hibernate.service.ServiceRegistryBuilder; import org.junit.Test; public class UserTest { @Test public void test() { //1) 创建一个SessionFactory对象 SessionFactory sessionFactory = null; //创建Configuration配置对象,加载hibernate基本配置文件和关系对象映射文件 Configuration configuration = new Configuration().configure(); //弃用 // sessionFactory = configuration.buildSessionFactory(); //创建ServiceRegistry服务注册对象,hibernate任何配置和服务都需要在这个对象中注册后才可以使用 ServiceRegistry serviceRegistry = new ServiceRegistryBuilder() .applySettings(configuration.getProperties()) .buildServiceRegistry(); try { sessionFactory = configuration.buildSessionFactory(serviceRegistry); } catch (Exception e) { e.printStackTrace(); } //2) 创建一个Session对象 Session session = sessionFactory.openSession(); //3) 开启事务 Transaction transaction = session.beginTransaction(); //4) 执行相关操作 User user = null; try { user = new User("马韶华", 23, new Date(new SimpleDateFormat("yyyy-MM-dd").parse("1989-11-10").getTime())); } catch (ParseException e) { // TODO Auto-generated catch block e.printStackTrace(); } session.save(user); //5) 提交事务 transaction.commit(); //6) 关闭Session对象 session.close(); //7) 关闭SessionFactroy对象 sessionFactory.close(); } }
3、Session
1)session接口是hibernate向引用程序提供的操作数据库的最主要的接口,提供了基本的增删改和加载java对象的操作;
2)session具有一个缓存,被称之为hibernate一级缓存;位于缓存中的对象称之为持久化对象;
package com.shma.hibernate.entity; import java.util.Date; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; import org.hibernate.service.ServiceRegistry; import org.hibernate.service.ServiceRegistryBuilder; import org.junit.After; import org.junit.Before; import org.junit.Test; public class UserTest { private SessionFactory sessionFactory = null; private Session session = null; private Transaction transaction = null; @Before public void init() { Configuration configuration = new Configuration().configure(); ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties()) .buildServiceRegistry(); sessionFactory = configuration.buildSessionFactory(serviceRegistry); session = sessionFactory.openSession(); transaction = session.beginTransaction(); } /** * clear(): 清理缓存 */ @Test public void clear() { User user = (User) session.get(User.class, 1); System.out.println(user); User user2 = (User) session.get(User.class, 1); System.out.println(user2); session.clear(); User user3 = (User) session.get(User.class, 1); System.out.println(user3); } /** * reflesh():会强制发送 SELECT 语句, 以使 Session 缓存中对象的状态和数据表中对应的记录保持一致!使数据库中的记录同步到session缓存中 */ @Test public void reflesh() { User user = (User) session.get(User.class, 1); System.out.println(user); session.refresh(user); System.out.println(user); } /** * flush(): 使session缓存中的数据同步到数据库中,为了保存一致,可能会发送对应的SQL语句操作 * * flush()被调用的契机: * 1) 手动调用session.flush()方法 * 2) 在Transaction对象提交事务之前,会先调用session对象的flush()方法,在提交事务 * 3) 执行HQL或者QBC查询时,如果缓存中持久化对象属性发生变化,则会先flush()一次,以保证查询出来的是最新的数据 * 4) 如果持久化对象主键采用native生成OID(记录的 ID 是由底层数据库使用自增的方式生成),在调用save()方法时,先发生insert()语句,以创建主键id,保证save()方法后主键id是存在的 */ @Test public void testSessionFlush() { // User user = (User) session.get(User.class, 1); // user.setAge(27); // user.setName("齐娇娇"); // // session.flush(); //将session缓存中的数据同步到数据库中,执行update方法,但是数据库值没有修改,没有commit // System.out.println(user); // User user = (User) session.get(User.class, 1); // // //执行HQL或者QBC查询时,如果缓存中持久化对象属性发生变化,则会先flush()一次,以保证查询出来的是最新的数据 // User user2 = (User) session.createCriteria(User.class).uniqueResult(); // // System.out.println(user == user2); User user3 = new User("孙威", 28, new Date()); session.save(user3); } /** * 验证session缓存 */ @Test public void testSessionCache() { User user = (User) session.get(User.class, 1); System.out.println(user); User user2 = (User) session.get(User.class, 1); //从session缓存中获取,没有查询数据库 System.out.println(user2); System.out.println(user == user2); } @After public void destory() { transaction.commit(); session.close(); sessionFactory.close(); } }
4、持久化对象状态
1)站在持久化的角度上,hibernate将对象分为四种状态:
持久化状态:存在session缓存中,存在数据库记录中,存在OID
临时状态:不存在session缓存中,不存在数据库记录中,不存在OID
游离状态:存在OID,不存在session缓存中,可能存在数据库记录中,一般情况下游离对象是由持久化对象转变而来
删除状态:存在OID,但是数据库中不存在对应的记录,不存在数据库中,不存在session缓存中
package com.shma.hibernate.entity; import java.sql.Connection; import java.sql.SQLException; import java.util.Date; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; import org.hibernate.jdbc.Work; import org.hibernate.service.ServiceRegistry; import org.hibernate.service.ServiceRegistryBuilder; import org.junit.After; import org.junit.Before; import org.junit.Test; public class UserTest2 { private SessionFactory sessionFactory = null; private Session session = null; private Transaction transaction = null; /** * 调用存储过程 */ @Test public void testDoWork() { session.doWork(new Work() { @Override public void execute(Connection conn) throws SQLException { //调用存储过程 } }); } /** * evict():从缓存中移除指定的持久化对象 */ @Test public void testEvict() { User user = (User) session.get(User.class, 8); User user2 = (User) session.get(User.class, 9); user.setName("nihao"); user2.setName("haha"); session.evict(user); } /** * delete: 执行删除操作. 只要 OID 和数据表中一条记录对应, 就会准备执行 delete 操作 * 若 OID 在数据表中没有对应的记录, 则抛出异常 * * 可以通过设置 hibernate 配置文件 hibernate.use_identifier_rollback 为 true, * 使删除对象后, 把其 OID 置为 null */ @Test public void testDelete() { // User user = new User(); // user.setId(1); // session.delete(user); User user = (User) session.get(User.class, 3); session.delete(user); System.out.println(user); } /** * saveOrUpdate: * 包含了save和update方法,当对象处于游离状态时,则执行save操作,当对象处于持久化状态时,则执行update操作 * 判断是否为临时状态: * 1、Java对象的OID为null * 2、如果OID在数据库表记录中不存在,则会抛出异常, * 除非映射文件中<id>设置了unsaved-value属性,并且java对象中的oid值与设置的unsaved-value值一致 */ @Test public void testSaveOrUpdate() { // User user = new User("王二", 22, new Date()); // // //user处于游离状态,执行save // session.saveOrUpdate(user); // // // 执行save操作后user转变为持久化对象 // user.setAge(45); // user.setName("王五"); // // session.saveOrUpdate(user); User user2 = new User("aidai", 10, new Date()); user2.setId(999); session.saveOrUpdate(user2); } /** * update(): * 1) 若更新一个持久化对象,不需要显示调用update方法,因为在调用Transaction的commit方法 * 时,会调用session的flush()方法 * * 2) 若更新一个游离对象,需要显示的调用update方法,把一个游离对象转换为持久化对象 * * 需要注意的地方: * 1、无论要更新的游离对象和数据库表中的记录是否一致(持久化对象会先检查,不一致才执行update),都会调用update * 操作,如何能让 update方法不再盲目的出发 update 语句呢 ? 在 .hbm.xml 文件的 class 节点设置 * select-before-update=true (默认为 false). 这个属性的含义是在每次update之前先查询一遍数 * 据库,如果有修改在执行update,但通常不需要设置该属性. * * 2、若数据表中没有对应的记录, 但还调用了 update 方法, 会抛出异常 * * 3、当 update() 方法关联一个游离对象时, * 如果在 Session 的缓存中已经存在相同 OID 的持久化对象, 会抛出异常. 因为在 Session 缓存中 * 不能有两个 OID 相同的对象! */ @Test public void testUpdate() { // 持久化对象,不需要显示调用update方法 User user = (User) session.get(User.class, 1); // user.setName("齐娇娇"); // session.update(user); // session.clear(); // 游离状态,必须显示调用update方法 // user.setName("马韶华"); // session.update(user); User user2 = (User) session.get(User.class, 1); session.update(user); //session 中已经存在user2 } @Before public void init() { Configuration configuration = new Configuration().configure(); ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties()) .buildServiceRegistry(); sessionFactory = configuration.buildSessionFactory(serviceRegistry); session = sessionFactory.openSession(); transaction = session.beginTransaction(); } /** * 1) 执行get()方法:立即执行查询操作加载对象,get为立即检索 * 执行load()方法:如不使用该对象,则不会执行查询操作,而是返回一个代理对象,load为延迟检索 * 2) 当使用load延时检索时,如果session关闭,可能会抛出LazyInitializationException异常 * 3) 如果查询的oid数据库没有对应的数据记录,并且session也没有关闭 * get方法返回null * load方法如果不使用实体对象属性,加载不会抛出异常,使用的时候会抛出异常 * */ @Test public void testLoad() { User user = (User) session.load(User.class, 10); System.out.println(user.getClass().getName()); // session.close(); System.out.println(user); } /** * get/load:根据一个oid,从数据库中加载一个持久化对象到session缓存中 */ @Test public void testGet() { User user = (User) session.get(User.class, 10); System.out.println(user.getClass().getName()); // session.close(); System.out.println(user); } /** * persist(): 和save方法一样保存记录到持久化对象 * 和save()方法区别:当对一个OID不为null的对象执行save时,会把对象以一个新oid保存到数据库中,而persist则会抛出异常 */ @Test public void testPersist() { User user = new User(); user.setAge(20); user.setDate(new Date()); user.setName("zhangsan"); user.setId(10); // 抛出异常 session.persist(user); } /** * save():用于将临时对象转换为持久化对象,插入记录 * 执行步骤:1) 使一个临时对象保存到session缓存中,转换为持久化对象 * 2) 为持久化对象生成唯一的UID * 3) 执行一条insert语句:在flush缓存时 * 4) 在save之前的设置id是无效的 * 5) 在save之后的设置id是不能被修改的,修改会抛出异常 */ @Test public void testSave() { User user = new User(); user.setAge(20); user.setDate(new Date()); user.setName("zhangsan"); // user.setId(10); // 设置id是无效的 session.save(user); System.out.println(user); user.setId(10); //save()后修改id,抛出异常 } @After public void destory() { transaction.commit(); session.close(); sessionFactory.close(); } @Test public void testWorker() { Worker worker = new Worker(); Pay pay = new Pay(); pay.setMonthPay(13000.23d); pay.setYearDay(5); pay.setYearPay(153422.12344d); worker.setName("马韶华"); worker.setPay(pay); session.save(worker); } }
5、映射对象关系
1)单向多对一
package com.shma.hibernate.entity.n21; public class Customer { private int customerId; private String customerName; public int getCustomerId() { return customerId; } public void setCustomerId(int customerId) { this.customerId = customerId; } public String getCustomerName() { return customerName; } public void setCustomerName(String customerName) { this.customerName = customerName; } @Override public String toString() { return "Customer [customerId=" + customerId + ", customerName=" + customerName + "]"; } } package com.shma.hibernate.entity.n21; public class Order { private int orderId; private String orderName; private Customer customer; public int getOrderId() { return orderId; } public void setOrderId(int orderId) { this.orderId = orderId; } public String getOrderName() { return orderName; } public void setOrderName(String orderName) { this.orderName = orderName; } public Customer getCustomer() { return customer; } public void setCustomer(Customer customer) { this.customer = customer; } @Override public String toString() { return "Order [orderId=" + orderId + ", orderName=" + orderName + ", customer=" + customer + "]"; } } package com.shma.hibernate.entity.n21; import static org.junit.Assert.*; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; import org.hibernate.service.ServiceRegistry; import org.hibernate.service.ServiceRegistryBuilder; import org.junit.After; import org.junit.Before; import org.junit.Test; public class TestN21 { private SessionFactory sessionFactory = null; private Session session = null; private Transaction transaction = null; @Before public void init() { Configuration configuration = new Configuration().configure(); ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties()) .buildServiceRegistry(); sessionFactory = configuration.buildSessionFactory(serviceRegistry); session = sessionFactory.openSession(); transaction = session.beginTransaction(); } @After public void destory() { transaction.commit(); session.close(); sessionFactory.close(); } @Test public void testMany2OneDel() { // Order order = (Order)session.get(Order.class, 2); // session.delete(order); // // session.delete(order.getCustomer()); //在不设定级联关系的情况下, 且 1 这一端的对象有 n 的对象在引用, 不能直接删除 1 这一端的对象 Customer customer = (Customer) session.get(Customer.class, 2); session.delete(customer); } @Test public void testMany2OneUpdate() { Order order = (Order)session.get(Order.class, 1); order.setOrderName("order-112222"); order.getCustomer().setCustomerName("AAAAAAAA"); } @Test public void testMany2OneGet() { Order order = (Order)session.get(Order.class, 1); System.out.println(order); System.out.println(order.getCustomer().getClass()); //如果session被关闭,将抛出异常 // session.close(); //延时加载Customer Customer customer = order.getCustomer(); System.out.println(customer); System.out.println(customer.getClass()); } @Test public void testMany2OneSave() { // Customer customer = new Customer(); // customer.setCustomerName("AAA"); // // Order order01 = new Order(); // order01.setOrderName("Order-01"); // // Order order02 = new Order(); // order02.setOrderName("Order-02"); // // order01.setCustomer(customer); // order02.setCustomer(customer); // // //先savecustomer,会saveorder,执行三次insert // session.save(customer); // session.save(order01); // session.save(order02); Customer customer = new Customer(); customer.setCustomerName("BBB"); Order order01 = new Order(); order01.setOrderName("Order-03"); Order order02 = new Order(); order02.setOrderName("Order-04"); order01.setCustomer(customer); order02.setCustomer(customer); //先save order,会save customer,执行三次insert,会执行2次update session.save(order01); session.save(order02); session.save(customer); } }
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="com.shma.hibernate.entity.n21.Customer" table="CUSTOMERS"> <id name="customerId" type="int"> <column name="CUSTOMER_ID" /> <generator class="native" /> </id> <property name="customerName" type="java.lang.String"> <column name="CUSTOMER_NAME" /> </property> </class> </hibernate-mapping> <?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <!-- Generated 2015-7-18 15:21:35 by Hibernate Tools 3.4.0.CR1 --> <hibernate-mapping package="com.shma.hibernate.entity.n21"> <class name="Order" table="ORDERS"> <id name="orderId" type="int"> <column name="ORDER_ID" /> <generator class="native" /> </id> <property name="orderName" type="java.lang.String"> <column name="ORDER_NAME" /> </property> <!-- 多对一映射关系 name:多这一端的一那一端的属性名称 class:一端的类型 column:一那一端对应在多端的外键名称 --> <many-to-one name="customer" class="Customer"> <column name="customer_id"></column> </many-to-one> </class> </hibernate-mapping>
2)双向一对多
package com.shma.hibernate.entity.n21.bath; import java.util.HashSet; import java.util.Set; public class Customer { private int customerId; private String customerName; /** * 1、声明集合需要使用接口,因为hibernate延迟加载,在获取集合的时候是获取到的hibernate内部集合实例 * 2、需要把集合进行初始化, 可以防止发生空指针异常 */ private Set<Order> orders = new HashSet<>(); public int getCustomerId() { return customerId; } public void setCustomerId(int customerId) { this.customerId = customerId; } public String getCustomerName() { return customerName; } public void setCustomerName(String customerName) { this.customerName = customerName; } public Set<Order> getOrders() { return orders; } public void setOrders(Set<Order> orders) { this.orders = orders; } } package com.shma.hibernate.entity.n21.bath; public class Order { private int orderId; private String orderName; private Customer customer; public int getOrderId() { return orderId; } public void setOrderId(int orderId) { this.orderId = orderId; } public String getOrderName() { return orderName; } public void setOrderName(String orderName) { this.orderName = orderName; } public Customer getCustomer() { return customer; } public void setCustomer(Customer customer) { this.customer = customer; } @Override public String toString() { return "Order [orderId=" + orderId + ", orderName=" + orderName + ", customer=" + customer + "]"; } } package com.shma.hibernate.entity.n21.bath; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; import org.hibernate.service.ServiceRegistry; import org.hibernate.service.ServiceRegistryBuilder; import org.junit.After; import org.junit.Before; import org.junit.Test; public class Test12N { private SessionFactory sessionFactory = null; private Session session = null; private Transaction transaction = null; @Before public void init() { Configuration configuration = new Configuration().configure(); ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties()) .buildServiceRegistry(); sessionFactory = configuration.buildSessionFactory(serviceRegistry); session = sessionFactory.openSession(); transaction = session.beginTransaction(); } @After public void destory() { transaction.commit(); session.close(); sessionFactory.close(); } @Test public void testOne2ManyDel() { //在不设定级联关系的情况下, 且 1 这一端的对象有 n 的对象在引用, 不能直接删除 1 这一端的对象 Customer customer = (Customer) session.get(Customer.class, 1); session.delete(customer.getOrders().iterator().next()); } @Test public void testOne2ManyUpdate() { Customer customer = (Customer) session.get(Customer.class, 1); customer.setCustomerName("CCCCCC"); Customer customer2 = (Customer) session.get(Customer.class, 2); customer.getOrders().iterator().next().setCustomer(customer2); } @Test public void testOne2ManyGet() { Customer customer = (Customer) session.get(Customer.class, 1); System.out.println(customer.getCustomerName()); //延时加载 //返回的多的一端的集合时 Hibernate 内置的集合类型. //该类型具有延迟加载和存放代理对象的功能. System.out.println(customer.getOrders().getClass()); //3. 可能会抛出 LazyInitializationException 异常 // session.close(); System.out.println(customer.getOrders().iterator().next().getOrderName()); //再需要使用集合中元素的时候进行初始化. } @Test public void testOne2ManySave() { // Customer customer = new Customer(); // customer.setCustomerName("AAA"); // // Order order01 = new Order(); // order01.setOrderName("Order-01"); // // Order order02 = new Order(); // order02.setOrderName("Order-02"); // // order01.setCustomer(customer); // order02.setCustomer(customer); // // customer.getOrders().add(order01); // customer.getOrders().add(order02); // // //先savecustomer,会saveorder,执行三次insert // session.save(customer); // session.save(order01); // session.save(order02); Customer customer = new Customer(); customer.setCustomerName("BBB"); Order order01 = new Order(); order01.setOrderName("Order-03"); Order order02 = new Order(); order02.setOrderName("Order-04"); order01.setCustomer(customer); order02.setCustomer(customer); customer.getOrders().add(order01); customer.getOrders().add(order02); //先save order,会save customer,执行三次insert,会执行2次update session.save(order01); session.save(order02); session.save(customer); } }
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="com.shma.hibernate.entity.n21.bath"> <class name="Customer" table="CUSTOMERS"> <id name="customerId" type="int"> <column name="CUSTOMER_ID" /> <generator class="native" /> </id> <property name="customerName" type="java.lang.String"> <column name="CUSTOMER_NAME" /> </property> <!-- 1对多映射关系那个属性集合 set:映射集合为set类型 table:set中集合类型的所对应的表名,需要与多对一中的表名一致 inverse:指定由哪一方来维护关联关系. 通常设置为 true, 以指定由多的一端来维护关联关系 cascade:级联操作,save-update级联保存并修改关联,delete:级联删除 order-by:排序,字段是数据库里面的字段类型 name:1的集合属性名称 --> <set name="orders" table="ORDERS" inverse="true" order-by="order_name desc"> <!-- 执行多的表中的外键列的名字 --> <key column="CUSTOMER_ID"></key> <!-- 指定映射类型 --> <one-to-many class="Order"/> </set> </class> </hibernate-mapping> <?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <!-- Generated 2015-7-18 15:21:35 by Hibernate Tools 3.4.0.CR1 --> <hibernate-mapping package="com.shma.hibernate.entity.n21.bath"> <class name="Order" table="ORDERS"> <id name="orderId" type="int"> <column name="ORDER_ID" /> <generator class="native" /> </id> <property name="orderName" type="java.lang.String"> <column name="ORDER_NAME" /> </property> <!-- 多对一映射关系 name:多这一端的一那一端的属性名称 class:一端的类型 column:一那一端对应在多端的外键名称 --> <many-to-one name="customer" class="Customer"> <column name="customer_id"></column> </many-to-one> </class> </hibernate-mapping>