我第一次尝试在Hibernate中进行多对一关联映射。我有2个POJO类-Employee和Address-它们之间的关联是一个Address对象可以与多个Employee对象关联。
我的程序从未编译过,它始终总是卡在堆栈跟踪中-
Jun 25, 2020 12:41:09 AM org.hibernate.Version logVersion
INFO: HHH000412: Hibernate Core {5.3.1.Final}
Jun 25, 2020 12:41:09 AM org.hibernate.cfg.Environment <clinit>
INFO: HHH000206: hibernate.properties not found
Jun 25, 2020 12:41:09 AM org.hibernate.spatial.integration.SpatialService <init>
INFO: HHH80000001: hibernate-spatial integration enabled : true
Jun 25, 2020 12:41:09 AM org.hibernate.annotations.common.reflection.java.JavaReflectionManager <clinit>
INFO: HCANN000001: Hibernate Commons Annotations {5.0.3.Final}
Jun 25, 2020 12:41:10 AM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl configure
WARN: HHH10001002: Using Hibernate built-in connection pool (not for production use!)
Jun 25, 2020 12:41:10 AM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001005: using driver [com.mysql.jdbc.Driver] at URL [jdbc:mysql://localhost/hibernatedb2]
Jun 25, 2020 12:41:10 AM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001001: Connection properties: {user=root}
Jun 25, 2020 12:41:10 AM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001003: Autocommit mode: false
Jun 25, 2020 12:41:10 AM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl$PooledConnections <init>
INFO: HHH000115: Hibernate connection pool size: 20 (min=1)
Jun 25, 2020 12:41:10 AM org.hibernate.dialect.Dialect <init>
INFO: HHH000400: Using dialect: org.hibernate.dialect.MySQL5Dialect
Jun 25, 2020 12:41:10 AM org.hibernate.envers.boot.internal.EnversServiceImpl configure
INFO: Envers integration enabled? : true
Jun 25, 2020 12:41:11 AM org.hibernate.resource.transaction.backend.jdbc.internal.DdlTransactionIsolatorNonJtaImpl getIsolatedConnection
INFO: HHH10001501: Connection obtained from JdbcConnectionAccess [org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess@7a18e8d] for (non-JTA) DDL execution was not in auto-commit mode; the Connection 'local transaction' will be committed and the Connection will be set into auto-commit mode.
Jun 25, 2020 12:41:11 AM org.hibernate.hql.internal.QueryTranslatorFactoryInitiator initiateService
INFO: HHH000397: Using ASTQueryTranslatorFactory
Jun 25, 2020 12:41:11 AM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl stop
INFO: HHH10001008: Cleaning up connection pool [jdbc:mysql://localhost/hibernatedb2]
Address.java-
package firsthb;
public class Address {
private int id;
private String street, city, state;
//getters and setters
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
}
Employee.java-
package firsthb;
public class Employee {
private int id;
private String firstName, lastName;
private Address address;
//getters and setters
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
}
employee.hbm.xml(休眠映射文件)-
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "<a class='vglnk' href='http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd' rel='nofollow'><span>http</span><span>://</span><span>hibernate</span><span>.</span><span>sourceforge</span><span>.</span><span>net</span><span>/</span><span>hibernate</span><span>-</span><span>mapping</span><span>-</span><span>3</span><span>.</span><span>0</span><span>.</span><span>dtd</span></a>">
<hibernate-mapping>
<class name="firsthb.Employee" table="EMP">
<meta attribute="class-description">
This class contains employees' details
</meta>
<id column="ID" name="id" type="int">
<generator class="native" />
</id>
<property column="FIRST_NAME" name="firstName" type="string"/>
<property column="LAST_NAME" name="lastName" type="string"/>
<many-to-one name="address" column="address" class="firsthb.Address" not-null="true"/>
<!-- Attributes in <many-to-one> tag -
1. name: data member in parent class
2. column: column name in parent table -->
</class>
<class name="firsthb.Address" table="ADDRESS">
<meta attribute="class-description">
This class contains the addresses of employees
</meta>
<id name="id" column="ID" type="int">
<generator class="native"/>
</id>
<property name="street" column="street_name" type="string"/>
<property name="city" column="city_name" type="string"/>
<property name="state" column="state_name" type="string"/>
</class>
</hibernate-mapping>
hibernate.cfg.xml(休眠配置文件)-
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 5.3//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-5.3.dtd">
<hibernate-configuration>
<session-factory>
<property name="hbm2ddl.auto">update</property>
<property name="dialect">org.hibernate.dialect.MySQL5Dialect</property>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost/hibernatedb2</property>
<property name="connection.username">root</property>
<mapping resource="employee.hbm.xml"/>
</session-factory>
</hibernate-configuration>
最后,我实现多对一关联功能的文件-
package firsthb;
import java.util.ArrayList;
import java.util.List;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration; //new - so that line 24 works, and StandardServiceRegistry + metadata initialization can be avoided
/*
import org.hibernate.boot.Metadata;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
*/
@SuppressWarnings({"deprecation", "unchecked"})
public class FunctionalityImplementer {
private static SessionFactory factory;
public static void main(String[] args) {
factory = new Configuration().configure().buildSessionFactory();
FunctionalityImplementer fi = new FunctionalityImplementer();
Address addr1 = fi.addAddress("E-85, DDA Flats", "New Delhi", "Delhi");
Employee emp1 = fi.addEmployee("Vikramaditya", "Bhatnagar", addr1);
Employee emp2 = fi.addEmployee("Yashaswani", "Bhatnagar", addr1);
fi.listEmployees();
//Address addr1 = ME.add
//System.out.println("Successfully saved");
factory.close();
}
public Address addAddress(String street, String city, String state) {
//StandardServiceRegistry ssr = new StandardServiceRegistryBuilder().configure("hibernate.cfg.xml").build();
//Metadata meta = new MetadataSources(ssr).getMetadataBuilder().build();
//factory = meta.getSessionFactoryBuilder().build();
Session session = factory.openSession();
Transaction t = session.beginTransaction();
Address a = new Address(); //better programming practice would be to use a parameterized constructor instead of individual setters
a.setStreet(street);
a.setCity(city);
a.setState(state);
t.commit();
session.close();
return a;
}
public Employee addEmployee(String firstName, String lastName, Address address) {
Session session = factory.openSession();
Transaction t = session.beginTransaction();
Employee e = new Employee(); //better programming practice would be to use a parameterized constructor instead of individual setters
e.setFirstName(firstName);
e.setLastName(lastName);
e.setAddress(address);
t.commit();
session.close();
return e;
}
public void listEmployees() {
Session session = factory.openSession();
Transaction t = session.beginTransaction();
List<Employee> elist = new ArrayList<>();
Query<Employee> query = session.createQuery("From Employee");
elist = (ArrayList<Employee>)query.list();
for(Employee loopctr : elist) {
System.out.println("EMPLOYEE DETAILS -");
System.out.println(loopctr.getId() + "\t" + loopctr.getFirstName() + "\t" + loopctr.getLastName());
System.out.println("ADDRESS DETAILS -");
Address addr = loopctr.getAddress();
System.out.println(addr.getStreet() + "\t" + addr.getCity() + "\t" + addr.getState());
}
t.commit();
session.close();
}
}
我在某处读到,如果您要在整个程序中创建多个SessionFactory
对象,则这样的程序可能要花很长时间才能编译(因为SessionFactory对象的大小很大)。但是,这里不是这种情况,因为我已经创建了一个具有整个 FunctionalityImplementer 类范围的单个SessionFactory对象,并且在进行过程中创建了多个Session对象(据我所知,很好,因为它们的尺寸较小。
请注意,在这一点上,表是在MySQL控制台中创建的(编译开始时,RDBMS中不存在表)-
describe emp;
+------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+----------------+
| ID | int(11) | NO | PRI | NULL | auto_increment |
| FIRST_NAME | varchar(255) | YES | | NULL | |
| LAST_NAME | varchar(255) | YES | | NULL | |
| address | int(11) | NO | MUL | NULL | |
+------------+--------------+------+-----+---------+----------------+
4 rows in set (0.30 sec)
mysql> desc address;
+-------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+--------------+------+-----+---------+----------------+
| ID | int(11) | NO | PRI | NULL | auto_increment |
| street_name | varchar(255) | YES | | NULL | |
| city_name | varchar(255) | YES | | NULL | |
| state_name | varchar(255) | YES | | NULL | |
+-------------+--------------+------+-----+---------+----------------+
4 rows in set (0.03 sec)
答案 0 :(得分:0)
找到了答案!很简单,我忘了添加
session.save(a);
和session.save(em);
在两个数据添加函数中的t.commit();
语句之前。
从那以后像魅力一样工作!