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>