0

JPA, Spring and Kotlin: store a list or an array in a column of the database

 1 month ago
source link: https://marco.dev/java-jpa-arrays
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

JPA, Spring and Kotlin: store a list or an array in a column of the database

Updated: 2024-03-26

In some use cases could be useful to store a list of values in a column and not a relationship @OneToMany

This has to be considered an anti-pattern and should be applied only in specific cases.

Storing an array in a database column can have many negative consequences:

  • the database cannot validate the values
  • the column could be wrongly sized for the future amount of data stored

The advantages of storing a list / array of data in a column are:

  • the ORM and the database require to manage one relationship less
  • the query of one table should be more efficient that the query of a 1 to many relationship

Example with Kotlin

For our example we will use Kotlin, if you are a Java developer it should be easily understandable.

Converting a CSV String in a Set and the other way around

You need to use the @Converter feature of JPA:

@Converter 
class StringSetColumnConverter : AttributeConverter<Set<String>, String> { 
 
private val delimiter = "," 
 
override fun convertToDatabaseColumn(attribute: Set<String>?): String? { 
return attribute?.joinToString(delimiter) 
} 
 
override fun convertToEntityAttribute(dbData: String?): Set<String> { 
return dbData?.split(delimiter)?.toSet() ?: emptySet() 
} 

Create unit tests

The test show how easy is to use them and the expected result:

class StringSetColumConverterTest { 
private val stringSetColumnConverter = StringSetColumnConverter() 
 
@Test 
fun concertSetToColumnString() { 
assertEquals("abd,def", stringSetColumnConverter.convertToDatabaseColumn(setOf("abc","def"))) 
} 
 
@Test 
fun convertStringColumnToSet() { 
assertEquals(setOf("abc", "def"), stringSetColumnConverter.convertToEntityAttribute("abc,def")) 
} 
} 

The @Entity declaration

The @Entity that requires the conversion can be declared:

@Entity 
@Table(name = "MyTable") 
class MyTable( 
@Id 
val id: Long, 
@Convert(converter = StringSetColumnConverter::class) 
val words: Set<String>? 
) 

You table can simply use a Varchar field.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK