单边一对多关系:电子邮件管理
单边一对多关系:指一方有集合属性,包含多个多方,而多的一方没有一方的引用。
比如:用户(一)与电子邮件(多)。一个用户可以有多个电子邮件记录。
目的:通过OneToMany映射,当保存用户信息到用户表tb_person时,也能自动保存该用户的邮件的信息到邮件表tb_email
当删除用户信息时,也自动从数据库删除该用户的邮件的信息
实现效果:
用户: 邮件表:
工程目录:(这里用java EE 6 Libraries,5会报错)
jar包
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:1521:orcl</property> <property name="connection.username">daym2</property> <property name="connection.password">daym2</property> <property name="connection.isolation">2</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