1. 写在类定义上
@Entity // 表明是实体类
@Table(name="person_db") // 映射到的表名
2. 主键修饰
@Id @GeneratedValue(strategy = GenerationType.AUTO)-----表中 auto_increment
@Column(name = "id") // 数据库id
表示是主键,并且对应增长形势,对应表列
1) IDENTITY:表自增键字段,Oracle不支持这种方式;
2) AUTO: JPA自动选择合适的策略,是默认选项; ===auto_increment
3. SEQUENCE:通过序列产生主键,通过@SequenceGenerator注解指定序列名,MySql不支持这种方式;
4. TABLE:通过表产生主键,框架借由表模拟序列产生主键,使用该策略可以使应用更易于数据库移植
1) 普通属性
@Column(name = "name") // 名字
直接在某一属性上写,表示此属性对应表的列
2) 关系属性
@OneToMany(cascade = CascadeType.ALL, mappedBy = "person", fetch = FetchType.EAGER)
mappedBy="school"就相当于inverse=true,(mappedBy指定的是不需要维护关系的一端)
关系属性上,表示是OneToMany
cascade级联关系 mappedBy对应类中的自己的应用属性名 fetch懒加载(eager lazy)
@ManyToOne (optional=true, fetch = FetchType.EAGER)
@JoinColumn(name="person_id", nullable=true, insertable = false, updatable = false)
关系属性上,表示是ManyToOne
name表示对应表内字段
注:必须是所谓的双向关系,不然报 没有序列化异常
5. mysql的序列生成
auto_increment 自动增长
uuid()函数 适用于并发,但是效率不高,且占磁盘。(UUID的内容是字符串的)
6. @Id
@GeneratedValue(generator = "system-uuid")
@GenericGenerator(name = "system-uuid", strategy = "uuid") -----表中id没有主键生成
7. 特殊@Formula("select COUNT(*) from school_info")
private int count;
8. 关系修饰
@OneToOne注释指明Person 与IDCard为一对一关系,@OneToOne注释五个属性:targetEntity、cascade、fetch、optional 和mappedBy
*optional = true设置idcard属性可以为null。
*targetEntity属性:Class类型的属性。定义关系类的类型,默认是该成员属性对应的类类型,所以通常不需要提供定义。
*cascade属性:CascadeType[]类型。该属性定义类和类之间的级联关系。定义的级联关系将被容器视为对当前类对象及其关联类对象采取相同的操作,
*而且这种关系是递归调用的。cascade的值只能从CascadeType.PERSIST(级联新建)、CascadeType.REMOVE(级联删除)、
*CascadeType.REFRESH(级联刷新)、CascadeType.MERGE(级联更新)中选择一个或多个。还有一个选择是使用CascadeType.ALL,表示选择全部四项。
*fetch属性:FetchType类型的属性。可选择项包括:FetchType.EAGER 和FetchType.LAZY。
*FetchType.EAGER表示关系类(本例是OrderItem类)在主类加载的时候同时加载,FetchType.LAZY表示关系类在被访问时才加载。默认值是FetchType.LAZY。
*@OrderBy(value = "id ASC")注释指明加载元组时按id的升序排序(降序 "DESC")
@JoinColumn(name = "Person_ID", referencedColumnName ="personid",unique = true)指明IDCard对应表的Person_ID列作为外键与Person对应表的personid列进行关联.
9. @OneToOne的四个属性
1). targetEntity
targetEntity 属性是 Class 类型的属性。定义实体一对一关系中处于从属地位的实体类的类型。
2). mappedBy
mappedBy 属性是 String 类型的属性。mappedBy 属性的值是当前实体在关联实体中的属性名称,使用 mappedBy 可以定义实体类之间的双向关系。如果类之间是单向关系,不需要提供定义,如果类和类之间形成双向关系,我们就需要使用这个属性进行定义,否则可能引起数据一致性的问题。
3). cascade
cascade 属性的类型是 CascadeType[] 类型。cascade 属性定义实体和实体之间的级联关系。使用 cascade 属性定义的级联关系将被容器视为对当前类对象及其关联类对象采取相同的操作,而且这种关系是递归调用的。
cascade 的值只能从 CascadeType.PERSIST(级联新建)、CascadeType.REMOVE(级联删除)、CascadeType.REFRESH(级联刷新)、CascadeType.MERGE(级联更新)中选择一个或多个。还有一个更方便的选择是使用 CascadeType.ALL,表示选择上面全部四项。
4) .fetch
fetch 属性是 FetchType 类型的属性。可选择项包括:FetchType.EAGER 和 FetchType.LAZY.前者表示关联关系的从类在主类加载的时候同时加载,后者表示关联关系的从类在自己被访问时才加载。默认值是 FetchType.EAGER.
5). optional
optional 属性是 boolean 类型的属性。optional 属性用于定义关联关系的从类对象是否必须存在。如果设置为 false,那么该属性就不能设置为 null.默认值是 true。注释的 optional 属性设为 True 表示该对象可以不存在。
例:
package com.persia.jpa; import java.io.Serializable; import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.OneToOne; import javax.persistence.Table; @Entity @Table(name="person") public class Person implements Serializable { private Integer id; private String name; private Short age; private Address address; @Id @GeneratedValue(strategy=GenerationType.AUTO) public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } @Column(name="personname",nullable=false,length=32) public String getName() { return name; } public void setName(String name) { this.name = name; } public Short getAge() { return age; } public void setAge(Short age) { this.age = age; } @OneToOne(optional=true,cascade=CascadeType.ALL,mappedBy="person") public Address getAddress() { return address; } public void setAddress(Address address) { this.address = address; } }
1. javax.persistence.JoinColumn 注释可以和 javax.persistence.OneToOne 注释一起使用,用于定义关联关系中的主类在数据库中对应的表
通过什么字段和关联关系中的从类的主键进行关联,这个注释是可选的,如果不提供该注释,OpenJPA 会默认使用“对象名_ID”和关联表的主键字段进行关联。
2.JoinColumn 注释支持两个重要属性:name 和 referencedColumnName 属性。
(1)name
name 属性的类型是 String 类型。name 属性用于指定关联关系中的主类对应的表中和关联关系中的从类的主键进行关联的字段的名称。
(2)referencedColumnName
referencedColumnName 属性的类型是 String 类型。referencedColumnName 属性指定关联关系中的从类与关联关系中的主类对应的表之间形成关联关系的字段名称,通常用于关联关系中的从类的关联字段不是自己的主键的情况。
package com.persia.jpa; import java.io.Serializable; import javax.persistence.CascadeType; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.OneToOne; import javax.persistence.Table; @Entity @Table(name="address") public class Address implements Serializable { private Integer id; private String city; private String street; private Person person; @Id @GeneratedValue(strategy=GenerationType.AUTO) public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } public String getStreet() { return street; } public void setStreet(String street) { this.street = street; } @OneToOne(optional=false,cascade=CascadeType.ALL) @JoinColumn(name="person_id",referencedColumnName="id",unique=true) public Person getPerson() { return person; } public void setPerson(Person person) { this.person = person; } }
使用 JoinColumn 注释设置两个对象对应数据库表之间的关联字段
name 属性指定关联关系中主类对应表中参与关联关系的字段名称,
referencedColumnNam 属性指定关联关系中从类对应表中参与关联关系的字段名称。
实体操作:
package com.persia.jpa; import javax.ejb.Remote; import javax.ejb.Stateless; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; @Stateless @Remote({OneToOneDAO.class}) public class OneToOneDAOBean implements OneToOneDAO { @PersistenceContext private EntityManager em; @Override public void deleteAddress(Integer id) { // TODO Auto-generated method stub Address a=em.find(Address.class, id); em.remove(a); } @Override public void deletePerson(Integer id) { // TODO Auto-generated method stub Person p=em.find(Person.class,id); em.remove(p); } @Override public Person getPersonByID(Integer id) { // TODO Auto-generated method stub Person p=em.find(Person.class,id); return p; } @Override public void insertPerson(String name, short age, String city, String street) { // TODO Auto-generated method stub Person p=new Person(); p.setName(name); p.setAge(age); Address address=new Address(); address.setCity(city); address.setStreet(street); address.setPerson(p); p.setAddress(address); em.persist(p); } @Override public void updatePersonInfo(Integer id, String newname, String newstreet) { // TODO Auto-generated method stub Person p=em.find(Person.class,id); p.setName(newname); Address a=p.getAddress(); a.setStreet(newstreet); } }
客户端:
package com.persia.jpa.test; import java.util.Properties; import javax.naming.InitialContext; import javax.naming.NamingException; import com.persia.jpa.oto.OneToOneDAO; import com.persia.jpa.oto.Person; public class Test { /** * @param args * @throws NamingException */ public static void main(String[] args) throws NamingException { 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 context=new InitialContext(props); try{ OneToOneDAO dao=(OneToOneDAO)context.lookup("OneToOneDAOBean/remote"); // dao.insertPerson("persia",new Short((short)26), "beijing", "shangdi"); //dao.insertPerson("linda", new Short((short)26), "beijing", "shangdi"); // dao.deletePerson(new Integer(8)); Person p=dao.getPersonByID(new Integer(5)); System.out.println(p.getName()+"-"+p.getAddress().getStreet()); dao.updatePersonInfo(new Integer(5), "persiacai", "fujian"); dao.deleteAddress(new Integer(10)); }catch(Exception e){ e.printStackTrace(); } } }