Hibernate不保存复杂的对象

时间:2017-07-01 02:20:59

标签: java hibernate

我想使用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试图保存它,但它似乎与子对象失败。 创建3层深的Setting对象时,只保存前2个图层,忽略第3个图层。

除此之外,第二层仅保存internalID和parentID,在数据库中保留name,type和regex null。

保存数据库的功能:

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();
    }
}

我错过了什么? 注释是错误的吗?

重现的步骤:

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);
    }));
}

使用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`));

和配置:

<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>

1 个答案:

答案 0 :(得分:1)

尝试@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;

或者如果你想在同一个表上使用自联接来执行此操作,请执行以下操作:

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

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