接着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语句。