首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何在JPA中持久化List<String>类型的属性?

如何在JPA中持久化List<String>类型的属性?
EN

Stack Overflow用户
提问于 2008-11-13 23:15:24
回答 8查看 308.9K关注 0票数 188

要持久化类型为List的字段的实体,最聪明的方法是什么?

Command.java

package persistlistofstring;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.Basic;
import javax.persistence.Entity;
import javax.persistence.EntityManager;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Persistence;

@Entity
public class Command implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    Long id;
    @Basic
    List<String> arguments = new ArrayList<String>();

    public static void main(String[] args) {
        Command command = new Command();

        EntityManager em = Persistence
                .createEntityManagerFactory("pu")
                .createEntityManager();
        em.getTransaction().begin();
        em.persist(command);
        em.getTransaction().commit();
        em.close();

        System.out.println("Persisted with id=" + command.id);
    }
}

这段代码产生:

> Exception in thread "main" javax.persistence.PersistenceException: No Persistence provider for EntityManager named pu: Provider named oracle.toplink.essentials.PersistenceProvider threw unexpected exception at create EntityManagerFactory: 
> oracle.toplink.essentials.exceptions.PersistenceUnitLoadingException
> Local Exception Stack: 
> Exception [TOPLINK-30005] (Oracle TopLink Essentials - 2.0.1 (Build b09d-fcs (12/06/2007))): oracle.toplink.essentials.exceptions.PersistenceUnitLoadingException
> Exception Description: An exception was thrown while searching for persistence archives with ClassLoader: sun.misc.Launcher$AppClassLoader@11b86e7
> Internal Exception: javax.persistence.PersistenceException: Exception [TOPLINK-28018] (Oracle TopLink Essentials - 2.0.1 (Build b09d-fcs (12/06/2007))): oracle.toplink.essentials.exceptions.EntityManagerSetupException
> Exception Description: predeploy for PersistenceUnit [pu] failed.
> Internal Exception: Exception [TOPLINK-7155] (Oracle TopLink Essentials - 2.0.1 (Build b09d-fcs (12/06/2007))): oracle.toplink.essentials.exceptions.ValidationException
> Exception Description: The type [interface java.util.List] for the attribute [arguments] on the entity class [class persistlistofstring.Command] is not a valid type for a serialized mapping. The attribute type must implement the Serializable interface.
>         at oracle.toplink.essentials.exceptions.PersistenceUnitLoadingException.exceptionSearchingForPersistenceResources(PersistenceUnitLoadingException.java:143)
>         at oracle.toplink.essentials.ejb.cmp3.EntityManagerFactoryProvider.createEntityManagerFactory(EntityManagerFactoryProvider.java:169)
>         at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:110)
>         at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:83)
>         at persistlistofstring.Command.main(Command.java:30)
> Caused by: 
> ...
EN

回答 8

Stack Overflow用户

发布于 2018-05-21 19:43:36

如果有人正在寻找另一种解决方案,将字符串列表作为一个字段存储在数据库中,下面是我解决这个问题的方法。创建一个转换器,如下所示:

import java.util.Arrays;
import java.util.List;

import javax.persistence.AttributeConverter;
import javax.persistence.Converter;

import static java.util.Collections.*;

@Converter
public class StringListConverter implements AttributeConverter<List<String>, String> {
    private static final String SPLIT_CHAR = ";";
    
    @Override
    public String convertToDatabaseColumn(List<String> stringList) {
        return stringList != null ? String.join(SPLIT_CHAR, stringList) : "";
    }

    @Override
    public List<String> convertToEntityAttribute(String string) {
        return string != null ? Arrays.asList(string.split(SPLIT_CHAR)) : emptyList();
    }
}

现在像这样在你的实体上使用它:

@Convert(converter = StringListConverter.class)
private List<String> yourList;

在数据库中,您的列表将被存储为foo;bar;foobar,并且在您的Java对象中,您将获得一个包含这些字符串的列表。

票数 82
EN

Stack Overflow用户

发布于 2008-11-13 15:34:47

这个答案是在JPA2实现之前做出的,如果你使用的是JPA2,请参阅上面的ElementCollection答案:

模型对象中的对象列表通常被认为是与另一个对象的"OneToMany“关系。但是,字符串(本身)不是一对多关系的允许客户端,因为它没有ID。

因此,您应该将String列表转换为包含ID和String的参数类JPA对象列表。

或者,您可以将列表转换为@瞬态,并向您的类添加另一个字段(argStorage),该字段可以是VARCHAR()或CLOB。然后需要添加3个函数:其中2个函数相同,应该将字符串列表转换为单个字符串(在argStorage中),以便于分隔。用@PrePersist和@PreUpdate注释这两个函数(每个函数做同样的事情)。最后,添加第三个函数,该函数将argStorage再次拆分为字符串列表,并将其注释为@PostLoad。这将使您的CLOB在您存储命令时使用字符串进行更新,并在您将其存储到数据库之前保持argStorage字段的更新。

我仍然建议做第一种情况。这是以后建立真正的关系的很好的实践。

票数 32
EN

Stack Overflow用户

发布于 2017-08-09 00:58:50

我们也可以使用这个。

@Column(name="arguments")
@ElementCollection(targetClass=String.class)
private List<String> arguments;
票数 16
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/287201

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档