欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

jpa相关说明---OpenJpa

程序员文章站 2022-07-03 19:56:34
...

各个字段的映射:

 

@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");这种删除会不会起作用呢?是不会起作用的,因为配置里那四项都是针对实体管理器的对应的方法。