Chinaunix首页 | 论坛 | 博客
  • 博客访问: 442017
  • 博文数量: 56
  • 博客积分: 2705
  • 博客等级: 少校
  • 技术积分: 740
  • 用 户 组: 普通用户
  • 注册时间: 2008-08-21 13:52
文章分类

全部博文(56)

文章存档

2016年(1)

2014年(1)

2013年(5)

2012年(4)

2011年(8)

2010年(10)

2009年(15)

2008年(12)

分类: Java

2014-10-10 23:15:21

建表语句:
复制代码
DROP TABLE IF EXISTS `t_company`; CREATE TABLE `t_company` (
  `companyId` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `companyName` varchar(30) NOT NULL, PRIMARY KEY (`companyId`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=gb2312; INSERT INTO `t_company` VALUES ('1', 'Sun'); INSERT INTO `t_company` VALUES ('2', 'Apache');
复制代码
复制代码
DROP TABLE IF EXISTS `t_employee`; CREATE TABLE `t_employee` (
  `employeeId` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `employeeName` varchar(15) NOT NULL,
  `cid` int(10) unsigned NOT NULL, PRIMARY KEY (`employeeId`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=gb2312; INSERT INTO `t_employee` VALUES ('1', 'Tom', '1'); INSERT INTO `t_employee` VALUES ('2', 'Summ', '1'); INSERT INTO `t_employee` VALUES ('3', 'Cat', '2'); INSERT INTO `t_employee` VALUES ('4', 'Vinylon', '1'); INSERT INTO `t_employee` VALUES ('5', 'Dog', '2');
复制代码

Employee.java

package com.fancy.po;


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.ManyToOne;
import javax.persistence.Table;
/**
 * -----------------------------------------
 * @文件: Employee.java
 * @作者: fancy
 * @邮箱: fancyzero@yeah.net
 * @时间: 2012-6-10
 * @描述: 实体类
 * -----------------------------------------
 */
/**
 * 下面只说@ManyToOne,如需了解其他注解,
 * 可以参考上一篇:http://www.cnblogs.com/fancyzero/archive/2012/06/10/hibernate-one-to-one-annotation.html
 */
@Entity
@Table(name = "t_employee")
public class Employee {


    private Integer employeeId;
    private String  employeeName;
    private Company company;
    
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    public Integer getEmployeeId() {
        return employeeId;
    }
    /**
     * @ManyToOne:多对一,cascade:级联,请参考上一篇
      * fetch = FetchType.LAZY,延迟加载策略,如果不想延迟加载可以用FetchType.EAGER
     */
    @ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH},fetch = FetchType.LAZY)
    @JoinColumn(name = "cid")
    public Company getCompany() {
        return company;
    }
    public String getEmployeeName() {
        return employeeName;
    }
    public void setEmployeeId(Integer employeeId) {
        this.employeeId = employeeId;
    }
    public void setEmployeeName(String employeeName) {
        this.employeeName = employeeName;
    }
    public void setCompany(Company company) {
        this.company = company;
    }
}

 Company.java

package com.fancy.po;


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.ManyToOne;
import javax.persistence.Table;
/**
 * -----------------------------------------
 * @文件: Employee.java
 * @作者: fancy
 * @邮箱: fancyzero@yeah.net
 * @时间: 2012-6-10
 * @描述: 实体类
 * -----------------------------------------
 */
/**
 * 下面只说@ManyToOne,如需了解其他注解,
 * 可以参考上一篇:http://www.cnblogs.com/fancyzero/archive/2012/06/10/hibernate-one-to-one-annotation.html
 */
@Entity
@Table(name = "t_employee")
public class Employee {


    private Integer employeeId;
    private String  employeeName;
    private Company company;
    
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    public Integer getEmployeeId() {
        return employeeId;
    }
    /**
     * @ManyToOne:多对一,cascade:级联,请参考上一篇
      * fetch = FetchType.LAZY,延迟加载策略,如果不想延迟加载可以用FetchType.EAGER
     */
    @ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH},fetch = FetchType.LAZY)
    @JoinColumn(name = "cid")
    public Company getCompany() {
        return company;
    }
    public String getEmployeeName() {
        return employeeName;
    }
    public void setEmployeeId(Integer employeeId) {
        this.employeeId = employeeId;
    }
    public void setEmployeeName(String employeeName) {
        this.employeeName = employeeName;
    }
    public void setCompany(Company company) {
        this.company = company;
    }
}
Test.java


package com.fancy.test;


import java.util.Iterator;
import java.util.Set;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.cfg.Configuration;
import com.fancy.po.Company;
import com.fancy.po.Employee;
/**
 * -----------------------------------------
 * @文件: Test.java
 * @作者: fancy
 * @邮箱: fancyzero@yeah.net
 * @时间: 2012-6-10
 * @描述: 测试类
 * -----------------------------------------
 */
public class Test {


    public static void main(String[] args) {
        //读取hibernate配置,默认读取classpath下的hibernate.cfg.xml
        Configuration conf = new AnnotationConfiguration();    
        //构建session工厂
         SessionFactory sessionFactory = conf.configure().buildSessionFactory();
        //打开session
        Session session = sessionFactory.openSession();
        //开始事务
         session.beginTransaction();
        // * * * * * * * * * * * * * * * * * * * * * * * * * * * *
        //test1(session);   //测试 1
        //test2(session);  //测试  2
        test3(session);   //测试   3
        // * * * * * * * * * * * * * * * * * * * * * * * * * * * *
        //提交事务
         session.getTransaction().commit();
        //关闭session工厂
         sessionFactory.close();
        //关闭session
        session.close();
    }
    public static void test1(Session session){
        Company company = (Company)session.get(Company.class, 1); //发出Company的select语句
         Set employee = company.getEmployees();         //不发出Employee的select语句
         System.out.println("Company :" + company.getCompanyName());
        System.out.println("CountSum:" + employee.size()); //Employee初次被使用,发出select语句
         Iterator it = employee.iterator(); //Employee不再发出select语句
         while(it.hasNext()){
          System.out.println("EmployeeName:" + it.next().getEmployeeName());
        }
    }
    public static void test2(Session session){
       Company company = (Company)session.get(Company.class, 2);//发出Company的select语句
        Set employee = company.getEmployees();        //不发出Employee的select语句
        Iterator it = employee.iterator(); //发出Employee的select语句
        Employee e = null;
       Boolean first = false;
       while(it.hasNext()){
          e = it.next();
          if(!first){
              System.out.println("EmployeeId:[" + e.getEmployeeId() + "] information will be change");
              e.setEmployeeName("fancy"); //更改雇员名字
            //  session.save(e);  //发出Employee的update语句,不发出Company的update语句
                session.save(company);    //发出Employee的update语句,不发出Company的update语句
                first = true;
            }
            System.out.println("EmployeeName:" + e.getEmployeeName());
        }
    }
    public static void test3(Session session){
        Employee employee = (Employee)session.get(Employee.class, 1);//发出Employee的select语句
         Company  company  = (Company)session.get(Company.class, 1);//发出Company的select语句
         company.setCompanyName("Oracle"); //更改公司名字
    //  session.save(company);//发出Company的update语句,不发出Employee的update语句
         session.save(employee);//发出Company的update语句,不发出Employee的update语句
    }
}


一、一对多(@OneToMany)
1、单向一对多模型
假设通过一个客户实体可以获得多个地址信息。
对于一对多的实体关系而言,表结构有两种设计策略,分别是外键关联和表关联。
(1) 映射策略---外键关联
在数据库中表customer和表结构address定义,如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
create table customer (
  id int(20) not null auto_increment,
  name varchar(100),
  primary key(id)
)
 
create table address (
  id int(20) not null auto_increment,
  province varchar(50),
  city varchar(50),
  postcode varchar(50),
  detail varchar(50),
  customer_id int(20),
  primary key (id)
)

注意此时外键定义在多的一方,也就是address表中。

 此时,表customer映射为实体CustomerEO,代码如下:

?
1
2
3
4
5
6
7
8
@Entity
@Table(name="customer")
public class CustomerEO implements java.io.Serializable {
  @OneToMany(cascade={ CascadeType.ALL })
  @JoinColumn(name="customer_id")
  private Collection addresses = new ArrayList();
 ...
}
注释@OneToMany的定义代码如下:
?
1
2
3
4
5
6
7
@Target({METHOD, FIELD}) @Retention(RUNTIME)
public @interface OneToMany {
  Class targetEntity() default void.class;
  CascadeType[] cascade() default {};
  FetchType fetch() default LAZY;
  String mappedBy() default "";
}
使用时要注意一下几点问题: 
a、targetEntity属性表示默认关联的实体类型。如果集合类中指定了具体类型了,不需要使用targetEntity.否则要指定targetEntity=AddressEO.class。 
b、mappedBy属性用于标记当实体之间是双向时使用。 

(2) 映射策略---表关联 
在上面address表中去掉customer_id字段,在增加一个表ref_customer_address,如下: 
?
1
2
3
4
5
--客户地址关系表
create table ref_customer_address (
  customer_id int(20) not null,
  address_id int(20) not null unique
)
此时表customer映射为CustomerEO实体,代码如下:
?
1
2
3
4
5
6
7
8
9
10
11
@Entity
@Table(name = "customer")
public class CustomerEO implements java.io.Serializable {
  ...
  @OneToMany(cascade = { CascadeType.ALL })
  @JoinTable(name="ref_customer_address",
           joinColumns={ @JoinColumn(name="customer_id",referencedColumnName="id")},
           inverseJoinColumns={@JoinColumn(name="address_id",referencedColumnName="id")})
  private Collection addresses = new ArrayList();
  ...
}
表关联@JoinTable,定义如下:
?
1
2
3
4
5
6
7
8
9
@Target({METHOD,FIELD})
public @interface JoinTable {
  String name() default "";
  String catalog() default "";
  String schema() default "";
  JoinColumn[] joinColumns() default {};
  JoinColumn[] inverseJoinColumns() default {};
  UniqueConstraint[] uniqueConstraints default {};
}

其中:
a、该标记和@Table相似,用于标注用于关联的表。
b、name属性为连接两张表的表名。默认的表名为:“表名1”+“-”+“表名2”,上面例子默认的表名为customer_address。
c、joinColumns属性表示,在保存关系中的表中,所保存关联的外键字段。
d、inverseJoinColumns属性与joinColumns属性类似,不过它保存的是保存关系的另一个外键字段。

(3) 默认关联
在数据库底层为两张表添加约束,如下:

?
1
2
3
4
5
6
7
create table customer_address (
  customer_id int(20) not null,
  address_id int(20) not null unique
)
alter table customer_address add constraint fk_ref_customer foreign key (customer_id) references customer (id);
 
alter table customer_address add constraint fk_ref_address foreign key (address_id) references address (id);

这样,在CustomerEO中只需要在标注@OneToMany即可!


二、多对一@ManyToOne
1、单向多对一模型。
(1) 外键关联
配置AddressEO实体如下:

?
1
2
3
4
5
6
7
8
9
10
@Entity
@Table(name="address")
public class AddressEO implements java.io.Serializable {
     
  @ManyToOne(cascade = { CascadeType.ALL })
  @JoinColumn(name="customer_id")
  private CustomerEO customer;
     
  // ...
}

@ManyToOne定义如下:

?
1
2
3
4
5
6
7
@Target({METHOD,FIELD}) @Retention(RUNTIME)
public @interface ManyToOne {
  Class targetEntity() default void.class;
  CascadeType[] cascade() default {};
  FetchType fatch() default EAGER;
  boolean optional() default true;
}


(2) 默认关联
数据库脚本定义的相关字段的约束,创建外键后,直接使用@ManyToOne

三、高级一对多和多对一映射
即双向关联模型,确定了双向关联后,多的一方AddressEO不变使用@ManyToOne,而CustomerEO实体修改为:

?
1
2
3
4
5
6
7
8
9
@Entity
@Table(name="customer")
public class CustomerEO {
     
  @OneToMany(mappedBy="customer")
  private Collection addresses = new ArrayList();
     
  // ...
}
其中,@OneToMany标记中的mappedBy属性的值为AddressEO实体中所引用的CustomerEO实体的属性名。
阅读(19168) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~