我想使用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>
答案 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;