【Java EE (Struts2 + Spring + Hibernate)开发】:Hibernate(一)基本用法
来源:互联网 发布:中南大学网络登录平台 编辑:程序博客网 时间:2024/05/10 07:21
【Java EE (Struts2 + Spring + Hibernate)开发】:Hibernate(一)基本用法
本文地址:http://blog.csdn.net/shanglianlm/article/details/49975515
1 ORM 和 Hibernate
1-1 对象/关系数据库映射(ORM)
1-2 基本映射方式
1-3 Hibernate 概述
2 Hibernate 入门
2-1 Hibernate 下载和安装
- 等录 http://www.hibernate.org/downloads 下载 Core 包。
- 解压缩,得到如下文件结构
把 hibernate3.jar 和 lib 目录下的所有 JAR 包添加到应用的类加载路径下。
2-2 Hibernate 的数据库操作
News.java
public class News{ //消息类的标识属性 private Integer id; //消息标题 private String title; //消息内容 private String content; //id属性的setter和getter方法 public void setId(Integer id) { this.id = id; } public Integer getId() { return this.id; } //title属性的setter和getter方法 public void setTitle(String title) { this.title = title; } public String getTitle() { return this.title; } //content属性的setter和getter方法 public void setContent(String content) { this.content = content; } public String getContent() { return this.content; }}
News.hbm.xml
<?xml version="1.0" encoding="gb2312"?><!-- 指定Hiberante3映射文件的DTD信息 --><!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"><!-- hibernate-mapping是映射文件的根元素 --><hibernate-mapping package="org.crazyit.app.domain"> <!-- 每个class元素对应一个持久化对象 --> <class name="News" table="news_table"> <!-- id元素定义持久化类的标识属性 --> <id name="id"> <!-- 指定主键生成策略 --> <generator class="identity"/> </id> <!-- property元素定义常规属性 --> <property name="title"/> <property name="content"/> </class></hibernate-mapping>
PO = POJO + 映射文件
hibernate.cfg.xml
<?xml version="1.0" encoding="GBK"?><!-- 指定Hibernate配置文件的DTD信息 --><!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"><!-- hibernate- configuration是连接配置文件的根元素 --><hibernate-configuration> <session-factory> <!-- 指定连接数据库所用的驱动 --> <property name="connection.driver_class">com.mysql.jdbc.Driver</property> <!-- 指定连接数据库的url,hibernate连接的数据库名 --> <property name="connection.url">jdbc:mysql://localhost/hibernate</property> <!-- 指定连接数据库的用户名 --> <property name="connection.username">root</property> <!-- 指定连接数据库的密码 --> <property name="connection.password">32147</property> <!-- 指定连接池里最大连接数 --> <property name="hibernate.c3p0.max_size">20</property> <!-- 指定连接池里最小连接数 --> <property name="hibernate.c3p0.min_size">1</property> <!-- 指定连接池里连接的超时时长 --> <property name="hibernate.c3p0.timeout">5000</property> <!-- 指定连接池里最大缓存多少个Statement对象 --> <property name="hibernate.c3p0.max_statements">100</property> <property name="hibernate.c3p0.idle_test_period">3000</property> <property name="hibernate.c3p0.acquire_increment">2</property> <property name="hibernate.c3p0.validate">true</property> <!-- 指定数据库方言 --> <property name="dialect">org.hibernate.dialect.MySQLInnoDBDialect</property> <!-- 根据需要自动创建数据表 --> <property name="hbm2ddl.auto">update</property> <!-- 显示Hibernate持久化操作所生成的SQL --> <property name="show_sql">true</property> <!-- 将SQL脚本进行格式化后再输出 --> <property name="hibernate.format_sql">true</property> <!-- 罗列所有的映射文件 --> <mapping resource="org/crazyit/app/domain/News.hbm.xml"/> </session-factory></hibernate-configuration>
NewsManager.java
public class NewsManager{ public static void main(String[] args) throws Exception { //实例化Configuration, Configuration conf = new Configuration() //下面方法默认加载hibernate.cfg.xml文件 .configure(); //以Configuration创建SessionFactory SessionFactory sf = conf.buildSessionFactory(); //创建Session Session sess = sf.openSession(); //开始事务 Transaction tx = sess.beginTransaction(); //创建消息实例 News n = new News(); //设置消息标题和消息内容 n.setTitle("疯狂Java联盟成立了"); n.setContent("疯狂Java联盟成立了," + "网站地址http://www.crazyit.org"); //保存消息 sess.save(n); //提交事务 tx.commit(); //关闭Session sess.close(); sf.close(); }}
使用 Hibernata 进行持久化操作步骤:
PO 有三种状态:
3 Hibernate 的体系结构
4 深入 Hibernate 的配置文件
4-1 创建 Configuration 对象
4-1-1 使用 hibernate.properties 作为配置文件(适合初学者)
// 实例化 ConfigurationConfiguration cfg = new Configuration() //多次调用 addResource 方法,添加映射文件 .addResource("Item.hbm.xml") .addResource("Bid.hbm.xml");
也可以通过向 Configuration 对象添加持久化类,让 Hibernate 自己搜索映射文件:
// 实例化 ConfigurationConfiguration cfg = new Configuration() //多次调用 addClass 方法,直接添加持久化类 .addClass("lee.Item.class") .addClass("lee.Bid.class");
4-1-2 使用 hibernate.cfg.xml 作为配置文件
// 实例化 ConfigurationConfiguration cfg = new Configuration() //configure()方法将会负责加载 hibernate.cfg.xml 文件 .configure();
4-1-3 不使用配置文件创建 Configuration 实例(极度烦琐)
Configuration 对象提供了如下三个方法:
利用上面三个方法,可以无须任何配置文件支持,直接通过编程方式创建 Configuration 实例。
NewsManager.java
public class NewsManager{ public static void main(String[] args) throws Exception { //实例化Configuration,不加载任何配置文件 Configuration conf = new Configuration() //通过addClass方法添加持久化类 .addClass(org.crazyit.app.domain.News.class) //通过setProperty设置Hibernate的连接属性。 .setProperty("hibernate.connection.driver_class" , "com.mysql.jdbc.Driver") .setProperty("hibernate.connection.url" , "jdbc:mysql://localhost/hibernate") .setProperty("hibernate.connection.username" , "root") .setProperty("hibernate.connection.password" , "32147") .setProperty("hibernate.c3p0.max_size" , "20") .setProperty("hibernate.c3p0.min_size" , "1") .setProperty("hibernate.c3p0.timeout" , "5000") .setProperty("hibernate.c3p0.max_statements" , "100") .setProperty("hibernate.c3p0.idle_test_period" , "3000") .setProperty("hibernate.c3p0.acquire_increment" , "2") .setProperty("hibernate.c3p0.validate" , "true") .setProperty("hibernate.dialect" , "org.hibernate.dialect.MySQLInnoDBDialect") .setProperty("hibernate.hbm2ddl.auto" , "create"); //以Configuration创建SessionFactory SessionFactory sf = conf.buildSessionFactory(); //实例化Session Session sess = sf.openSession(); //开始事务 Transaction tx = sess.beginTransaction(); //创建消息实例 News n = new News(); //设置消息标题和消息内容 n.setTitle("疯狂Java联盟成立了"); n.setContent("疯狂Java联盟成立了," + "网站地址http://www.crazyit.org"); //保存消息 sess.save(n); //提交事务 tx.commit(); //关闭Session sess.close(); }}
4-2 hibernate.properties 文件与 hibernate.cfg.xml 文件
hibernate.properties
//指定数据库的方言hibernate.dialect org.hibernate.dialect.MySQLDialect
hibernate.cfg.xml
<property name="dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>
格式不同,但其实质完全一样。
4-3 JDBC 连接属性
下面是配置 C3P0 连接池的配置片段
<!-- 指定连接数据库所用的驱动 --> <property name="connection.driver_class">com.mysql.jdbc.Driver</property> <!-- 指定连接数据库的url,hibernate连接的数据库名 --> <property name="connection.url">jdbc:mysql://localhost/hibernate</property> <!-- 指定连接数据库的用户名 --> <property name="connection.username">root</property> <!-- 指定连接数据库的密码 --> <property name="connection.password">32147</property> <!-- 指定连接池里最大连接数 --> <property name="hibernate.c3p0.max_size">20</property> <!-- 指定连接池里最小连接数 --> <property name="hibernate.c3p0.min_size">1</property> <!-- 指定连接池里连接的超时时长 --> <property name="hibernate.c3p0.timeout">1800</property> <!-- 指定连接池里最大缓存多少个Statement对象 --> <property name="hibernate.c3p0.max_statements">50</property>
4-4 数据库方言
4-5 JNDI 连接源的连接属性
下面是配置 hibernate 连接 Tomcat 中数据源的配置片段。
<!-- 配置 JNDI 数据源的 JNDI 名 --><property name="connection.datasource">java:comp/env/jdbc/dstest</property><!-- 配置连接数据库的方言 --><property name="dialect">org.hibernate.dialect.MySQLDialect</property>
4-6 Hibernate 事务属性
4-7 二级缓存相关属性
4-8 外连接抓取属性
4-9 其他常用的配置属性
5 深入理解持久化对象
5-1 持久化类的要求
5-2 持久化对象的状态
5-3 改变持久化对象状态的方法
//创建消息实例News n = new News();//设置消息标题和消息内容n.setTitle("疯狂java联盟");n.setContent("疯狂java联盟成立了," + "http://www.aaa.com");//保存消息sess.save(n);
News n = sess.load(News.class, new Integer(pk));
News n = firstSess.load(News.class, new Integer(pk));// 第一个 Session 已经关闭了firstSess.close();// 修改托管状态下的持久化对象n.setTitle("");// 打开第二个 SessionSession secondSess = ...// 保存托管对象所做的修改secondSess.update(n);
还可以通过 Session 的 delete 方法来删除持久化实例,一旦删除了持久化实例,该持久化实例对应的数据记录也将被删除。
News n = Session.load(News.class, new Integer(pk));Session.delete(n);
6 深入 Hibernate 的映射文件
6-1 映射文件结构
<hibernate-mapping> <class /> <class /> ...</hibernate-mapping>
6-2 映射主键
示例
<class name="News" table="news_table"> <!-- 定义标识属性 --> <id name="id" column="news_id"> <!-- 定义主键生成器 --> <generator class="identity" /> </id> <!-- 用于定义普通属性 --> <property ... /> <property ... /></class>
6-3 映射普通属性
示例:formula
News.java
public class News{ //消息类的标识属性 private Integer id; //消息标题 private String title; //消息内容 private String content; //消息全部内容,由系统根据公式生成 private String fullContent; ...}
News.hbm.xml
<!-- hibernate-mapping是映射文件的根元素 --><hibernate-mapping package="org.crazyit.app.domain"> <!-- 每个class元素对应一个持久化对象 --> <class name="News" table="news_table"> <!-- id元素定义持久化类的标识属性 --> <id name="id"> <generator class="identity"/> </id> <!-- property元素定义常规属性 --> <property name="title" not-null="true"/> <property name="content"/> <!-- 通过formula指定该属性值没有对应的实际数据列,该属性值将由系统根据表达式来生成--> <property name="fullContent" formula="(select concat(nt.title,nt.content) from news_table nt where nt.id= id)"/> </class></hibernate-mapping>
NewsManager.java
public class NewsManager{ public static void main(String[] args) throws Exception { //实例化Configuration,这行代码默认加载hibernate.cfg.xml文件 Configuration conf = new Configuration().configure(); //以Configuration创建SessionFactory SessionFactory sf = conf.buildSessionFactory(); //实例化Session Session sess = sf.openSession(); //开始事务 Transaction tx = sess.beginTransaction();// //创建消息实例// News n = new News();// //设置消息标题和消息内容// n.setTitle("疯狂Java联盟成立了");// n.setContent("疯狂Java联盟成立了,"// + "网站地址http://www.crazyit.org");// //保存消息// sess.save(n); News n2 = (News)sess.get(News.class , 1); //输出fullContent属性值 System.out.println(n2.getFullContent()); //提交事务 tx.commit(); //关闭Session sess.close(); }}
示例: fullContent 属性值由数据库系统生成。
News.hbm.xml
<!-- hibernate-mapping是映射文件的根元素 --><hibernate-mapping package="org.crazyit.app.domain"> <!-- 每个class元素对应一个持久化对象 --> <class name="News" table="news_table"> <!-- id元素定义持久化类的标识属性 --> <id name="id"> <generator class="identity"/> </id> <!-- property元素定义常规属性 --> <property name="title" not-null="true"/> <property name="content"/> <!-- 为该property指定generated属性为always 该属性的值由数据库生成, 而Hibernate会在每次插入、更新之后执行 select语句来查询到该属性的值 --> <property name="fullContent" column="full_content" type="string" generated="insert"/> </class></hibernate-mapping>
sql.sql
drop database hibernate;create database hibernate;use hibernate;create table news_table(id int auto_increment primary key,title varchar(255) not null,content varchar(255),full_content varchar(255));DELIMITER |create trigger t_full_content_gen BEFORE INSERT ON news_table FOR EACH ROW BEGIN set new.full_content=concat(new.title,new.content); END;|DELIMITER ;
NewsManager.java
public static void main(String[] args) throws Exception { //实例化Configuration,这行代码默认加载hibernate.cfg.xml文件 Configuration conf = new Configuration().configure(); //以Configuration创建SessionFactory SessionFactory sf = conf.buildSessionFactory(); //实例化Session Session sess = sf.openSession(); //开始事务 Transaction tx = sess.beginTransaction(); //创建消息实例 News n = new News(); //设置消息标题和消息内容 n.setTitle("疯狂Java联盟成立了"); n.setContent("疯狂Java联盟成立了," + "网站地址http://www.crazyit.org"); //保存消息 sess.save(n); //输出fullContent属性,将看到title和content连缀的字符串 System.out.println(n.getFullContent()); //提交事务 tx.commit(); //关闭Session sess.close(); }
6-4 映射集合属性
6-4-1 List 集合属性
Person.java
public class Person{ //标识属性 private Integer id; //普通属性name private String name; //普通属性age private int age; //集合属性,保留该对象关联的学校 private List<String> schools = new ArrayList<String>(); ... //schools属性的setter和getter方法 public void setSchools(List<String> schools) { this.schools = schools; } public List<String> getSchools() { return this.schools; }}
Person.hbm.xml
<hibernate-mapping package="org.crazyit.app.domain"> <class name="Person" table="person_inf"> <!-- 映射标识属性 --> <id name="id" column="person_id"> <!-- 指定主键生成器策略 --> <generator class="identity"/> </id> <!-- 映射普通属性 --> <property name="name" type="string"/> <property name="age" type="int"/> <!-- 映射List集合属性 --> <list name="schools" table="school"> <!-- 映射集合属性数据表的外键列 --> <key column="person_id" not-null="true"/> <!-- 映射集合属性数据表的集合索引列 --> <list-index column="list_order"/> <!-- 映射保存集合元素的数据列 --> <element type="string" column="school_name"/> </list> </class></hibernate-mapping>
PersonManager.java
public class PersonManager{ public static void main(String[] args) { PersonManager mgr = new PersonManager(); mgr.createAndStorePerson(); HibernateUtil.sessionFactory.close(); } //创建并保存Person对象 private void createAndStorePerson() { //打开线程安全的session对象 Session session = HibernateUtil.currentSession(); //打开事务 Transaction tx = session.beginTransaction(); //创建Person对象 Person yeeku = new Person(); //为Person对象设置属性 yeeku.setAge(29); yeeku.setName("crazyit.org"); //创建List集合 List<String> schools = new ArrayList<String>(); schools.add("小学"); schools.add("中学"); //设置List集合属性 yeeku.setSchools(schools); session.save(yeeku); tx.commit(); HibernateUtil.closeSession(); }}
HibernateUtil.java
package lee;import org.hibernate.*;import org.hibernate.cfg.*;public class HibernateUtil{ public static final SessionFactory sessionFactory; static { try { //采用默认的hibernate.cfg.xml来启动一个Configuration的实例 Configuration configuration = new Configuration() .configure(); //由Configuration的实例来创建一个SessionFactory实例 sessionFactory = configuration.buildSessionFactory(); } catch (Throwable ex) { System.err.println("Initial SessionFactory creation failed." + ex); throw new ExceptionInInitializerError(ex); } } //ThreadLocal可以隔离多个线程的数据共享,因此不再需要对线程同步 public static final ThreadLocal<Session> session = new ThreadLocal<Session>(); public static Session currentSession() throws HibernateException { Session s = session.get(); //如果该线程还没有Session,则创建一个新的Session if (s == null) { s = sessionFactory.openSession(); //将获得的Session变量存储在ThreadLocal变量session里 session.set(s); } return s; } public static void closeSession() throws HibernateException { Session s = session.get(); if (s != null) s.close(); session.set(null); }}
6-4-2 数组属性
Person.java
public class Person{ ... //数组属性,保留该对象关联的学校 private String[] schools; ... //schools属性的setter和getter方法 public void setSchools(String[] schools) { this.schools = schools; } public String[] getSchools() { return this.schools; }}
Person.hbm.xml
<hibernate-mapping package="org.crazyit.app.domain"> <class name="Person" table="person_inf"> ... <!-- 映射数组属性 --> <array name="schools" table="school"> <!-- 映射数组属性数据表的外键列 --> <key column="person_id" not-null="true"/> <!-- 映射数组属性数据表的数组索引列 --> <list-index column="list_order"/> <!-- 映射保存数组元素的数据列 --> <element type="string" column="school_name"/> </array> </class></hibernate-mapping>
6-4-3 Set 集合属性
Person.java
public class Person{ ... //集合属性,保留该对象关联的学校 private Set<String> schools = new HashSet<String>(); ... //schools属性的setter和getter方法 public void setSchools(Set<String> schools) { this.schools = schools; } public Set<String> getSchools() { return this.schools; }}
Person.hbm.xml
<hibernate-mapping package="org.crazyit.app.domain"> <class name="Person" table="person_inf"> ... <!-- 映射Set集合属性 --> <set name="schools" table="school"> <!-- 映射集合属性数据表的外键列 --> <key column="person_id" not-null="true"/> <!-- 映射保存集合元素的数据列,增加非空约束 --> <element type="string" column="school_name" not-null="true"/> </set> </class></hibernate-mapping>
6-4-4 bag 元素映射
Person.java
public class Person{ ... //集合属性,保留该对象关联的学校 private Collection<String> schools = new ArrayList<String>(); ... //schools属性的setter和getter方法 public void setSchools(Collection<String> schools) { this.schools = schools; } public Collection<String> getSchools() { return this.schools; }}
Person.hbm.xml
<hibernate-mapping package="org.crazyit.app.domain"> <class name="Person" table="person_inf"> ... <!-- 使用bag元素映射集合属性 --> <bag name="schools" table="school"> <!-- 映射集合属性数据表的外键列 --> <key column="person_id" not-null="true"/> <!-- 映射保存集合元素的数据列 --> <element type="string" column="school_name" not-null="true"/> </bag> </class></hibernate-mapping>
6-4-5 Map 集合属性
Person.java
public class Person{ ... //集合属性,保留该对象关联的考试成绩 private Map<String ,Float> scores = new HashMap<String ,Float>(); ... //scores属性的setter和getter方法 public void setScores(Map<String ,Float> scores) { this.scores = scores; } public Map<String ,Float> getScores() { return this.scores; }}
Person.hbm.xml
<hibernate-mapping package="org.crazyit.app.domain"> <class name="Person" table="person_inf"> ... <!-- 映射Map集合属性 --> <map name="scores" table="score"> <!-- 映射集合属性数据表的外键列 --> <key column="person_id" not-null="true"/> <!-- 映射集合属性数据表的Map key列 --> <map-key column="subject" type="string"/> <!-- 映射保存集合元素的数据列 --> <element column="grade" type="float"/> </map> </class></hibernate-mapping>
6-5 集合属性的性能分析
6-6 有序集合映射
Person.java
public class Person{ //标识属性 private Integer id; //普通属性name private String name; //普通属性age private int age; //有序集合属性,保留该对象参与的培训 private SortedSet<String> trainings = new TreeSet<String>(); ... //trainings属性的setter和getter方法 public void setTrainings(SortedSet<String> trainings) { this.trainings = trainings; } public SortedSet<String> getTrainings() { return this.trainings; }}
Person.hbm.xml
<hibernate-mapping package="org.crazyit.app.domain"> <class name="Person" table="person_inf"> <!-- 映射标识属性 --> <id name="id" column="person_id"> <!-- 指定主键生成器策略 --> <generator class="identity"/> </id> <!-- 映射普通属性 --> <property name="name" type="string"/> <property name="age" type="int"/> <!-- 映射SortedSet集合属性,使用自然排序 增加sort="natural"定义--> <set name="trainings" table="training" sort="natural"> <!-- 映射集合属性数据表的外键列 --> <key column="person_id" not-null="true"/> <!-- 映射保存集合元素的数据列,增加非空约束 --> <element type="string" column="training_name" not-null="true"/> </set> </class></hibernate-mapping>
PersonManager.java
public class PersonManager{ public static void main(String[] args) { PersonManager mgr = new PersonManager(); mgr.createAndStorePerson(); HibernateUtil.sessionFactory.close(); } private void createAndStorePerson() { Session session = HibernateUtil.currentSession(); Transaction tx = session.beginTransaction(); //创建Person对象 Person wawa = new Person(); //为Person对象设置属性 wawa.setAge(21); wawa.setName("crazyit.org"); //创建Set集合 SortedSet<String> s = new TreeSet<String>(); s.add("Wild Java Camp"); s.add("Sun SCJP"); //设置Set集合属性 wawa.setTrainings(s); session.save(wawa); tx.commit(); HibernateUtil.closeSession(); }}
Person p = (Person)session.get(Person.class , 1);p.getTrainings().add("CCNP");
<!-- 映射Set集合属性,指定在内存中排序 --><set name="trainings" table="training" order-by="training desc"> <!-- 映射集合属性数据表的外键列 --> <key column="person_id" not-null="true"/> <!-- 映射保存集合元素的数据列,增加非空约束 --> <element type="string" column="training" not-null="true"/></set>
6-7 映射数据库对象
News.hbm.xml
<!-- hibernate-mapping是映射文件的根元素 --><hibernate-mapping> <!-- 使用data-object元素定义数据库对象 --> <database-object> <!-- 定义创建数据库对象的语句 --> <create>create table test(t_name varchar(255));</create> <!-- 让drop元素为空,不删除任何对象 --> <drop></drop> <!-- 指定仅对MySQL数据库有效 --> <dialect-scope name="org.hibernate.dialect.MySQLDialect"/> <dialect-scope name="org.hibernate.dialect.MySQLInnoDBDialect"/> </database-object> </hibernate-mapping>
NewsManager.java
//实例化Configuration,这行代码默认加载hibernate.cfg.xml文件 Configuration conf = new Configuration().configure(); //以Configuration创建SessionFactory SessionFactory sf = conf.buildSessionFactory();
7 映射组件属性
Person.java
public class Person{ //标识属性 private Integer id; //普通属性age private int age; //组件属性name private Name name; ... //name属性的setter和getter方法 public void setName(Name name) { this.name = name; } public Name getName() { return this.name; }}
Name.java
public class Name{ //定义first属性 private String first; //定义last属性 private String last; //引用拥有该Name的Person对象 private Person owner; //无参数的构造器 public Name() { } //初始化first、last属性的构造器 public Name(String first , String last) { this.first = first; this.last = last; } ... //owner属性的setter和getter方法 public void setOwner(Person owner) { this.owner = owner; } public Person getOwner() { return this.owner; }}
Person.hbm.xml
<hibernate-mapping package="org.crazyit.app.domain"> <class name="Person" table="person_inf"> <!-- 映射标识属性 --> <id name="id" column="person_id"> <!-- 指定主键生成器策略 --> <generator class="identity"/> </id> <!-- 映射普通属性 --> <property name="age" type="int"/> <!-- 映射组件属性name,组件属性的类型为Name --> <component name="name" class="Name" unique="true"> <!-- 指定owner属性代表容器实体 --> <parent name="owner"/> <!-- 映射组件属性的first属性 --> <property name="first"/> <!-- 映射组件属性的last属性 --> <property name="last"/> </component> </class></hibernate-mapping>
PersonManager.java
public class PersonManager{ public static void main(String[] args) { PersonManager mgr = new PersonManager(); mgr.createAndStorePerson(); HibernateUtil.sessionFactory.close(); } private void createAndStorePerson() { Session session = HibernateUtil.currentSession(); Transaction tx = session.beginTransaction(); //创建Person对象 Person yeeku = new Person(); //为Person对象设置属性 yeeku.setAge(29); Name n = new Name("crazyit.org" , "疯狂Java联盟"); yeeku.setName(n); session.save(yeeku); tx.commit(); HibernateUtil.closeSession(); }}
结果
7-1 组合属性为集合
Name.java
public class Name{ ... //引用拥有该Name的Person对象 private Person owner; private Map<String ,Integer> power = new HashMap<String ,Integer>(); ... //power属性的setter和getter方法 public void setPower(Map<String ,Integer> power) { this.power = power; } public Map<String ,Integer> getPower() { return this.power; }}
Person.hbm.xml
<hibernate-mapping package="org.crazyit.app.domain"> <class name="Person" table="person_inf"> <!-- 映射标识属性 --> <id name="id" column="person_id"> <!-- 指定主键生成器策略 --> <generator class="identity"/> </id> <!-- 映射普通属性 --> <property name="age" type="int"/> <!-- 映射组件属性name,组件属性的类型为Name --> <component name="name" class="Name" unique="true"> <!-- 指定owner属性代表容器实体 --> <parent name="owner"/> <!-- 映射组件属性的first属性 --> <property name="first"/> <!-- 映射组件属性的last属性 --> <property name="last"/> <!-- 映射组件属性里的Map集合属性 --> <map name="power" table="name_power"> <!-- 映射集合属性数据表的外键列 --> <key column="person_name_id" not-null="true"/> <!-- 映射集合属性数据表的Map key列 --> <map-key column="name_aspect" type="string"/> <!-- 映射保存集合元素的数据列 --> <element column="name_power" type="int"/> </map> </component> </class></hibernate-mapping>
7-2 集合属性的元素为组件
Person.java
public class Person{ ... //组件属性name private Map<String , Name> nicks = new HashMap<String , Name>(); ... //nicks属性的setter和getter方法 public void setNicks(Map<String , Name> nicks) { this.nicks = nicks; } public Map<String , Name> getNicks() { return this.nicks; }}
Person.hbm.xml
<hibernate-mapping package="org.crazyit.app.domain"> <class name="Person" table="person_inf"> <!-- 映射标识属性 --> <id name="id" column="person_id"> <!-- 指定主键生成器策略 --> <generator class="identity"/> </id> <!-- 映射普通属性 --> <property name="age" type="int"/> <!-- 映射nicks集合属性,集合属性对应的数据表为nick_inf --> <map name="nicks" table="nick_inf"> <!-- 映射集合属性数据表的外键列 --> <key column="person_id" not-null="true"/> <!-- 映射集合属性数据表的Map key列 --> <map-key column="phase" type="string"/> <!-- 映射保存集合里的组件元素 --> <composite-element class="Name"> <!-- 指定owner属性代表容器实体 --> <parent name="owner"/> <!-- 映射组件属性的first属性 --> <property name="first"/> <!-- 映射组件属性的last属性 --> <property name="last"/> </composite-element> </map> </class></hibernate-mapping>
7-3 组件作为 Map 的索引
Person.java
public class Person{ ... //集合属性nickPower private Map<Name , Integer> nickPower = new HashMap<Name , Integer>(); ... //nickPower属性的setter和getter方法 public void setNickPower(Map<Name , Integer> nickPower) { this.nickPower = nickPower; } public Map<Name , Integer> getNickPower() { return this.nickPower; }}
Name.java
public class Name{ //定义first属性 private String first; //定义last属性 private String last; //引用拥有该Name的Person对象 private Person owner; //无参数的构造器 public Name() { } //初始化全部属性的构造器 public Name(String first , String last) { this.first = first; this.last = last; } ... //重写equals方法,根据first、last进行判断 public boolean equals(Object obj) { if (this == obj) { return true; } if (obj != null && obj.getClass() == Name.class) { Name target = (Name)obj; if (target.getFirst().equals(getFirst()) && target.getLast().equals(getLast())) { return true; } } return false; } //重写hashCode方法,根据first、last计算hashCode值 public int hashCode() { return getFirst().hashCode() * 13 + getLast().hashCode(); }}
Person.hbm.xml
<hibernate-mapping package="org.crazyit.app.domain"> <class name="Person" table="person_inf"> <!-- 映射标识属性 --> <id name="id" column="person_id"> <!-- 指定主键生成器策略 --> <generator class="identity"/> </id> <!-- 映射普通属性 --> <property name="age" type="int"/> <!-- 映射nickPower集合属性,集合属性对应的数据表为nick_power --> <map name="nickPower" table="nick_power"> <!-- 映射集合属性数据表的外键列 --> <key column="person_id" not-null="true"/> <!-- 映射集合属性数据表的Map key列 , 因为Map key的数据类型是复合类型,所以使用如下元素--> <composite-map-key class="Name"> <!-- 映射复合组件的属性 --> <key-property name="first" type="string"/> <key-property name="last" type="string"/> </composite-map-key> <!-- 映射集合元素的数据列 --> <element column="nick_power" type="int"/> </map> </class></hibernate-mapping>
7-4 组件作为集合主键
Person.java
public class Person{ //以Name组件作为标识属性 private Name name; //普通属性age private int age; //name属性的setter和getter方法 public void setName(Name name) { this.name = name; } public Name getName() { return this.name; } ...}
Name.java
public class Name implements java.io.Serializable{ //定义first属性 private String first; //定义last属性 private String last; //无参数的构造器 public Name() { } //初始化全部属性的构造器 public Name(String first , String last) { this.first = first; this.last = last; } ... //重写equals方法,根据first、last进行判断 public boolean equals(Object obj) { if (this == obj) { return true; } if (obj != null && obj.getClass() == Name.class) { Name target = (Name)obj; if (target.getFirst().equals(getFirst()) && target.getLast().equals(getLast())) { return true; } } return false; } //重写hashCode方法,根据first、last计算hashCode值 public int hashCode() { return getFirst().hashCode() * 7 + getLast().hashCode(); }}
Person.hbm.xml
<hibernate-mapping package="org.crazyit.app.domain"> <class name="Person" table="person_inf"> <!-- 映射组件类型的标识属性 --> <composite-id name="name" class="Name"> <!-- 映射组件主键里的各属性 --> <key-property name="first" type="string"/> <key-property name="last" type="string"/> </composite-id> <!-- 映射普通属性 --> <property name="age" type="int"/> </class></hibernate-mapping>
PersonManager.java
public class PersonManager{ public static void main(String[] args) { PersonManager mgr = new PersonManager(); mgr.createAndStorePerson(); HibernateUtil.sessionFactory.close(); } private void createAndStorePerson() { Session session = HibernateUtil.currentSession(); Transaction tx = session.beginTransaction(); //创建Person对象 Person yeeku = new Person(); //为Person对象设置属性 yeeku.setAge(29); //创建一个Name对象作为Person对象的标识属性值 Name n = new Name("crazyit.org" , "疯狂Java联盟"); yeeku.setName(n); session.save(yeeku); tx.commit(); HibernateUtil.closeSession(); }}
7-5 多列作为联合主键
Person.java
public class Person implements java.io.Serializable{ //定义first属性,作为标识属性的成员 private String first; //定义last属性,作为标识属性的成员 private String last; //普通属性age private int age; ... //重写equals方法,根据first、last进行判断 public boolean equals(Object obj) { if (this == obj) { return true; } if (obj != null && obj.getClass() == Person.class) { Person target = (Person)obj; if (target.getFirst().equals(getFirst()) && target.getLast().equals(getLast())) { return true; } } return false; } //重写hashCode方法,根据first、last计算hashCode值 public int hashCode() { return getFirst().hashCode() * 13 + getLast().hashCode(); }}
Person.hbm.xml
<hibernate-mapping package="org.crazyit.app.domain"> <class name="Person" table="person_inf"> <!-- 直接使用composite-id映射多列联合主键 --> <composite-id> <!-- 映射组件主键里的各属性 --> <key-property name="first" type="string"/> <key-property name="last" type="string"/> </composite-id> <!-- 映射普通属性 --> <property name="age" type="int"/> </class></hibernate-mapping>
8 使用 JPA Annotation 标注实体
8-1 增加 JPA Annotation 支持
当采用 来管理实体类之后,可以得到如下公式:
PO = POJO + @Annotation
将 hibernate 发行包 lib 目录下 jpa 子目录下的 JAR 包添加到了系统的类加载路径中。
示例
Person.java
@Entity@Table(name="person_table")public class Person{ /* 指定使用复合主键类是Name */ @EmbeddedId @AttributeOverrides({ @AttributeOverride(name="first" , column=@Column(name="person_first")), @AttributeOverride(name="last" , column=@Column(name="person_last" , length=20)) }) private Name name; //普通属性 @Column(name="person_email") private String email; @Embedded @AttributeOverrides({ @AttributeOverride(name="name" , column=@Column(name="cat_name" , length=35)), @AttributeOverride(name="color" , column=@Column(name="cat_color")) }) //组件属性,代表此人拥有的宠物 private Cat pet; ...}
@Entity 标注该类是一个持久化类
@EmbeddedId 标注复合类型的标识属性
@Embedded 标注一个组件属性
Name.java
//修饰组件属性类@Embeddablepublic class Name implements java.io.Serializable{ private String first; private String last; //无参数的构造器 public Name() { } //初始化全部属性的构造器 public Name(String first , String last) { this.first = first; this.last = last; } ... //提供重写的equals方法 public boolean equals(Object obj) { if (this == obj) { return true; } if (obj.getClass() == Name.class) { Name target = (Name)obj; if (target.getFirst().equals(first) && target.getLast().equals(last)) { return true; } } return false; } //提供重写的hashCode方法 public int hashCode() { return first.hashCode() + last.hashCode() * 17; }}
Cat.java
//修饰组件属性类@Embeddablepublic class Cat{ private String name; private String color; //无参数的构造器 public Cat() { } //初始化全部属性的构造器 public Cat(String name , String color) { this.name = name; this.color = color; } ...}
hibernate.cfg.xml
<hibernate-configuration> <session-factory> ... <!-- 罗列所有的持久化类 --> <mapping class="org.crazyit.app.domain.Person"/> </session-factory></hibernate-configuration>
8-2 JPA Annotation? 还是 XML 映射文件
- 【Java EE (Struts2 + Spring + Hibernate)开发】:Hibernate(一)基本用法
- 【Java EE (Struts2 + Spring + Hibernate)开发】: Struts2(一)基本用法(待续)
- 【Java EE (Struts2 + Spring + Hibernate)开发】系列之 Spring(一)基本用法
- 【Java EE (Struts2 + Spring + Hibernate)开发】: Struts2(一)之 【Struts2标签库】
- 【Java EE (Struts2 + Spring + Hibernate)开发】:Struts2(二)之【类型转换】
- 【Java EE (Struts2 + Spring + Hibernate)开发】:Struts2(二)之【输入校验】
- 【Java EE (Struts2 + Spring + Hibernate)开发】:Struts2(二)之【控制文件上传和下载】
- 【Java EE (Struts2 + Spring + Hibernate)开发】:Struts2(二)之【拦截器机制】
- 【Java EE (Struts2 + Spring + Hibernate)开发】:Struts2(二)之【Ajax 支持】
- 【Java EE (Struts2 + Spring + Hibernate)开发】:Spring(二)深入使用
- 【Java EE (Struts2 + Spring + Hibernate)开发】:开发环境配置(待续)
- 【Java EE (Struts2 + Spring + Hibernate)开发】:Web 之 【JSP基础知识】
- 【Java EE (Struts2 + Spring + Hibernate)开发】 :Hibernate(二)之【关联映射|继承映射|批量处理】
- 【Java EE (Struts2 + Spring + Hibernate)开发】 :Hibernate(二)之【HQL查询|条件查询|SQL查询】
- 【Java EE (Struts2 + Spring + Hibernate)开发】 :Hibernate(二)之【数据过滤|事务控制|二级缓存和查询缓存|事件机制】
- 《轻量级Java EE 企业应用实战(第4版)——Struts2+Spring 4+Hibernate》 李刚 第三章 Struts2 开发流程 错误解决
- Java EE实用开发指南:基于Weblogic+EJB3+Struts2+Hibernate+Spring 高洪岩 配套源码下载地址
- (Spring+IBatis+Struts1+Struts2+Hibernate+Java EE+Oracle)
- jquery基础语法
- 【Java EE (Struts2 + Spring + Hibernate)开发】:Struts2(二)之【类型转换】
- socket通信实例(简单的聊天室)
- 【Java EE (Struts2 + Spring + Hibernate)开发】 :Hibernate(二)之【关联映射|继承映射|批量处理】
- Java 调用 MySQL 存储过程并获得返回值
- 【Java EE (Struts2 + Spring + Hibernate)开发】:Hibernate(一)基本用法
- Docker在测试领域的应用
- AltiumDesigner05——常见芯片的封装类型
- 【Java EE (Struts2 + Spring + Hibernate)开发】系列之 Spring(一)基本用法
- 【Java EE (Struts2 + Spring + Hibernate)开发】:Spring(二)深入使用
- C#之抽象类、虚方法、重写、接口、密封类
- 显示当前日期和时间
- t-sql out output ref
- 显示程序运行时间