0
点赞
收藏
分享

微信扫一扫

uniapp文件下载

云岭逸人 2023-07-28 阅读 96
hibernate

JPA


定义:是 JavaEE 中一组用于持久化数据的 API,它提供了一种标准的 ORM 规范,用于 Java 对象映射到数据库中。
JPA 的开发是为了简化企业级应用程序的开发,降低应用程序与数据库之间的耦合度,并提高应用程序的可维护性和可扩展性。
JPA 定义了一系列注解和接口,用于描述 Java 对象与数据库表之间的映射关系。其中,最重要的是实体类(Entity)和实体管理器(EntityManager)。

注意:JPA 只是一种规范,具体的实现由不同的厂商提供,比如 Hibernate、EclipseLink 等。因此,在使用 JPA 时,需要选择一个合适的实现,并按照其提供的文档进行配置和使用。

Interview & Answer

什么是 JPA?它的作用是什么?

JPA 中的实体类是什么?如何定义实体类?

JPA 提供了哪些 API 接口?分别有什么作用?

JPA 中的实体管理器是什么?如何使用它来操作实体对象?

JPA 中的注解有哪些?它们的作用是什么?

JPA 中的事务管理是如何实现的?如何配置事务管理器?

JPA 中的缓存机制是如何实现的?什么是一级缓存和二级缓存?

JPA 中的 JPQL 是什么?如何使用 JPQL 进行查询操作?

JPA 的实现有哪些?它们之间有什么区别?

JPA 和 Hibernate 之间有什么关系?它们之间有什么区别?

JPA 实现方式及缓存默认状态

        JPA规范并没有指定一级和二级缓存的默认状态,这取决于具体的JPA实现和配置。下面是常见的JPA实现的默认缓存状态:

  • Hibernate:Hibernate是一个常用的JPA实现,它的一级缓存(Session级别的缓存)默认是开启的,而二级缓存(应用程序级别的缓存)默认是关闭的。可以通过配置文件或者代码的方式来开启或关闭二级缓存。

  • EclipseLink:EclipseLink是另一个常用的JPA实现,它的一级缓存(EntityManager级别的缓存)默认是开启的,而二级缓存(应用程序级别的缓存)默认是关闭的。可以通过配置文件或者代码的方式来开启或关闭二级缓存。

  • OpenJPA:OpenJPA是另一个流行的JPA实现,它的一级缓存(EntityManager级别的缓存)默认是开启的,而二级缓存(应用程序级别的缓存)默认是关闭的。可以通过配置文件或者代码的方式来开启或关闭二级缓存。

如何理解都默认开一级缓存

        有点类似都在一个事务中,这要求可重复读等,所以都要开启

JPA 注解使用 demo

    // 查询
    @Query(value = "SELECT * FROM user WHERE name = :name", nativeQuery = true)
    List<User> findByName(@Param("name") String name);

    // 修改
    @Modifying
    @Query(value = "UPDATE user SET age = :age WHERE id = :id", nativeQuery = true)
    void updateAgeById(@Param("id") Long id, @Param("age") Integer age);

    // 删除
    @Modifying
    @Query(value = "DELETE FROM user WHERE id = :id", nativeQuery = true)
    void deleteById(@Param("id") Long id);

    // list 入参
    @Query("SELECT u FROM User u WHERE u.name IN :names")
    List<User> findByNames(@Param("names") List<String> names);

    // map 入参
    // 在这个示例中,我们定义了一个自定义查询方法findByCondition,使用@Query注解指定了JPQL查询语句。查询语句中使用了实体类User和其属性name、age,使用AND关键字指定查找name属性等于condition中的"name"键对应的值,age属性大于等于condition中的"minAge"键对应的值的用户信息
    // 使用Map作为查询条件时,需要注意的是,Map中的键必须与JPQL查询语句中的参数名一致,否则会抛出异常。
    @Query("SELECT u FROM User u WHERE u.name = :name AND u.age >= :minAge")
    List<User> findByCondition(@Param("condition") Map<String, Object> condition);

    // 复杂对象入参
    // @Query("SELECT u FROM User u WHERE u.name = :#{#query.name} AND u.age >= :#{#query.minAge}")
    //    List<User> findByCondition(@Param("query") UserQuery query);
    //
    //public class UserQuery {
    //    private String name;
    //    private Integer minAge;
    //    // 省略getter和setter方法
    //}

    // 联表查询
    // @Query("SELECT o FROM Order o JOIN o.user u WHERE u.name = :name")
    //    List<Order> findByUserName(@Param("name") String name);

    // null 不更新
    @Query("UPDATE TP_USER_ACTIVITY_LOG \n" +
        "SET IF :name IS NOT NULL THEN name = :name END IF\n" +
        ",age = :age\n" +
        "WHERE LOG_DATE = :logDate")
    Integer updateTest(@Param("name") String name, @Param("age") String age, @Param("logDate") Date logDate);

    // 关键在于数据库if 语句使用,不同数据库if的用法有所不同,所以,没有通用性
    
    // where 条件 为 null 
        //  如果为空时显示1=1 代表参数为真,对查询结果不产生作用。
        // "WHERE IF (:byname is not null, c.byname LIKE CONCAT('%',:byname,'%') , 1 = 1) and IF (:isMember is not null, c.is_member = :isMember , 1 = 1) and IF (:isBlacklist is not null, c.is_blacklist = :isBlacklist , 1 = 1) and "
    // + "IF (:phone is not null, c.phone = :phone , 1 = 1)"

Hibernate


Hibernate 一级缓存

Hibernate 的一级缓存是 Session 级别的缓存,它默认是开启的,并且通常是不建议关闭的。但是,在某些特定的场景下,关闭一级缓存可能是有必要的,例如:

  • 当需要强制刷新缓存,以避免缓存数据和数据库数据不一致时,可以考虑关闭一级缓存。
  • 当需要避免缓存数据的过期或者内存溢出时,可以考虑关闭一级缓存。
  • 当需要测试或者调试缓存相关的问题时,可以考虑关闭一级缓存。

关闭 Hibernate 的一级缓存有以下两种方式:

① 在 Session 中调用 clear() 方法:通过 Session 的 clear() 方法可以清空一级缓存中的所有数据。例如:

    Session session = sessionFactory.openSession();
    session.beginTransaction();
    // 这里执行数据库操作,将数据写入数据库
    session.clear(); // 清空一级缓存
    // 这里再次执行数据库操作,从数据库中读取最新的数据

② 在 Hibernate 配置文件中设置缓存策略:通过在 Hibernate 配置文件(如 hibernate.cfg.xml)中设置缓存策略可以关闭一级缓存。例如:

<hibernate-configuration>
<session-factory>
    <!-- ... -->
      <property name="hibernate.cache.use_second_level_cache">false</property>
      <property name="hibernate.cache.use_query_cache">false</property>
    <!-- ... -->
   </session-factory>
</hibernate-configuration>

在上述配置中,将 hibernate.cache.use_second_level_cache 和 hibernate.cache.use_query_cache 都设置为 false,可以关闭一级缓存和查询缓存。

注意:关闭一级缓存可能会导致性能下降和数据不一致等问题,因此在实际应用中需要慎重考虑是否关闭一级缓存。

Hibernate 一级缓存过期

        Hibernate 的一级缓存是 Session 级别的缓存,它存储的是 Session 中查询的实体对象。一级缓存的过期时间是根据缓存中的对象状态和 Session 的状态来判断的。一级缓存的过期包括以下几种情况:

  • 对象状态为持久化状态:当Session中的实体对象状态为持久化状态时,即该对象已经被保存到数据库中并且与数据库中的数据保持一致,那么该对象会一直保留在一级缓存中,直到Session关闭或者显式地从缓存中清除。

  • 对象状态为游离状态:当Session中的实体对象状态为游离状态时,即该对象已经被从Session中分离出来,与数据库中的数据不再保持一致,那么该对象会失效并从一级缓存中移除。

  • 对象状态为脱管状态:当Session中的实体对象状态为脱管状态时,即该对象已经被Session关闭或者从Session中分离出来,那么该对象会失效并从一级缓存中移除。

注意:一级缓存中的对象生命周期与 Session 的生命周期相关联。当 Session 关闭时,所有在一级缓存中的对象都会失效并从缓存中移除。因此,在使用 Hibernate 的过程中,需要根据具体的业务需求和场景来管理缓存,以避免数据的不一致和缓存的内存溢出等问题。

分布式 Hibernate 二级缓存一致性

        在分布式系统中,由于存在多个应用程序实例和多个数据库实例,使用Hibernate的二级缓存可能会导致数据的不一致性问题。为了保持Hibernate的二级缓存一致性,可以采用以下几种方法:

  • 配置缓存同步策略:通过配置缓存同步策略,可以保证多个应用程序实例之间的缓存数据一致性。例如,可以使用JGroups、ZooKeeper等工具来实现缓存同步和协调。

  • 配置缓存失效策略:通过配置缓存失效策略,可以及时使缓存数据失效,避免缓存数据和数据库数据不一致。例如,可以使用时间戳、版本号等方式来实现缓存数据的失效和更新。

  • 选择合适的二级缓存实现:不同的二级缓存实现具有不同的特点和优缺点,需要根据具体的业务需求和场景来选择合适的缓存实现。例如,Ehcache、Redis等缓存工具都是常用的二级缓存实现,它们都具有不同的特点和适用场景。

  • 避免缓存数据过期:在使用Hibernate的二级缓存时,需要注意缓存数据的过期时间,避免缓存数据过期导致数据不一致。需要根据具体的业务需求和场景来设置缓存数据的过期时间,以保证数据的一致性和有效性。

注意:保持 Hibernate 的二级缓存一致性是一个复杂的问题,需要综合考虑多个因素和技术手段。在实际应用中,需要根据具体的业务需求和场景来选择合适的缓存策略和技术,以保证系统的性能和可靠性。

Springboot 接入 Hibernate

  1. maven 依赖
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
  <groupId>org.hibernate</groupId>
  <artifactId>hibernate-core</artifactId>
  <version>${hibernate.version}</version>
</dependency>
  1. yaml 配置
spring.datasource.url=jdbc:mysql://localhost:3306/mydb
spring.datasource.username=root
spring.datasource.password=password
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
  1. 创建 Entity
@Entity
@Table(name = "user")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

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

    @Column(name = "age")
    private int age;

    // getters and setters
}
  1. 创建 Repository
public interface UserRepository extends JpaRepository<User, Long> {
    List<User> findByName(String name);
}
  1. 调用
@Service
public class UserService {
    @Autowired
    private UserRepository userRepository;
    public List<User> findByName(String name) {
        return userRepository.findByName(name);
    }
}
举报

相关推荐

0 条评论