I have a Sring hibernate Model as follows
#Entity
#Table(name = "client")
public class Category {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Column(name = "id")
private long id;
private String type;
...
...
...
I have some 50 columns. Now while inseting a new row into this table, how can i give the column name dynamically,
Client client = new Client();
String columnName = "type";
How do I update client model with the column name given in string columnName?
If you want to set the values for columns dynamically, you can use Java reflection concept.
Have a look at the Java reflection concept, following links may be helpful
http://tutorials.jenkov.com/java-reflection/fields.html
http://www.avajava.com/tutorials/lessons/how-do-i-get-and-set-a-field-using-reflection.html
For updating the table, we need to get the the field from the category Object and set the new value for that and finally invoke the save() method.
But if you want to set the field values dynamically, then you need to find the the attributes present inside the Category object using Java reflection methods. Use methods provided by Field object in java and use them. Then after getting the filed invoke the set method of the same and update the value.
Category.class.getDeclaredFields().
Related
I am using SpringBoot and Hibernate in Java, and SQL to manage my database. There are two tables and corresponding entities in the database called Order and Package. One order can have many packages. And one package can be only in one order. So it's OneToMany (Order->Package).
So in Order class there is a field called List pckList.
In Package class there is a field called Order order.
Now, I receive a list newPackageList of packages from the user. I need to create a brand new order and then add all the given packages into this newly created order.
I tried doing something like this:
Order order = new Order;
orderRepo.save(order);
Long lastId = orderRepo.lastAddedId; // id of the newly added order it's auto generated. Let's assume for now I can get it
order.setId(lastId);
for (Package pck : newPackageList){
pck.setOrder(order);
packageRepo.save(pck);
}
packageRepo.setPackageListForOrder(lastId, newPackageList); // set the pckList property of the newly created order
First of all you should review you entities design.
I'm pretty sure you don't need order inside your each package as entity.
Yes,may be you need orderId as a foreign key, but not order.
In my practice that was a reason for cyclic SQL selects --->
you select order -- > order select packages --> each package select order again and so on. For resolve this behavior Hibernate has some hacks but just don't)
So I suggest you:
#Entity
#Table(name="orders")
public class Order {
#Id
private int id;
private String name;
#OneToMany(cascade = CascadeType.PERSIST) // CascadeType.PERSIST is needed so that when saving an entity, its collection is saved (or updated)
#JoinColumn(name="order_id")
private List<Package> packages = new ArrayList<>();
// getters setters
}
#Entity
#Table(name="packages")
public class Package {
#Id
private int id;
private String packageName;
private int orderId; // order foreign key instead of entity
// getters setters
}
To save, you need to:
Order order = new Order;
order.setPackages(newPackageList)
orderRepo.save(order); // method from JPA CrudRepoposiry
orderRepo.save(order) will return the persisted object back to you. You should reassign the order variable to point to the returned instance:
Order order = new Order();
order = orderRepo.save(order);
// no need to remember the id or set it
for (Package pck : newPackageList){
pck.setOrder(order);
packageRepo.save(pck);
}
packageRepo.setPackageListForOrder(lastId, newPackageList); // set the pckList property of the newly created order
I'm creating an entity object that I will use to query a database with. However, I'm not sure how to build it since all of the columns are the key for the table. Typically I'd create an Entity object with the parameters that aren't the key and make a nested object within that one as the key. That entity object key would hold the values needed to build the key. But, in this case, all 5 values of the table are used for the key.
This is what I have currently, but I know that it's wrong.
Would I just have to make an #EmbeddedId key object within this one and push all of the values to that while practically leaving this base entity object empty? Or is there a better way to do this?
#Entity
#Table(name = "<insert>", schema="<insert>")
public class Market {
#Id
#Column(name="MKT_ID")
private String marketId;
#Column(name="DLR_CD")
private String dealerCd;
#Column(name="SER_NO_PFX")
private String serialNoPrefix;
#Column(name="SER_NO_BDY")
private String serialNoBody;
#Column(name="USER_ID")
private String userId;
}
I am trying to map a single java class to two identical views depends on the value of a field in this class:
here is my java class:
#Entity
#Immutable
#Table(name = "VIEW_ACCOUNT_PERMISSION")
public class AccountPermission implements Serializable {
#Id
#Column(name = "PERMISSION_ID")
private String id;
#Column(name = "ACCOUNT_ID")
private Long accountId;
#Column(name = "OBJECT_TYPE_ID")
#Type(type = "refObjectType")
private RefObjectType objectType;
// getters and setters
}
right now it mapped to just one view ("VIEW_ACCOUNT_PERMISSION"). Not to mention the OBJECT_TYPE_ID field can be 1,2 or 3.
Now I want to create another view the same as the "VIEW_ACCOUNT_PERMISSION" lets say "VIEW_ACCOUNT_PERMISSION2" which will have the records with OBJECT_TYPE_ID equals to 3 (1 and 2 will stay in the old view).
I can create another java model and map it to the new view but I don't like that. Is there any way to use single java model and then maps it (discriminate probably) to two views based on the value of objectType ?
You can search on basis of entity names. One Hibernate pojo class can denote to multiple entity names with different tables.
I do have a simple entity named "Address" that has a couple of properties and relations defined by itself and some inherited from some superclass.
public class Base {
private UUID id;
private Date createdAt;
#NotNull
private User createdBy; // User is a related Entity that cannot be null
private DataImport dataImport; // DataImport is another related entity that can be null
//getter & setter
}
public class Address extends Base {
private String street;
#NotNull
private Country country; // related entity that can't be null
//getter & setter
}
What I'm trying to achieve is with one query using the Criteria API, I want to get a list of Address objects containing all simple attributes like street and createdAt. At the same time I want only the IDs of the related entities if present: createdBy.id, dataImport.id and country.id.
I'm almost there using the following Criteria query:
entityManager.getDelegate().createCriteria(Address.class).add(criteriaExample)
.excludeZeroes()
.createAlias("createdBy", "subcreatedBy")
.createAlias("country", "subcountry")
.setProjection(Projections.projectionList().add(Projections.property("id").as("id"))
.add(Projections.property("createdAt").as("createdAt"))
.add(Projections.property("street").as("street")).
.add(Projections.property("subcreatedBy.id").as("createdBy.id"))
.add(Projections.property("subcountry.id").as("country.id")))
.setResultTransformer(new AliasToBeanNestedResultTransformer(Address.class));
List<Address> result = criteria.list();
This works just perfect!
Problem occurs when I only add the "alias" for the dataImport relation.
...createAlias("dataImport", "subdataImport")...
Even without adding the Projection for dataImport.id to the query, it returns an empty list, meaning list.size() = 0, as soon as I add this alias.
My current guess is, that I can't put an alias on a nullable property. Does anybody have an idea what the solution might be? So, when the related entity is not null, I want to get it's ID. And I want it to be simply null, when the relation is not set.
Thanks in advance.
Stupid me should have read the documentation and set the CriteriaSpecification.LEFT_JOIN.
...createAlias("dataImport", "subdataImport", CriteriaSpecification.LEFT_JOIN)...
#Entity
public class Language {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column(length = 2)
private String code; //EN, DE, US
public Language(String code) {
this.code = code;
}
}
#Entity
public class ProductText {
#OneToOne(Cascade.ALL)
private Language lang;
}
ProductText text = new ProductText();
text.setLang(new Language("en")); //what if "en" exists?
dao.save(text);
Now, when I persist the ProductText, everytime a new Language object would be generated.
Can I prevent this, and in case a language table entry with code = 'en' exists this existing entity should be linked instead.
My initial goal is to not having to repeat the countryCodeString "EN" multiple times in my product-text table, but just reference the id. But does this really make sense? Should I rather just use the plain String without an extra table? (I later want to query a list of productTexts where lang = 'de').
Is the only change executing a select like dao.findByLang("en") before?
Or is there also some hibernate feature that would support this without explicit executing a query myself?
Do you process the value "en" further or do you display it directly? If only used for displaying purposes, I would just store the string, but if you want to reduce redundancy by using foreign key IDs you have to create an Entity containing the language string en which can be persisted via entity manager and which you have to obtain out of the entity manager before persisting to reuse it.
If there is only three different possible values for the language, you can also use an enum like thisĀ :
public enum Language {
EN("EN"),
DE("DE"),
US("US");
private String code; //EN, DE, US
public Language(String code) {
this.code = code;
}
// Getter...
}
#Entity
public class ProductText {
#Enumerated(EnumType.STRING)
// Or #Enumerated(EnumType.ORDINAL)
private Language lang;
}
EnumType.STRING will store the enum in the database as a String, while EnumType.ORDINAL will store it as an int. Int is maybe a little more efficient, but the mapping could change if you insert a new value in your enum. String is more flexible since it will use the names of your enum members.
In both case, you don't have to manage a separate entity and hibernate will not create an additional table, and it's more type-safe than using a plain string.
If the only value in Language is a 2 or 3 letter string, why not just have the string as a member? This will be quicker and more efficient.