Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create rules for migration to Hibernate 5.6 #206

Merged
merged 4 commits into from
Jan 16, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,76 @@
- title: 'Spring 6.0 migration guide'
url: https://github.com/spring-projects/spring-framework/wiki/Spring-Framework-6.0-Release-Notes#removed-apis

- ruleID: spring-framework-5.x-to-6.0-data-access-00002
category: mandatory
effort: 1
labels:
- konveyor.io/source=spring5
- konveyor.io/target=spring6+
- konveyor.io/target=hibernate6+
when:
or:
- builtin.filecontent:
filePattern: .*\.properties
pattern: hibernate.bytecode.provider=javassist
jmle marked this conversation as resolved.
Show resolved Hide resolved
- builtin.xml:
namespaces:
s: http://www.hibernate.org/xsd/hibernate-configuration
xpath: "/hibernate-configuration/session-factory/property[@name='hibernate.bytecode.provider' and text()='javassist']"
- java.referenced:
pattern: org.hibernate.bytecode.javassist*
- builtin.filecontent:
filePattern: .*\.java
pattern: setProperty\(\"hibernate.bytecode.provider\", \"javassist\"\)
description: Javassist no longer supported
message: |
Explicit configuration of `hibernate.bytecode.provider=javassist` has been detected. Javassist is no longer supported by Hibernate 5.6 and later.

The simplest and recommended solution is to remove this property entirely. Hibernate will automatically use Byte Buddy, which is the current default.
links:
- title: 'Hibernate 5.6 migration guide - Javassist removed'
url: https://github.com/hibernate/hibernate-orm/blob/5.6/migration-guide.adoc#javassist-removed

- ruleID: spring-framework-5.x-to-6.0-data-access-00003
category: potential
effort: 5
labels:
- konveyor.io/source=spring5
- konveyor.io/target=spring6+
- konveyor.io/target=hibernate6+
when:
and:
- or: # Check for Hibernate annotations or clob fields
- java.referenced:
location: ANNOTATION
pattern: javax.persistence.Lob
- java.referenced:
location: FIELD
pattern: java.sql.Clob
- or:
- builtin.filecontent:
filePattern: .*\.(java|properties|xml)
pattern: org.hibernate.dialect.PostgreSQL81Dialect
- java.dependency:
lowerbound: 0.0.0
name: org.postgresql.postgresql
description: Changes to the DDL type for CLOB
message: |
Using `@Lob` or `java.sql.Clob` with PostgreSQL 8.1 dialect might require DDL type changes for CLOBs.

Consider reviewing DDL generation for CLOB columns and potential migration to 'oid' type if necessary.
jmle marked this conversation as resolved.
Show resolved Hide resolved

All PostgreSQL JDBC drivers unfortunately just store the oid it created for a `java.sql.Clob` into the text column.
Although reading back the value with the CLOB API works, PostgreSQL has no knowledge of the reference to the LOB,
because the oid is not known to PostgreSQL, leading to data loss when vacuumlo (the utility to clean up unused LOBs) runs.
To avoid the data loss, it is required to use the oid type so that vacuumlo can see the reference.

Updating to 5.6.2 does not require any schema or application changes by default, but we highly recommend that you migrate
existing text columns for LOBs to oid to prevent data loss due to the activity of vacuumlo.
links:
- title: 'Hibernate 5.6 migration guide - Changes to the DDL type for CLOB'
url: https://github.com/hibernate/hibernate-orm/blob/5.6/migration-guide.adoc#changes-to-the-ddl-type-for-clob-in-postgresql81dialect-and-its-subclasses

- ruleID: spring-framework-5.x-to-6.0-data-access-00010
category: mandatory
effort: 3
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,12 @@
<version>8.0.30</version>
</dependency>

<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.5.4</version>
</dependency>

<!-- Logging -->
<dependency>
<groupId>org.slf4j</groupId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package com.example.hibernateclobtest;

import org.hibernate.annotations.DialectOverride;
import org.hibernate.dialect.PostgreSQL81Dialect;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import javax.persistence.*;
import java.sql.Clob;

@SpringBootApplication
public class HibernateClobTestApplication {

public static void main(String[] args) {
SpringApplication.run(HibernateClobTestApplication.class, args);
}
}

@Entity
@DialectOverride.Overrides({
@DialectOverride(dialect = PostgreSQL81Dialect.class, overrides = {
@DialectOverride.Override(sqlType = "TEXT", type = String.class)
})
})
class MyEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Lob
private String largeText;

private Clob clobData;


public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public String getLargeText() {
return largeText;
}

public void setLargeText(String largeText) {
this.largeText = largeText;
}

public Clob getClobData() {
return clobData;
}

public void setClobData(Clob clobData) {
this.clobData = clobData;
}
}

@Repository
interface MyEntityRepository extends JpaRepository<MyEntity, Long> {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package com.example.config;

import org.apache.commons.dbcp2.BasicDataSource; // Or your preferred DataSource
import org.hibernate.SessionFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.orm.hibernate5.HibernateTransactionManager;
import org.springframework.orm.hibernate5.LocalSessionFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.hibernate.bytecode.javassist.FieldHandled;

import javax.sql.DataSource;
import java.util.Properties;

@Configuration
@EnableTransactionManagement // Enable Spring's transaction management
public class HibernateConfig {

@Bean
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionFactoryBean = new LocalSessionFactoryBean();
sessionFactoryBean.setDataSource(dataSource()); // Set the DataSource
sessionFactoryBean.setPackagesToScan("com.example.entity"); // Package containing your entities

Properties properties = new Properties();
properties.setProperty("hibernate.dialect", "org.hibernate.dialect.H2Dialect"); // Database dialect
properties.setProperty("hibernate.bytecode.provider", "javassist"); // Javassist Bytecode provider (For Testing)
properties.setProperty("hibernate.show_sql", "true"); // Show SQL queries in the console (for debugging)
properties.setProperty("hibernate.format_sql", "true"); // Format SQL queries for better readability
//Add other hibernate properties as needed

sessionFactoryBean.setHibernateProperties(properties);

return sessionFactoryBean;
}

@Bean
public DataSource dataSource() {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName("org.h2.Driver");
dataSource.setUrl("jdbc:h2:mem:testdb"); // In-memory H2 database
dataSource.setUsername("sa");
dataSource.setPassword("");
return dataSource;
}

@Bean
public PlatformTransactionManager hibernateTransactionManager() {
HibernateTransactionManager transactionManager = new HibernateTransactionManager();
transactionManager.setSessionFactory(sessionFactory().getObject());
return transactionManager;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQL81Dialect
spring.datasource.url=jdbc:postgresql://localhost:5432/your_database
spring.datasource.driver-class-name=org.postgresql.Driver
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.cache.provider_class">org.hibernate.cache.EHCacheProvider</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
<property name="connection.pool_size">10</property>
<property name="show_sql">false</property>
<property name="hibernate.bytecode.provider">javassist</property>
</session-factory>
</hibernate-configuration>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
hibernate.bytecode.provider=javassist
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,20 @@ tests:
mode: "source-only"
hasIncidents:
exactly: 1
- ruleID: spring-framework-5.x-to-6.0-data-access-00002
testCases:
- name: tc-1
analysisParams:
mode: "source-only"
hasIncidents:
exactly: 4
- ruleID: spring-framework-5.x-to-6.0-data-access-00003
testCases:
- name: tc-1
analysisParams:
mode: "source-only"
hasIncidents:
exactly: 5
- ruleID: spring-framework-5.x-to-6.0-data-access-00010
testCases:
- name: tc-1
Expand Down
Loading