简体   繁体   English

休眠不保存复杂对象

[英]Hibernate not saving complex objects

I have the following object that I would like to save using hibernate: 我有以下要使用休眠保存的对象:

@Entity
@Table(name = "setting")
@JsonInclude(JsonInclude.Include.NON_EMPTY)
public class Setting
{
    @Id
    @Column(name = "id")
    public String internalID;
    @Column(name = "name")
    public String name;
    @Column(name = "type")
    public String type;
    @Column(name = "regex")
    public String regex;

    @OneToMany(fetch = FetchType.EAGER, cascade = {CascadeType.PERSIST, CascadeType.MERGE})
    @JoinTable(name = "setting",
           joinColumns = {@JoinColumn(name = "parent_id")},
           inverseJoinColumns = {@JoinColumn(name = "id")})
    public Collection<Setting> children;

    @JsonIgnore
    @Column(name = "parent_id")
    public String parentID;

    @Column(name = "value")
    public String value;

    public Setting()
    {
        this.internalID = UUID.randomUUID().toString();
    }
}

Hibernate tries to save this, but it seems to fail with the child objects. Hibernate尝试保存此内容,但似乎在子对象失败。 When creating a Setting object that is 3 layers deep, only the first 2 layers are saved and the third one is ignored. 创建3层深的Setting对象时,仅保存前2层,而忽略第3层。

Beside that the second layer is only saving the internalID and parentID, leaving name, type and regex null in the database. 此外,第二层仅保存internalID和parentID,而在数据库中保留name,type和regex null。

save function for the database: 数据库保存功能:

public static void saveObject(Object obj)
{
    if(sessionFactory == null)
        init();
    try(Session session = sessionFactory.openSession())
    {
        session.beginTransaction();
        session.save(obj);
        session.getTransaction().commit();
    }
    catch(Exception e)
    {
        e.printStackTrace();
    }
}

What is it that I am missing? 我想念的是什么? Are the annotations wrong? 注释有误吗?

Steps to reproduce: 重现步骤:

public static void test()
{
    Setting outer = new Setting();
    outer.name = "Outer";
    Setting inner = new Setting();
    inner.name = "Inner";
    outer.children = new ArrayList<>();
    outer.children.add(inner);
    saveObject(outer);
}

public static void saveObject(Object obj)
{
    if(sessionFactory == null)
        initDB();
    try(Session session = sessionFactory.openSession())
    {
        session.beginTransaction();
        session.save(obj);
        session.getTransaction().commit();
    }
    catch(Exception e)
    {
        e.printStackTrace();
    }
}

private static SessionFactory sessionFactory;

private static void initDB()
{
    final StandardServiceRegistry registry = new StandardServiceRegistryBuilder().configure() // configures settings from hibernate.cfg.xml
            .build();
    sessionFactory = new MetadataSources(registry).buildMetadata().buildSessionFactory();
    Runtime.getRuntime().addShutdownHook(new Thread(() ->
    {
        StandardServiceRegistryBuilder.destroy(registry);
    }));
}

with the SQL: 与SQL:

CREATE SCHEMA `cosmos` ;

CREATE TABLE `cosmos`.`setting` (
  `id` VARCHAR(64) NOT NULL,
  `name` VARCHAR(256) NULL,
  `type` VARCHAR(7) NOT NULL,
  `regex` VARCHAR(512) NULL,
  `value` VARCHAR(512) NULL,
  `parent_id` VARCHAR(64) NULL,
  PRIMARY KEY (`id`));

CREATE TABLE `cosmos`.`setting_relation` (
  `id` VARCHAR(64) NOT NULL,
  `parent_id` VARCHAR(64) NULL,
  PRIMARY KEY (`id`));

and the config: 和配置:

<hibernate-configuration>
    <session-factory name="localConnection">
        <property name="hibernate.dialect">
            org.hibernate.dialect.MySQLDialect
        </property>
        <property name="hibernate.connection.driver_class">
            com.mysql.jdbc.Driver
        </property>

        <property
                name="hibernate.connection.url">
            jdbc:mysql://localhost:3306/cosmos?useSSL=false
        </property>
        <property name="hibernate.connection.username">
            root
        </property>
        <property name="hibernate.connection.password">
            ****
        </property>

        <!-- List of XML mapping files -->
        <mapping class="se.mulander.cosmos.settings.model.Setting"/>
    </session-factory>
</hibernate-configuration>

try @JoinTable(name = "setting_some_name" instead of @JoinTable(name = "setting" 尝试@JoinTable(name =“ setting_some_name”而不是@JoinTable(name =“ setting”

@OneToMany(fetch = FetchType.EAGER, cascade = {CascadeType.PERSIST, CascadeType.MERGE})
@JoinTable(name = "setting_some_name",
        joinColumns = {@JoinColumn(name = "parent_id")},
        inverseJoinColumns = {@JoinColumn(name = "id")})
public Collection<Setting> children;

or if you want to do it with self join on same table , do this : 或者,如果您想通过在同一表上进行自我连接来执行此操作,请执行以下操作:

@ManyToOne(optional = true)
@JoinColumn(name = "parent_id")
public Setting parent;

@OneToMany(fetch = FetchType.EAGER, mappedBy = "parent" , cascade = {CascadeType.ALL})
public Collection<Setting> children;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM