jpa核心api

接着jpa第一个程序及基础注解来介绍核心api,实体类User如下

@Entity
@Table(name = "t_user")
public class User {

    @Id//必须指定主键
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Long id;

    @Column(name="user_name")
    private String userName;

    private String password;

    private String telephone;

    private String email;

    @Column(name="create_time")
    @Temporal(TemporalType.DATE)
    private Date createTime;

    //映射必须定义个空构造器
    public User() {
    }

    public User(String userName, String password, String telephone, String email, Date createTime) {
        super();
        this.userName = userName;
        this.password = password;
        this.telephone = telephone;
        this.email = email;
        this.createTime = createTime;
    }
    public String getUserInfo(){
        return "username:"+this.userName+",email:"+this.email;
    }
    get,set,toString方法
}

测试步骤
1、创建EntityManager工厂
2、创建EntityManager
3、获取事务,开启事务
4、执行持久化操作
5、提交事务
6、关闭EntityManager

除了4其它都是重复步骤,可以提取出来。

public class TestCase2 {
    private EntityManager entityManager;
    private EntityManagerFactory entityManagerFactory;
    private EntityTransaction transaction;

    @Before
    public void init(){
        entityManagerFactory = Persistence.createEntityManagerFactory("jpa-2");
        entityManager = entityManagerFactory.createEntityManager();
        transaction = entityManager.getTransaction();
        transaction.begin();
    }
    @After
    public void destory(){
        transaction.commit();
        entityManager.close();
        entityManagerFactory.close();
    }
}

1、find(Class,oid):该方法根据主键(oid)查询给定的实体,先去缓存中(一级缓存,entityManager中)查询,如果缓存中有那么直接返回,如果缓存中没有那么会去数据库查询,查到了则返回封装好了的实体对象,没有查到则返回null。类似域hibernate中的get方法。

   @Test
    //1、根据id查询,类似于hibernate中session的get方法
    public void testFind(){
        User user = entityManager.find(User.class, 1l);
        System.out.println(user.getUserInfo());
        User user2 = entityManager.find(User.class, 1l);
        System.out.println(user.getUserInfo());
    }
输出:
Hibernate: 
    select
        user0_.id as id1_0_0_,
        user0_.create_time as create_t2_0_0_,
        user0_.email as email3_0_0_,
        user0_.password as password4_0_0_,
        user0_.telephone as telephon5_0_0_,
        user0_.user_name as user_nam6_0_0_ 
    from
        t_user user0_ 
    where
        user0_.id=?
username:Tom,email:tom@qq.com
username:Tom,email:tom@qq.com

输出结果能看到,首先在缓存中没查到,然后去了数据库查询,查询到了后保存了一份数据在缓存中,再去查缓存的时候就查询到了,而不必发送sql去数据库查询。

2、getReference(Class,oid):这个方法也是根据id查询,但是如果关联了实体类的话就跟find方法有区别了,因为存在着懒加载问题。类似于hibernate中的load方法。

    @Test
    //2、根据id查询,类似于hibernate中session的load方法(存在延迟加载问题)
    public void testReference(){
        User user = entityManager.getReference(User.class, 1l);
        System.out.println(user.getUserInfo());
    }

3、persist(entity T):该方法用于持久化数据,将实体类持久化到数据库中的一条记录,类似于hibernate中的save方法。与hibernate不同的是,创建实体的时候就设置了主键自增,如果实体类设置了id再执行该操作则会抛出异常。而hibernate会直接忽略该id执行操作。

@Test
    public void testPersist(){
        User user = new User("Lucy", "123456", "13322222226", "lucy@qq.com",new Date());
        entityManager.persist(user);
    }
控制台输出:
Hibernate: 
    insert 
    into
        t_user
        (create_time, email, password, telephone, user_name) 
    values
        (?, ?, ?, ?, ?)
    @Test
    public void testPersist2(){
        User user = new User("Lucy", "123456", "13322222226", "lucy@qq.com",new Date());
        user.setId(3l); 
        entityManager.persist(user);
    }

执行方法会抛出持久化对象异常
注:这个方法其实也是可以用作修改的,虽然不能有oid但是,可以从数据库中查出来指定对象,然后修改属性再执行该操作,则会执行修改。

比如:

@Test
    public void test3(){
        User user2 = entityManager.find(User.class, 1l);
        user2.setEmail("xixi@qqqq.com");
        entityManager.persist(user2);
    }
输出:
Hibernate: 
    select
        user0_.id as id1_0_0_,
        user0_.create_time as create_t2_0_0_,
        user0_.email as email3_0_0_,
        user0_.password as password4_0_0_,
        user0_.telephone as telephon5_0_0_,
        user0_.user_name as user_nam6_0_0_ 
    from
        t_user user0_ 
    where
        user0_.id=?
Hibernate: 
    update
        t_user 
    set
        create_time=?,
        email=?,
        password=?,
        telephone=?,
        user_name=? 
    where
        id=?

4、remove(Object obj):传入实体删除数据库对应记录,但是该方法只能删除持久化状态对象而不能删除游离状态对象。hibernate则都可以。

    @Test
    //删除游离状态对象
    public void testRemove(){
        User user = new User();
        user.setId(2l);
        entityManager.remove(user);
    }
    会抛出非法语句异常
    @Test
    public void testRemove(){
        /*User user = new User();
        user.setId(2l);
        entityManager.remove(user);*/
        User user2 = entityManager.find(User.class, 2l);
        entityManager.remove(user2);
    }
    执行之后,查看数据库,id为2的记录成功删除
控制台输出:
Hibernate: 
    select
        user0_.id as id1_0_0_,
        user0_.create_time as create_t2_0_0_,
        user0_.email as email3_0_0_,
        user0_.password as password4_0_0_,
        user0_.telephone as telephon5_0_0_,
        user0_.user_name as user_nam6_0_0_ 
    from
        t_user user0_ 
    where
        user0_.id=?
Hibernate: 
    delete 
    from
        t_user 
    where
        id=?

5、merge(entity T):类似于hibernate的saveOrUpdate()方法,但是根据传入的实体状态不同执行语句也会有区别。
(1)、如果传入的对象是临时状态(刚new出来的,并且在数据库中没有与oid对应的主键),会创建一个新的对象,把临时对象的属性复制到新的对象中,然后对新的对象执行持久化操作。所以新的对象中有id,但以前的临时对象中没有id

    @Test
    public void testMerge(){
        User user = new User("Torra", "123456", "15922222226", "Torra@qq.com",new Date());
        User user2 = entityManager.merge(user);
        System.out.println("user:"+user.getId());
        System.out.println("user2:"+user2.getId());
    }
控制台输出:
Hibernate: 
    insert 
    into
        t_user
        (create_time, email, password, telephone, user_name) 
    values
        (?, ?, ?, ?, ?)
user:null
user2:5

(2)、若传入的是一个托管状态对象(数据库中有,session缓存(entityManager中没有)),那么JPA会查询对应记录,返回该记录对应的对象,再然后把游离对象的属性复制到查询到的对象中,对新创建的对象执行update操作。

    @Test
    public void testMerge2(){
        User user = new User("Torra", "123456", "15922222226", "Torra@qq.com",new Date());
        user.setId(1l);
        User user2 = entityManager.merge(user);
        System.out.println(user==user2);
    }
控制台输出:
Hibernate: 
    select
        user0_.id as id1_0_0_,
        user0_.create_time as create_t2_0_0_,
        user0_.email as email3_0_0_,
        user0_.password as password4_0_0_,
        user0_.telephone as telephon5_0_0_,
        user0_.user_name as user_nam6_0_0_ 
    from
        t_user user0_ 
    where
        user0_.id=?
false
Hibernate: 
    update
        t_user 
    set
        create_time=?,
        email=?,
        password=?,
        telephone=?,
        user_name=? 
    where
        id=?

需要看执行流程是不是上面说的那样,可以在某个set方法上加断点,进行debug测试,如果三次进入该方法那么说话跟描述的一致。第一次是对游离状态对象设置属性,第二次是对查询出来的对象设置属性,最后一次是复制。

6、flush():同步持久上下文环境,即将持久上下文环境的所有未保存实体的状态信息保存到数据库中。

    @Test
    public void testFlush(){
        User user = entityManager.find(User.class, 1l);
        user.setEmail("qiqi@qq.com");
        entityManager.flush();
    }
控制台输出:
Hibernate: 
    select
        user0_.id as id1_0_0_,
        user0_.create_time as create_t2_0_0_,
        user0_.email as email3_0_0_,
        user0_.password as password4_0_0_,
        user0_.telephone as telephon5_0_0_,
        user0_.user_name as user_nam6_0_0_ 
    from
        t_user user0_ 
    where
        user0_.id=?
Hibernate: 
    update
        t_user 
    set
        create_time=?,
        email=?,
        password=?,
        telephone=?,
        user_name=? 
    where
        id=?

7、clear():清除持久上下文环境,断开所有关联的实体。如果这时还有未提交的更新则会被撤消。

    @Test
    public void testClear(){
        User user = entityManager.find(User.class, 1l);
        entityManager.clear();
        user.setEmail("torra@scu.com");
    }
控制台输出:一条出现语句,没有update语句
  select
        user0_.id as id1_0_0_,
        user0_.create_time as create_t2_0_0_,
        user0_.email as email3_0_0_,
        user0_.password as password4_0_0_,
        user0_.telephone as telephon5_0_0_,
        user0_.user_name as user_nam6_0_0_ 
    from
        t_user user0_ 
    where
        user0_.id=?

如果没有entityManager.clear()这条语句那么会多出一条update语句。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值