jpa相关说明---OpenJpa
各个字段的映射:
@Entity
@Table(name="person")
public class Person {
@Id @GeneratedValue //不写是采用默认策略,即:(Strategy=Generation.AUTO)
private Integer id; //主键且数据库是mysql就自动增长(identified),是Oracle就序列化(sequence)
@Column(length=10, nullable=false) //长度为10,且不能为空
private String name;
@Temporal(TemporalType.DATE) //日期类型
private Date birthday;
@Lob //长整型,对应到mysql数据库为LongText
private String info;
@Lob @Basic(fetch=FetchType.LAZY) //二进制数据,且延迟加载
private Byte[] file;
@Enumerated(EnumType.STRING) @Column(length=5,nullable=false) //枚举类型,且将值存入数据库
private Gender gender= Gender.MAN;
@Transient //不映射进数据库
private String imagepath;
}
@Id
@Column(name="id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
主键生成,注解
@GeneratedValue
•AUTO: JPA自动选择合适的策略,是默认选项;
•IDENTITY: 采用数据库ID自增长的方式来生成主键值,Oracle不支持这种方式;
•SEQUENCE: 通过序列产生主键,通过@SequenceGenerator注解指定序列名,MySql不支持这种方式;
•TABLE: 采用表生成方式来生成主键值,那怎么样生成呢?很简单,表里面通常有两个字段,第一个字段是给它一个名称(就是个列名而已),第二个字段专门用来累加用的,就是说每访问一次这个表,第二个字段就会累加1,不断累加。就是说你们要得到这个主键值的话,访问这个表,然后update这个表的这个字段,把它累加1之后,然后再把这个值取出来作为主键,再给他赋进去,表生成就是这样。TABLE表生成方式才是通用的,但是这种方式效率并不高。
Oracle数据库默认情况下,不能支持用id自增长方式来生成主键值;
mysql在默认情况下不能支持SEQUENCE序列的方式来生成主键值,所以我们一定要注意我们使用的数据库。
不知道哪种数据库,用AUTO, 由jpa根据配置,如果用的是mysql,那么它会用IDENTITY。
注意:如果我们把策略strategy设置成@GeneratedValue(strategy=GenerationType.AUTO)的话,AUTO本身就是策略的默认值,我们可以省略掉,就是说简单写成这样@GeneratedValue
一对多关系(1-n):
OneToMany
Order.java
/* one端
@OneToMany(cascade={CascadeType.PERSIST,CascadeType.MERGE,CascadeType.REMOVE})
mappedBy="order": 指明Order类为双向关系维护端,负责外键的更新
*/
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "order")
OrderItem.java
// optional=true:可选,表示此对象可以没有,可以为null;false表示必须存在
@ManyToOne(cascade = { CascadeType.REFRESH,CascadeType.PERSIST , CascadeType.MERGE }, optional = true)
@JoinColumn(name = "order_id")
private Order order;
CascadeType.REFRESH:级联刷新,也就是说,当你刚开始获取到了这条记录,那么在你处理业务过程中,这条记录被另一个业务程序修改了(数据库这条记录被修改了),那么你获取的这条数据就不是最新的数据,那你就要调用实体管理器里面的refresh方法来刷新实体,所谓刷新,大家一定要记住方向,它是获取数据,相当于执行select语句的(但不能用select,select方法返回的是EntityManager缓存中的数据,不是数据库里面最新的数据),也就是重新获取数据。
CascadeType.PERSIST:级联持久化,也就是级联保存。保存order的时候也保存orderItem,如果在数据库里已经存在与需要保存的orderItem相同的id记录,则级联保存出错。
CascadeType.MERGE: 级联更新,也可以叫级联合并;当对象Order处于游离状态时,对对象Order里面的属性作修改,也修改了Order里面的orderItems。
CascadeType.REMOVE:当对Order进行删除操作的时候,也要对orderItems对象进行级联删除操作。
如果在应用中,要同时使用这四项的话,可以改成cascade = CascadeType.ALL
应用场合问题:这四种级联操作,并不是对所有的操作都起作用,只有当我们调用实体管理器的persist方法的时候,CascadeType.PERSIST才会起作用;同样道理,只有当我们调用实体管理器的merge方法的时候,CascadeType.MERGE才会起作用,其他方法不起作用。同样道理,只有当我们调用实体管理器的remove方法的时候,CascadeType.REMOVE才会起作用。
注意: Query query = em.createQuery("delete from Person o where o.id=?1");这种删除会不会起作用呢?是不会起作用的,因为配置里那四项都是针对实体管理器的对应的方法。