EJB实体Bean的开发
一对一映射
一个人(Person)只有唯一的身份证号 (IDCard),Person 与 IDCard 是一对一关系。下面就以他们为例介绍存在 一对一关系的实体 Bean 开发过程
数据源的配置
META-INF
persistence.xml
<persistence>
<persistence-unit name="zk001">
<jta-data-source>java:/MySqlDS</jta-data-source>
<properties>
</properties>
</persistence-unit>
</persistence>
需要映射的数据库表
person
字段名称 字段类型属性 描述
personid (主键) Int(11) not null 人员 ID
PersonName Varchar(32) not null 姓名
sex Tinyint(1) not null 性别
age Smallint(6) not null 年龄
birthday Datetime null 出生日期
create table `test`.`idcard`(
`id` int not null auto_increment,
`cardno` varchar(32) default '' not null,
`Person_ID` int default '' not null,
primary key (`id`)
);
alter table `test`.`idcard`
add index `dfs`(`Person_ID`),
add constraint `dfs`
foreign key (`Person_ID`)
references `test`.`person`(`personid`);
create unique index `PRIMARY` on `test`.`idcard`(`id`);
create index `dfs` on `test`.`idcard`(`Person_ID`);
idcard
字段名称 字段类型属性 描述
id (主键) Int(11) not null 流水号
cardno Varchar(18) not null 身份证号
Person_ID Int(11) not null 作为外键指向person 表的主键
personid
create table `test`.`person`(
`personid` int not null auto_increment,
`PersonName` varchar(20) default '' not null,
`sex` int default '' not null,
`age` int default '' not null,
`birthday` varchar(50) default '' not null,
primary key (`personid`)
);
一对一关系需要在关系维护端(owner side)的@OneToOne 注释中定义 mappedBy 属性。在关系被维护端(inverseside)建立外键列指向关系维护端的主键列。
下面是关系维护端 Person.java 的源代码:
package com.pojo;
import java.io.Serializable;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.Table;
@SuppressWarnings("serial")
@Entity
@Table(name = "Person")
public class Person implements Serializable {
private Integer personid;
private String name;
private boolean sex;
private Short age;
private String birthday;
private IDCard idcard;
@Id
@GeneratedValue
public Integer getPersonid() {
return personid;
}
public void setPersonid(Integer personid) {
this.personid = personid;
}
@Column(name = "PersonName", nullable = false, length = 32)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Column(nullable = false)
public boolean getSex() {
return sex;
}
public void setSex(boolean sex) {
this.sex = sex;
}
@Column(nullable = false)
public Short getAge() {
return age;
}
public void setAge(Short age) {
this.age = age;
}
@Column(nullable = false)
public String getBirthday() {
return birthday;
}
public void setBirthday(String birthday) {
this.birthday = birthday;
}
@OneToOne(optional = true, cascade = CascadeType.ALL, mappedBy = "person")
// 使用@OneToONE标记映射一对一的关系
/*
* mappedBy:定义类与类的映射,如若是双向关联需要声明此标记,若为单向关联则不需要声明此标记
* 取值:必须与一对一的多方的属性名称相同(****重要****)
* cascade:设置的操作的级联关系(递归的操作) CascadeType的取值:ALL----全部的操作 MERGE----级联更新
* PERSIST----级联插入 REFRESH----级联刷新 REMOVE ----级联删除 fetch:表示查询的方式
* FetchType的取值:LAZY:延迟查询 EAGER:立即装载(不推荐)
*/
// 使用@OneToMany标记映射一对多的关系
/*
* mappedBy:定义类与类的映射,如若是双向关联需要声明此标记,若为单向关联则不需要声明此标记
* 取值:必须与一对多的多方的属性名称相同(****重要****)
* cascade:设置的操作的级联关系(递归的操作) CascadeType的取值:ALL----全部的操作 MERGE----级联更新
* PERSIST----级联插入 REFRESH----级联刷新 REMOVE ----级联删除 fetch:表示查询的方式
* FetchType的取值:LAZY:延迟查询 EAGER:立即装载(不推荐)
*/
public IDCard getIdcard() {
return idcard;
}
public void setIdcard(IDCard idcard) {
this.idcard = idcard;
}
}
}@OneToOne 注释指明 Person 与 IDCard 为一对一关系,@OneToOne 注释五个属性:targetEntit y、cascade、fetch、 optional 和 mappedB y, 前四个属性的具体含义与@ManyToOne 注释的同名属性一一对应, fetch 属性默认值是 FetchType.EAGER。mappedBy 属性的具体含义与@OneToMany 注释的同名属性相同。 上面的 optional = true 设置 idcard 属性可以为 null,也就是允讦没有身份证,未成年人就是没有身份证的。
package com.pojo;
import java.io.Serializable;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.Table;
@SuppressWarnings("serial")
@Entity
@Table(name = "IDCard")
public class IDCard implements Serializable{
private Integer id;
private String cardno;
private Person person;
public IDCard() {
}
public IDCard(String cardno) {
this.cardno = cardno;
}
@Id
@GeneratedValue
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
@Column(nullable=false,length=18,unique = true)
public String getCardno() {
return cardno;
}
public void setCardno(String cardno) {
this.cardno = cardno;
}
@OneToOne(optional = false, cascade = CascadeType.REFRESH)
@JoinColumn(name = "Person_ID", referencedColumnName = "personid",unique = true)
/*
* optional=false:主表和从表的连接关系
* false: inner join
* true: left join
* */
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
}
@OneToOne 注释指明 IDCard 与 Person 为一对一关系,IDCard 是关系被维护端,optional = false 设置 person 属性
值不能为 null,也就是身份证必须有对应的主人。@JoinColumn(name = "Person_ID", referencedColumnName =
"personid",unique = true)指明 IDCard 对应表的 Person_ID 列作为外键与 Person 对应表的 personid 列进行关联, unique= true 指明 Person_ID 列的值不可重复。
为了使用上面的实体 Bean,我们定义一个 Session Bean 作为他的使用者。下面是 Session Bean 的业务接口,他定 义了四个业务方法 insertPerson,getPersonByID,updatePersonInfo 和 deletePerson, 四个方法的业务功能是: insertPerson 添加一个人员(带一个身份证)进数据库
getPersonByID 获取指定编号的人员 updatePersonInfo 更新人名及身份证号 deletePerson 删除人员,连同其身份证一起删除 下面是 Session Bean 的业务接口及实现类package com.DAO;
import javax.ejb.Remote;
import com.pojo.Person;
@Remote
public interface PersonDAO {
public void insertPerson(String name, boolean sex, short age,
String birthday, String cardID);
public Person getPersonByID(Integer personid);
public void updatePersonInfo(Integer personid, String newname,
String newIDcard);
public void deletePerson(Integer personid);
package com.DAO;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import com.DAO.PersonDAO;
import com.pojo.IDCard;
import com.pojo.Person;
public @Stateless
class PersonDAOBean implements PersonDAO {
@PersistenceContext
private EntityManager em;
public void deletePerson(Integer personid) {
Person person = em.find(Person.class, personid);
if (person!=null) em.remove(person);
}
public Person getPersonByID(Integer personid) {
Person person = em.find(Person.class, personid);//QBC查询方式
return person;
}
public void insertPerson(String name, boolean sex, short age,
String birthday, String cardID) {
Person person = new Person();//生成实体BEAN的对象
person.setName(name);
person.setSex(sex);
person.setAge(Short.valueOf(age));
person.setBirthday(birthday);
IDCard idcard = new IDCard(cardID);//生成实体BEAN的对象
idcard.setPerson(person);
person.setIdcard(idcard);//设置双向关联
em.persist(person);//插入数据库
}
public void updatePersonInfo(Integer personid, String newname,
String newIDcard) {
Person person = em.find(Person.class, personid);
if (person!=null) {
person.setName(newname);
if (person.getIdcard()!=null){
person.getIdcard().setCardno(newIDcard);
}
em.merge(person);//更新方法
}
}
}
下面是 Session Bean 的 JSP 测试类代码:
import java.util.Date;
import java.util.Hashtable;
import java.util.Properties;
import javax.naming.Context;
import javax.naming.InitialContext;
import com.DAO.PersonDAO;
import com.pojo.Person;
public class Test {
public static void main(String[] args) throws Exception {
Properties props = new Properties();
props.setProperty("java.naming.factory.initial", "org.jnp.interfaces.NamingContextFactory");
props.setProperty("java.naming.provider.url", "localhost:1099");
props.setProperty("java.naming.factory.url.pkgs", "org.jboss.naming");
/*Hashtable prop=new Hashtable();
prop.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");
prop.put(Context.PROVIDER_URL, "jnp:/localhost");*/
InitialContext ctx = new InitialContext(props);
try {
PersonDAO oneToonedao = (PersonDAO) ctx
.lookup("PersonDAOBean/remote");
/*
* SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
* SimpleDateFormat formatter1 = new SimpleDateFormat("MMddhhmmss");
*/
String endno = "12010312";
oneToonedao.insertPerson("dddd", true, (short) 26, new Date().toGMTString(), "44011" + endno);
Person person = oneToonedao.getPersonByID(new Integer(5));
if (person != null) {
System.out.println("寻找编号为1的人员<br>");
System.out.println("姓名:" + person.getName() + " 身份证:"
+ person.getIdcard().getCardno() + "<br>");
} else {
System.out.println("没有找到编号为5的人员<br>");
}
System.out.println("更新编号为1的人员的姓名为李明,身份证号为33012" + endno + "<br>");
oneToonedao.updatePersonInfo(new Integer(5), "李明", "33012" + endno);
System.out.println("================删除编号为3的人员==============<br>");
oneToonedao.deletePerson(new Integer(6));
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
下面是 Session Bean 的 JSP 客户端代码:
OneToOneTest.jsp
<%@ page contentType="text/html; charset=GBK"%>
<%@ page import="com.foshanshop.ejb3.OneToOneDAO, com.foshanshop.ejb3.bean.*, javax.naming.*,
java.util.Date, java.text.SimpleDateFormat, java.util.*"%>
<%
Properties props = new Properties();
props.setProperty("java.naming.factory.initial",
"org.jnp.interfaces.NamingContextFactory"); props.setProperty("java.naming.provider.url", "localhost:1099"); props.setProperty("java.naming.factory.url.pkgs", "org.jboss.naming");
InitialContext ctx = new InitialContext(props);
try {
String outformate = "<font color=blue>CMD>>Out>></font> ";
OneToOneDAO oneToonedao = (OneToOneDAO) ctx.lookup("OneToOneDAOBean/remote"); SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd"); SimpleDateFormat formatter1 = new SimpleDateFormat("MMddhhmmss");
String endno = formatter1.format(new Date()).toString();
oneToonedao.insertPerson("zk001", true, (short)26,formatter.parse("1980-9-30"),
"44011"+endno);
//添加时请注意,身份证号不要重复,因为数据库字段身份证号是唯一的
Person person = oneToonedao.getPersonByID(new Integer(1));
if (person!=null){
out.println(outformate +"寻找编号为1的人员<br>");
out.println("姓名:"+ person.getName() +" 身份证:"+
person.getIdcard().getCardno() +"<br>");
}else{
out.println("没有找到编号为1的人员<br>");
}
+"<br>");
out.println(outformate +"更新编号为1的人员的姓名为李明,身份证号为33012" +endno
oneToonedao.updatePersonInfo(new Integer(1), "李明", "33012" +endno);
out.println("================删除编号为3的人员==============<br>");
oneToonedao.deletePerson(new Integer(3));
} catch (Exception e) {
out.println(e.getMessage());
}
%>