I'm trying to get a simple mapping done but I am having issues.
Basically what I have in Mysql is a User table with just one column that is a varchar(255) named Username that is the primary key.
I have one other table called notes which has a primary auto-generating key that is an int, a date column, varchar name and contents columns and a varchar(255) called owner which should contain a user's username.
This is tagged as a foreign key referencing Users (Username).
The code to get the session factory is this:
private static SessionFactory createSessionFactory() {
SessionFactory sessionFactory;
Configuration configuration = new Configuration();
configuration.configure("hibernate.cfg.xml");
configuration.addAnnotatedClass(Note.class);
configuration.addAnnotatedClass(User.class);
StandardServiceRegistry serviceRegistry = new
StandardServiceRegistryBuilder().applySettings(
configuration.getProperties()).build();
sessionFactory = configuration.buildSessionFactory(serviceRegistry);
return sessionFactory;
}
This works fine without the line that adds the annotated class 'Note' so it is probably an issue with that class. The error is this:
Could not get constructor for
org.hibernate.persister.entity.SingleTableEntityPersister
org.hibernate.MappingException
Full stacktrace:
Full classes are available here:
Note
User
Test
UPDATE: fixed Owner/OwnerName variable misnaming however I now get this error: ERROR:
Cannot add or update a child row: a foreign key constraint fails
(notes.notes, CONSTRAINT notes_ibfk_1 FOREIGN KEY (Owner)
REFERENCES users (username))
Stacktrace.
The issue is in the Note class.
For the variable owner, setter method name is not proper.
Instead of
public void setOwnerName(String u) {
this.owner = u;
}
It should be
public void setOwner(String u) {
this.owner = u;
}
This should resolve the issue.
you should first save user then save note in your test class.
your code should be like this.
#Test
public void testSave() {
Session session = factory.openSession();
Date date = Date.valueOf(LocalDate.now());
User user = new User("Joseph");
Note note = new Note();
note.setName("Joseph's note");
note.setContents("blah blah blah");
note.setOwnerName("Joseph");
session.beginTransaction();
session.save(user);
session.save(note);
session.getTransaction().commit();
session.close();
System.out.println(date);
}
but with this code, you just have foreign key in database and you don't have relation in your code.
your note enttiy can be like below code.
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "username")
public String getOwner() {
return owner;
}
finally your test class can be like :
#Test
public void testSave() {
Session session = factory.openSession();
Date date = Date.valueOf(LocalDate.now());
User user = new User("Joseph");
Note note = new Note();
note.setName("Joseph's note");
note.setContents("blah blah blah");
note.setOwner(user);
session.beginTransaction();
session.save(user);
session.save(note);
session.getTransaction().commit();
session.close();
System.out.println(date);
}
Related
I am making an application with users. A user has an id, which is automatically assigned using the following Hibernate annotation:
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id
That is all fine and dandy, however the problem is that every time I run the application (while adding the same user) it assigns a new id to the user, regardless if the user already exists.
What can I do that makes it so an existing user doesn't get a new id every time I run the application without having to request all users to check their username individually?
Thanks in advance.
EDIT
Some more code examples (I will only write relevant code here).
The User:
#Entity
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String username;
// more code here
}
The User hibernate class with the save function:
(The session is opened in Main and given to the constructor).
public class UserDAOHibernate implements GebruikerDAO {
private Session session;
public UserDAOHibernate(Session session) {
this.session = session;
}
#Override
public boolean save(User user) {
try {
if (this.findById(user.getId()) == null) {
Transaction transaction = session.beginTransaction();
session.save(user);
transaction.commit();
return true;
}
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
// more code here
}
The above code where I check if the user already exists based on the id doesn't work because of the fact that the user keeps getting new ids. So this function checks if there exists a user with id = 2, while the one that already exists has id = 1.
In Main:
// lots of code
User user = new User("Stijuh");
// more code here
UserDAOHibernate udao = new UserDAOHibernate(session);
udao.save(user);
When you want to update, before saving the object, you have to set the id field. This way Hibernate will not generate a new one
I'm new to Hibernate. I want to insert data into this hibernate entity:
#Entity
public class Invitation implements Serializable
{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "invited_on")
#Temporal(TemporalType.TIMESTAMP)
private Date invitedOn;
#Column(name = "invited_email")
private String invitedEmail;
#Column(name = "invitation_msg")
private String invitationMessage;
private Boolean status; //true:accepted || false:pending
#ManyToOne
#JoinColumn(name = "sent_by")
private Person inviter;
// getters and setters
}
I tested this code:
public void insert()
{
Query query = session.createQuery("insert into Invitation(invited_on, invited_email, invitation_msg, sent_by)");
int result = query.executeUpdate();
}
What is the proper way to insert data? How I should create session Object?
use this in the main class it works to insert data into table:
Users user = new Users();
user.setUid(1);
user.setUfname("firstname");
user.setUlname("Lastname");
Configuration config = new Configuration()
.configure()
.addAnnotatedClass(Users.class);
ServiceRegistry reg = new ServiceRegistryBuilder()
.applySettings(config.getProperties())
.buildServiceRegistry();
SessionFactory sf = config.buildSessionFactory(reg);
Session session = sf.openSession();
Transaction tx = session.beginTransaction();
session.save(user);
tx.commit();
You have Hibernate and it's tools USE THEM!!!
DISCLAIMER:
Example took from HERE
code written on the fly!!
I didnt use status attribute because is not mapped!
// don't need if you already got a session
Session session = HibernateUtil.getSessionFactory().openSession();
// start transaction
session.beginTransaction();
// create invitation Object
Invitation inv = new Invitation();
inv.setId(1L);
inv.setInvitedOn(new java.util.Date());
inv.setInvitedEmail("yo#yo.com");
inv.setInvitationMessage("come on!!!");
inv.setInviter(new Person("inviter")); // hey! this is not valid for sure! :)
// Save the invitation to database
session.save(inv);
// Commit the transaction
session.getTransaction().commit();
I have a problem.
I get error in my app: org.hibernate.id.IdentifierGenerationException: attempted to assign id from null one-to-one property
My pojos
User:
#Entity
#Table(name = "user")
#Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class User implements Serializable {
private static final long serialVersionUID = -5415891222321582213L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "userId", length = 100)
private int userId;
...
#OneToOne(mappedBy = "user", cascade = CascadeType.ALL)
private UserDetail userDetail;
UserDetail:
#Entity
#Table(name = "userdetail")
#Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class UserDetail implements Serializable {
private static final long serialVersionUID = 2155190440305692224L;
#Id
#GenericGenerator(
name = "gen",
strategy = "foreign",
parameters = #Parameter(name = "property", value = "user")
)
#GeneratedValue(generator = "gen")
#Column(name = "userId", length = 100)
private int userId;
...
#OneToOne
#PrimaryKeyJoinColumn
private User user;
Table User:
CREATE TABLE `user` (
`userId` INT(100) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(255) NULL DEFAULT NULL,
`surname` VARCHAR(255) NULL DEFAULT NULL,
`email` VARCHAR(255) NULL DEFAULT NULL,
`password` VARCHAR(255) NULL DEFAULT NULL,
PRIMARY KEY (`userId`)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
;
Table UserDetail
CREATE TABLE `userdetail` (
`userId` INT(100) NOT NULL,
`country` VARCHAR(255) NULL DEFAULT NULL,
`city` VARCHAR(255) NULL DEFAULT NULL,
`address` VARCHAR(255) NULL DEFAULT NULL,
PRIMARY KEY (`userId`)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
;
DAO Layer:
private Session session = HibernateUtil.getHibernateUtil().getSession();
#Override
public void create(T t) throws DaoException {
Object object = session.merge(t);
session.save(object);
log.info("Update: " + t);
}
Service Layer
private Session session = HibernateUtil.getHibernateUtil().getSession();
private Transaction transaction = null;
private Dao<T> dao = new BaseDao<T>();
#Override
public void create(T t) throws DaoException {
try {
transaction = session.beginTransaction();
dao.create(t);
transaction.commit();
log.info("Create: " + t);
} catch (HibernateException e) {
log.error("Error creating " + getPersistentClass() + " in Dao " + e);
transaction.rollback();
throw new DaoException(e);
}
}
Class with saving User
User user = new User(name, surname, email, password);
UserDetail userDetail = new UserDetail(country, city, address);
user.setUserDetail(userDetail);
userDetail.setUser(user);
userService.create(user);
HiberUtil
public class HibernateUtil {
private static Logger log = Logger.getLogger(HibernateUtil.class);
private static HibernateUtil util = null;
private static SessionFactory sessionFactory = null;
private static final ThreadLocal<Session> sessions = new ThreadLocal<Session>();
private HibernateUtil() {
try {
Configuration configuration = new Configuration().configure("hibernate.cfg.xml");
log.info("Hibernate Configuration loaded");
ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build();
log.info("Hibernate serviceRegistry created");
sessionFactory = configuration.buildSessionFactory(serviceRegistry);
} catch (Throwable e) {
log.error("Initial SessionFactory creation failed. " + e);
System.exit(0);
}
}
public Session getSession () {
Session session = sessions.get();
if (session == null) {
session = sessionFactory.openSession();
sessions.set(session);
}
return session;
}
public static synchronized HibernateUtil getHibernateUtil(){
if (util == null){
util = new HibernateUtil();
}
return util;
}
}
If i change in DAO layer:
#Override
public void create(T t) throws DaoException {
session.save(t);
log.info("Create: " + t);
}
I get error: org.hibernate.HibernateException: Illegal attempt to associate a collection with two open sessions
So I have 4 questions:
If I understood correctly, when userdeteil save userId from User is null because UserId don't get icnrement Id from Table, it's true?
Needed session.merge here or not
If merge is needed, how correct org.hibernate.id.IdentifierGenerationException: attempted to assign id from null one-to-one property
If merge is no needed, how correct "org.hibernate.HibernateException: Illegal attempt to associate a collection with two open sessions"
Note: Delet with merge is good, create with merge other Entity (not User and not UserDeteil) is good.
To get it work, remove Object object = session.merge(t); from update method of your DAO class. Here is updated update method
#Override
public void update(T t) throws DaoException {
session.saveOrUpdate(t);
log.info("Update: " + t);
}
This will fix your org.hibernate.id.IdentifierGenerationException exception.
For point 1: Your record was not saved, you were calling merge()
method, then the object return by merge method is passed in
save(here). merger(): Copy the state of the given object onto the
persistent object with the same identifier. In your case no
persistent object.
For point 2: No merge method is not required here, use save or
saveOrUpdate method with session
For point 3: N/A
Here is a good example of One-To-One association mapping
I solved my poroblem.
In my BaseDao and BaseService I removed:
private Session session = HibernateUtil.getHibernateUtil().getSession();
And I added in all methods in BaseDao and BaseService:
HibernateUtil.getHibernateUtil().getSession();
so I removed the two sessions
and my method, example create, became:
#Override
public void create(T t) throws DaoException {
HibernateUtil.getHibernateUtil().getSession().save(t);
log.info("Create: " + t);
}
Here is my Entity class
#Entity // Model Class as a DB entity
public class UserDetails
{
#Id
private int userId;
private String name;
#ElementCollection
private Set<Address> listOfAddresses = new HashSet();
// Setters and Getters Below
}
Here is my Address Class
#Embeddable
public class Address
{
private String Street;
private String City;
private String State;
private String PinCode;
// Setters and Getters Below
}
Am using a standalone Java Class to try and insert into my MySQL database. Since, am new to Hibernate I just want to use this annotation and not the relations for now.
My standalone Java class named HibernateTest.java
public class HibernateTest
{
public static void main(String[] args)
{
UserDetails user = new UserDetails();
Address addr = new Address();
user.setUserId(1);
user.setName("Swateek");
addr.setCity("Berhampur");
addr.setPinCode("760001");
addr.setState("Odisha");
addr.setStreet("RKN");
user.getListOfAddresses().add(addr);
Address addrOff = new Address();
addrOff.setCity("Bangalore");
addrOff.setPinCode("560037");
addrOff.setState("MTH");
addrOff.setStreet("YH");
user.getListOfAddresses().add(addrOff);
SessionFactory sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();
Session session = sessionFactory.openSession();
session.beginTransaction();
session.save(user);
session.getTransaction().commit();
}
}
Now when I run the class HibernateTest I find this exception coming up. I have no clue why.
Exception in thread "main" org.hibernate.MappingException: Could not determine type for: java.util.Set, for columns:
#ElementCollection is a part of JPA 2.0, which is supported by Hibernate since version 3.5.
If you version of Hibernate is older, you either need to upgrade it, or use similar Hibernate-specific annotation (#CollectionOfElements) instead.
Instead of having #javax.persistence.ElementCollection annotation try using #org.hibernate.annotations.CollectionOfElements.
I currently am trying to persist a collection using #OneToMany(cascade=CascadeType.ALL) for a simple list of objects. The table for Parent_Child gets created in MySQL but the keys for each object are not updated upon using SaveOrUpdate. Any idea what the issue is? (My parent key is defined and the children are generated). I add the children to the parent object's collection before persisting with saveOrUpdate. I'm using MySQL with hibernate 3 and my auto property is set to create-drop.
The test class:
public class Tester {
public static void main(String[] args) {
VideoChannel testChannel = new VideoChannel("Test Channel");
VideoChannelMap v = new VideoChannelMap(testChannel, "Test Map");
VideoSource sc2Vid = new VideoSource("starcraft-ii-ghost-of-the-past.mp4", "EinghersStreamingBucket");
testChannel.add(sc2Vid);
Session s = HibernateSessionFactory.getSession();
s.beginTransaction();
s.saveOrUpdate(v);
s.close();
}
}
The entities:
#Entity
public class VideoChannelMap {
#Id
String name;
#OneToMany(cascade=CascadeType.ALL)
List<VideoChannel> channelMap;
public VideoChannelMap(VideoChannel initialVid, String name)
{
this.name = name;
channelMap = new ArrayList<VideoChannel>();
channelMap.add(initialVid);
initialVid.setParent(this);
}
}
#Entity
public class VideoChannel {
#Id #GeneratedValue
Long id;
...
}
You have to actually commit your transaction. The behavior when you close a session with a transaction still open isn't very well defined and will likely depend on how your database is set up underneath.
Transaction t = s.beginTransaction();
s.saveOrUpdate(v);
t.commit();
s.close();
Obviously you should also have some try-catch-finally action going on in there for "real" code ;)