一、JPA更新指定字段
JPA更新指定字段需要使用EntityManager的merge方法将实体对象与数据库表进行同步。通过给实体对象的属性赋值后进行merge操作将在数据库表中更新对应的字段值,如下示例代码所示:
public void updateFieldById(Long id, String fieldName, Object fieldValue) {
T entity = entityManager.find(clazz, id);
if (entity != null) {
try {
Field field = clazz.getDeclaredField(fieldName);
field.setAccessible(true);
field.set(entity, fieldValue);
entityManager.merge(entity);
} catch (NoSuchFieldException | IllegalAccessException e) {
e.printStackTrace();
}
}
}
二、JPA只查询指定字段
在JPA中,只需要指定实体类中需要查询的字段,就可以减少查询的数据量,提高查询效率。例如,使用@NamedQuery注解或者调用EntityManager的createNamedQuery方法来查询指定字段,如示例代码所示:
@NamedQuery(
name = "findUserNameById",
query = "SELECT u.username FROM User u WHERE u.id = :id"
)
public class User {
//...
}
public User findUserNameById(Long id) {
TypedQuery<String> query = entityManager.createNamedQuery("findUserNameById", String.class);
query.setParameter("id", id);
String username = query.getSingleResult();
return new User(username);
}
三、JPA查询返回指定字段
JPA查询返回指定字段需要自定义ResultClass,将查询返回的结果映射到自己定义的ResultClass中。自定义ResultClass需要使用@ConstructorResult注解,将查询返回的结果映射到实体类中的构造方法参数中,如下示例代码所示:
@SqlResultSetMapping(name = "UserInfoMapping", classes = {
@ConstructorResult(targetClass = UserInfo.class, columns = {
@ColumnResult(name = "username", type = String.class),
@ColumnResult(name = "age", type = Integer.class),
@ColumnResult(name = "address", type = String.class)
})
})
public class User {
//...
}
public List<UserInfo> getUsersInfo() {
Query query = entityManager.createNativeQuery("SELECT username, age, address FROM users", "UserInfoMapping");
return query.getResultList();
}
public class UserInfo {
private String username;
private Integer age;
private String address;
public UserInfo(String username, Integer age, String address) {
this.username = username;
this.age = age;
this.address = address;
}
// getter and setter
}
四、JPA查询指定排序字段
使用JPA查询指定排序字段需要在查询语句中添加order by子句,并在order by后指定排序字段,如下示例代码所示:
public List<User> findAllUsersOrderByUsername() {
return entityManager.createQuery("SELECT u FROM User u ORDER BY u.username", User.class).getResultList();
}
五、JPA查询某个字段
在JPA查询某个字段时,可以直接在查询语句中指定查询的字段,并使用getSingleResult方法获取结果集中的第一条记录,如下示例代码所示:
public String findUsernameById(Long id) {
return entityManager.createQuery("SELECT u.username FROM User u WHERE u.id = :id", String.class)
.setParameter("id", id)
.getSingleResult();
}
六、JPA查询字段为null或为空
在JPA中查询字段为null或为空需要使用IS NULL或IS EMPTY,如下示例代码所示:
public List<User> findUsersWithNullAddress() {
return entityManager.createQuery("SELECT u FROM User u WHERE u.address IS NULL OR u.address = ''", User.class)
.getResultList();
}
七、JPA连表查询展示多表字段选取
在JPA中进行连表查询,可以使用JPQL语句实现。其中关联字段通过JPA关系映射进行关联,查询结果需要自定义ResultClass来映射多表字段,如下示例代码所示:
@Entity
public class User {
@Id
private Long id;
private String username;
private Integer age;
@OneToOne(mappedBy = "user")
private Address address;
// getter and setter
}
@Entity
public class Address {
@Id
private Long id;
private String province;
private String city;
private String area;
@OneToOne
private User user;
// getter and setter
}
@SqlResultSetMapping(name = "UserAndAddressMapping", classes = {
@ConstructorResult(targetClass = UserAndAddress.class, columns = {
@ColumnResult(name = "username", type = String.class),
@ColumnResult(name = "age", type = Integer.class),
@ColumnResult(name = "province", type = String.class),
@ColumnResult(name = "city", type = String.class),
@ColumnResult(name = "area", type = String.class)
})
})
public class UserAndAddress {
private String username;
private Integer age;
private String province;
private String city;
private String area;
public UserAndAddress(String username, Integer age, String province, String city, String area) {
this.username = username;
this.age = age;
this.province = province;
this.city = city;
this.area = area;
}
// getter and setter
}
public List<UserAndAddress> findUserAndAddress() {
Query query = entityManager.createQuery("SELECT new com.example.UserAndAddress(u.username, u.age, a.province, a.city, a.area) FROM User u JOIN u.address a", UserAndAddress.class);
return query.getResultList();
}