# Quarkus Panache: Simplificando el Acceso a Datos

## **Introducción**

Quarkus Panache es una extensión que simplifica el acceso a datos con Hibernate ORM. Proporciona dos patrones de programación que reducen significativamente el código boilerplate necesario para operaciones de base de datos.

## **¿Qué es Panache?**

Panache es una capa de abstracción sobre Hibernate ORM que proporciona:

* Métodos mágicos para queries comunes
    
* Dos patrones de programación (Repository y Active Record)
    
* API simplificada para operaciones CRUD
    
* Menos código boilerplate
    

## **Dos Patrones de Panache**

### **1\. Repository Pattern**

Similar a Spring Data, donde las entidades son POJOs simples y la lógica de acceso a datos está en repositorios:

```go
@Entity
public class Hero extends PanacheEntityBase {
    @Id
    @GeneratedValue
    private Long id;
    
    private String name;
    private Integer powerLevel;
    
    // Getters y setters
}

@ApplicationScoped
public class HeroRepository implements PanacheRepository<Hero> {
    // Métodos personalizados
    public List<Hero> findPowerfulHeroes() {
        return find("powerLevel >= ?1", 80).list();
    }
}
```

**Ventajas:**

* Separación clara entre entidad y lógica de acceso a datos
    
* Fácil de testear (puedes mockear el repositorio)
    
* Mejor para lógica compleja
    
* Similar a Spring Data (familiar para muchos desarrolladores)
    

### **2\. Active Record Pattern**

Donde las entidades extienden `PanacheEntity` y tienen métodos directamente:

```go
@Entity
public class Villain extends PanacheEntity {
    public String name;
    public Integer powerLevel;
    
    // Métodos de instancia
    public static List<Villain> findPowerful() {
        return find("powerLevel >= ?1", 80).list();
    }
}
```

**Ventajas:**

* Más simple y directo
    
* Menos clases (no necesitas repositorio)
    
* Ideal para operaciones CRUD básicas
    
* Código más compacto
    

## **Operaciones Comunes**

### **Buscar**

```go
// Repository Pattern
heroRepository.findById(id);
heroRepository.find("name", "Superman");
heroRepository.find("powerLevel >= ?1", 80).list();

// Active Record Pattern
Villain.findById(id);
Villain.find("name", "Joker");
Villain.find("powerLevel >= ?1", 80).list();
```

### **Crear**

```go
// Repository Pattern
Hero hero = new Hero();
hero.setName("Superman");
hero.setPowerLevel(95);
heroRepository.persist(hero);

// Active Record Pattern
Villain villain = new Villain();
villain.name = "Joker";
villain.powerLevel = 80;
villain.persist();
```

### **Actualizar**

```go
// Repository Pattern
Hero hero = heroRepository.findById(id);
hero.setPowerLevel(98);
// Los cambios se persisten automáticamente en managed entities

// Active Record Pattern
Villain villain = Villain.findById(id);
villain.powerLevel = 85;
// Los cambios se persisten automáticamente
```

### **Eliminar**

```go
// Repository Pattern
heroRepository.deleteById(id);
heroRepository.delete(hero);

// Active Record Pattern
Villain.deleteById(id);
villain.delete();
```

## **Métodos Mágicos**

Panache proporciona métodos que se generan automáticamente basándose en el nombre:

```go
// Estos métodos se generan automáticamente:
findById(id)
find("field", value)
find("field = ?1", value)
find("field1 = ?1 and field2 = ?2", value1, value2)
list()
listAll()
count()
count("field = ?1", value)
delete("field = ?1", value)
update("field = ?1 where id = ?2", newValue, id)
```

## **Queries con Panache Query API**

### **Queries Simples**

```go
// Por campo
find("name", "Superman")

// Con operador
find("powerLevel >= ?1", 80)

// Con múltiples condiciones
find("powerLevel >= ?1 and isActive = ?2", 80, true)

// Con ORDER BY
find("powerLevel >= ?1 order by powerLevel desc", 80)

// Con named parameters
find("powerLevel >= :minLevel", Parameters.with("minLevel", 80))
```

### **Paginación**

```go
// Primera página (10 items)
find("powerLevel >= ?1", 80).page(0, 10)

// Segunda página
find("powerLevel >= ?1", 80).page(1, 10)

// Navegar
PanacheQuery<Hero> query = find("powerLevel >= ?1", 80);
Page<Hero> firstPage = query.page(0, 10);
Page<Hero> secondPage = query.page(1, 10);
```

### **Proyecciones**

```go
// Seleccionar campos específicos
find("select name, powerLevel from Hero where powerLevel >= ?1", 80)
```

## **Comparación de Patrones**

| **Característica** | **Repository Pattern** | **Active Record Pattern** |
| --- | --- | --- |
| Separación de responsabilidades | ✅ Alta | ⚠️ Media |
| Testabilidad | ✅ Fácil de mockear | ⚠️ Más difícil |
| Simplicidad | ⚠️ Más clases | ✅ Menos código |
| Lógica compleja | ✅ Mejor | ⚠️ Puede ser confuso |
| Operaciones CRUD básicas | ✅ Bueno | ✅ Excelente |
| Familiaridad | ✅ Similar a Spring Data | ⚠️ Menos común |

## **Ejemplo Completo: Repository Pattern**

```go
@Entity
public class Hero extends PanacheEntityBase {
    @Id
    @GeneratedValue
    private Long id;
    
    private String name;
    private Integer powerLevel;
    private Boolean isActive = true;
    
    // Getters y setters
}

@ApplicationScoped
public class HeroRepository implements PanacheRepository<Hero> {
    
    public List<Hero> findPowerfulHeroes(int minLevel) {
        return find("powerLevel >= ?1 order by powerLevel desc", minLevel).list();
    }
    
    public List<Hero> findActiveHeroes() {
        return find("isActive = true").list();
    }
    
    public Page<Hero> findHeroesPaginated(int page, int size) {
        return findAll().page(page, size);
    }
    
    public long countPowerful(int minLevel) {
        return count("powerLevel >= ?1", minLevel);
    }
}
```

## **Ejemplo Completo: Active Record Pattern**

```go
@Entity
public class Villain extends PanacheEntity {
    public String name;
    public Integer powerLevel;
    public Boolean isActive = true;
    
    // Métodos estáticos para queries
    public static List<Villain> findPowerful(int minLevel) {
        return find("powerLevel >= ?1 order by powerLevel desc", minLevel).list();
    }
    
    public static List<Villain> findActive() {
        return find("isActive = true").list();
    }
    
    // Métodos de instancia
    public void activate() {
        this.isActive = true;
        persist(); // O simplemente modificar si está managed
    }
    
    public void deactivate() {
        this.isActive = false;
        persist();
    }
}
```

## **Cuándo Usar Cada Patrón**

### **Usa Repository Pattern cuando:**

* Necesitas separación clara de responsabilidades
    
* Tienes lógica de acceso a datos compleja
    
* Quieres fácil testabilidad
    
* Trabajas en equipo grande (mejor organización)
    

### **Usa Active Record Pattern cuando:**

* Tienes operaciones CRUD simples
    
* Quieres menos código
    
* Trabajas en proyectos pequeños
    
* Prefieres simplicidad sobre organización
    

## **Ventajas de Panache**

1. **Menos Código**: Reduce significativamente el boilerplate
    
2. **Métodos Mágicos**: Generación automática de métodos comunes
    
3. **Type-Safe**: Queries type-safe con validación en tiempo de compilación
    
4. **Flexible**: Puedes usar ambos patrones en el mismo proyecto
    
5. **Performance**: Optimizado para Quarkus
    

## **Integración con JPA**

Panache está construido sobre Hibernate ORM, por lo que:

* Todas las características de JPA están disponibles
    
* Puedes usar JPQL cuando necesites
    
* Las relaciones funcionan igual
    
* Los lifecycle callbacks funcionan
    

## **Ejemplo Completo**

Nuestro demo muestra:

* Repository Pattern completo con HeroRepository
    
* Active Record Pattern completo con VillainEntity
    
* Comparación de ambos patrones
    
* Queries complejas con Panache Query API
    
* Paginación y proyecciones
    

## **Conclusión**

Quarkus Panache simplifica enormemente el acceso a datos. Tanto el Repository Pattern como el Active Record Pattern tienen sus ventajas, y puedes elegir el que mejor se adapte a tu proyecto o usar ambos según necesites.

## **Recursos**

* [Demo completo](file:///Users/josediaz/Projects/JoeDayz/jakartaee-2026/quarkus-demos/panache/)
    
* [Quarkus Panache Guide](https://quarkus.io/guides/hibernate-orm-panache)
    
* [Panache Repository Pattern](https://quarkus.io/guides/hibernate-orm-panache#repository-pattern)
    
* [Panache Active Record Pattern](https://quarkus.io/guides/hibernate-orm-panache#active-record-pattern)
