Hibernate实体关系映射(OneToMany单边)——完整实例

单边一对多关系:电子邮件管理

单边一对多关系:指一方有集合属性,包含多个多方,而多的一方没有一方的引用。

比如:用户(一)与电子邮件(多)。一个用户可以有多个电子邮件记录。

目的:通过OneToMany映射,当保存用户信息到用户表tb_person时,也能自动保存该用户的邮件的信息到邮件表tb_email

   当删除用户信息时,也自动从数据库删除该用户的邮件的信息

实现效果:

用户:Hibernate实体关系映射(OneToMany单边)——完整实例     邮件表:Hibernate实体关系映射(OneToMany单边)——完整实例

工程目录:(这里用java EE 6 Libraries,5会报错)

Hibernate实体关系映射(OneToMany单边)——完整实例

jar包

Hibernate实体关系映射(OneToMany单边)——完整实例

Hibernate的注解方式可以自动生成数据表,不需要自己建表,只需在xml配置文件设置hbm2ddl.auto为create

代码如下:

1、Person.java(用户实体类)

package com.hibernate.bean;

import java.util.ArrayList;
import java.util.List; import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinColumns;
import javax.persistence.OneToMany;
import javax.persistence.OrderBy;
import javax.persistence.Table; @Entity
@Table(name="tb_person")
public class Person { @Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Integer id; private String name;
//一对多配置,并配置列关系
@OneToMany(fetch=FetchType.LAZY,targetEntity=Email.class,
cascade={CascadeType.PERSIST,CascadeType.REMOVE,CascadeType.MERGE,CascadeType.REFRESH})
//指定连接表Email中的person_id外键列,参照当前实体对应表的主键列id
@JoinColumns(value = { @JoinColumn(name="person_id",referencedColumnName="id") })
//配置排序方法
@OrderBy(value="email desc")
private List<Email> emails=new ArrayList<Email>(); //用户方有邮件方的集合属性,包含多个多方,用泛型<Email>指定Email对象 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 List<Email> getEmails() {
return emails;
} public void setEmails(List<Email> emails) {
this.emails = emails;
} }

Person实体类中使用@OneToMany配置一对多关系。fetch配置加载方式(延迟加载FetchType.LAZY或即时加载FetchType.EAGER)。

targetEntity中配置集合属性中的类型, 由于emails属性类型为List<Email>,用泛型指定了集合内为Email对象,因此targetEntity可省略。

cascade配置级联方式,本例配置为PERSIST、REMOVE、MERGE、REFRESH,表示在保存、删除、修改、刷新Person类时,可以通过操作Person类来操作Email类。CascadeType.ALL表示所有类型

2、Email.java(邮件实体类)

package com.hibernate.bean;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table; @Entity
@Table(name="tb_email")
public class Email { @Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Integer id; private String email; public Integer getId() {
return id;
} public void setId(Integer id) {
this.id = id;
} public String getEmail() {
return email;
} public void setEmail(String email) {
this.email = email;
} }

3、HibernateSessionFactory.java

package com.hibernate.bean;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.cfg.Configuration; /**
* Configures and provides access to Hibernate sessions, tied to the current
* thread of execution. Follows the Thread Local Session pattern, see
* {@link http://hibernate.org/42.html }.
*/
public class HibernateSessionFactory { /**
* Location of hibernate.cfg.xml file. Location should be on the classpath
* as Hibernate uses #resourceAsStream style lookup for its configuration
* file. The default classpath location of the hibernate config file is in
* the default package. Use #setConfigFile() to update the location of the
* configuration file for the current session.
*/
private static String CONFIG_FILE_LOCATION = "/hibernate.cfg.xml";
private static final ThreadLocal<Session> threadLocal = new ThreadLocal<Session>();
private static Configuration configuration = new AnnotationConfiguration();
private static org.hibernate.SessionFactory sessionFactory;
private static String configFile = CONFIG_FILE_LOCATION; static {
try {
configuration.configure(configFile);
sessionFactory = configuration.buildSessionFactory();
} catch (Exception e) {
System.err.println("%%%% Error Creating SessionFactory %%%%");
e.printStackTrace();
}
} private HibernateSessionFactory() {
} /**
* Returns the ThreadLocal Session instance. Lazy initialize the
* <code>SessionFactory</code> if needed.
*
* @return Session
* @throws HibernateException
*/
public static Session getSession() throws HibernateException {
Session session = (Session) threadLocal.get(); if (session == null || !session.isOpen()) {
if (sessionFactory == null) {
rebuildSessionFactory();
}
session = (sessionFactory != null) ? sessionFactory.openSession()
: null;
threadLocal.set(session);
} return session;
} /**
* Rebuild hibernate session factory
*
*/
public static void rebuildSessionFactory() {
try {
configuration.configure(configFile);
sessionFactory = configuration.buildSessionFactory();
} catch (Exception e) {
System.err.println("%%%% Error Creating SessionFactory %%%%");
e.printStackTrace();
}
} /**
* Close the single hibernate session instance.
*
* @throws HibernateException
*/
public static void closeSession() throws HibernateException {
Session session = (Session) threadLocal.get();
threadLocal.set(null); if (session != null) {
session.close();
}
} /**
* return session factory
*
*/
public static org.hibernate.SessionFactory getSessionFactory() {
return sessionFactory;
} /**
* return session factory
*
* session factory will be rebuilded in the next call
*/
public static void setConfigFile(String configFile) {
HibernateSessionFactory.configFile = configFile;
sessionFactory = null;
} /**
* return hibernate configuration
*
*/
public static Configuration getConfiguration() {
return configuration;
} }

4、hibernate.cfg.xml(src目录下)

<?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="show_sql">true</property>
<property name="format_sql">true</property>
<property name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
<property name="connection.url">jdbc:oracle:thin:@192.168.1.2::orcl</property>
<property name="connection.username">daym2</property>
<property name="connection.password">daym2</property>
<property name="connection.isolation"></property>
<property name="hbm2ddl.auto">create</property>
<property name="javax.persistence.validation.mode">none</property> <!-- SQL方言,这边设定的是Oracle -->
<property name="dialect">org.hibernate.dialect.Oracle10gDialect</property> <property name="current_session_context">thread</property>
<mapping class="com.hibernate.bean.Cat" />
<mapping class="com.hibernate.bean.Person" />
<mapping class="com.hibernate.bean.Email" />
</session-factory>
</hibernate-configuration>

5、TestPersonEmail.java测试类

package com.hibernate.bean;

import java.util.List;

import org.hibernate.Session;
import org.hibernate.Transaction; public class TestPersonEmail { public static void main(String[] args) {
Person person=new Person();
person.setName("Jane"); Email email=new Email(); //实例化一个Email
email.setEmail("yahoo@yahoo.com.cn");//设置Email
person.getEmails().add(email); //添加到Person对象中 email=new Email(); //实例化另一个Email
email.setEmail("163@163.com");//设置Email
person.getEmails().add(email);//添加到Person对象中 Session session=HibernateSessionFactory.getSession();
//开启一个事务
session.beginTransaction();
session.persist(person);//保存person对象,会自动级联保存Email对象 List list=session.createQuery("select p from Person p left join fetch p.emails e where e.email like '%@yahoo.com.cn' ").list();
for(Person p: (List<Person>)list){
System.out.println("Person:"+p.getName());
for(Email e:p.getEmails()){
System.out.println("\tEmail:"+e.getEmail());
}
}
//session.delete(person);//删除person对象,会自动级联删除属于它的Email记录 session.getTransaction().commit();
session.close();
}
}

6、log4j.properties(src目录下)

log4j.rootLogger=INFO,stdout
log4j.category.org.hibernate.tool.hbn2ddl=DEBUG
log4j.category.org.hibernate.SQL=DEBUG
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%-d{yyyy-MM-dd HH\:mm\:ss,SSS} [%c]-[%p] %m%n
上一篇:展开被 SpringBoot 玩的日子 《 三 》 整合Redis


下一篇:Python Web开发之Flask