Spring Data : Java configuration for MongoDB without XML - java

I tried the Spring Guide Accessing Data with MongoDB. What I can't figure out is how do I configure my code to not use the default server address and not use the default database. I have seen many ways to do it with XML but I am trying to stay with fully XML-less configurations.
Does anyone have an example that sets the server and database without XML and can be easily integrated into the sample they show in the Spring Guide?
Note: I did find how to set the collection (search for the phrase "Which collection will my documents be saved into " on this page.
Thank you!
p.s. same story with the Spring Guide for JPA -- how do you configure the db properties -- but that is another post :)

It would be something like this for a basic configuration :
#Configuration
#EnableMongoRepositories
public class MongoConfiguration extends AbstractMongoConfiguration {
#Override
protected String getDatabaseName() {
return "dataBaseName";
}
#Override
public Mongo mongo() throws Exception {
return new MongoClient("127.0.0.1", 27017);
}
#Override
protected String getMappingBasePackage() {
return "foo.bar.domain";
}
}
Example for a document :
#Document
public class Person {
#Id
private String id;
private String name;
public Person(String name) {
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Example for a repository :
#Repository
public class PersonRepository {
#Autowired
MongoTemplate mongoTemplate;
public long countAllPersons() {
return mongoTemplate.count(null, Person.class);
}
}

Related

Cassandra tables are not auto generated in Spring Boot app

I am trying to create a Spring Boot CRUD application using Cassandra. I created a docker image and I already configured Cassandra, in CassandraConfiguration class but still is not creating my tables.
My CassandraConfiguration.java code:
#Configuration
#EnableCassandraRepositories
public class CassandraConfiguration extends AbstractCassandraConfiguration {
#Value("${env.values.cassandra.keyspace.name}")
private String keyspaceName;
.......................................
#Override
protected String getKeyspaceName() {
return keyspaceName;
}
#Override
protected int getPort() {
return contactPort;
}
#Override
protected String getContactPoints() {
return contactPoint;
}
#Override
public SchemaAction getSchemaAction() {
return SchemaAction.CREATE_IF_NOT_EXISTS;
}
#Override
protected List<CreateKeyspaceSpecification> getKeyspaceCreations() {
return List.of(
CreateKeyspaceSpecification.createKeyspace(keyspaceName)
.ifNotExists()
.withSimpleReplication(3));
}
#Bean
#Override
public CqlSessionFactoryBean cassandraSession() {
CqlSessionFactoryBean cassandraSession =
super.cassandraSession(); // super session should be called only once
cassandraSession.setUsername(username);
cassandraSession.setPassword(password);
return cassandraSession;
}
}
My entity:
#Table
#AllArgsConstructor
#NoArgsConstructor
#Builder
#EqualsAndHashCode(of = {"id"})
#Getter
#Setter
public class Account {
#PrimaryKey private String id = UUID.randomUUID().toString();
private String username;
private String email;
private String name;
private String password;
}
My pom.xml file:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-cassandra</artifactId>
</dependency>
After I've done quick check of the code and configuration you posted, nothing was obvious to me as being incorrect.
My suggestion is to review the application logs looking specifically for errors and warnings from the Cassandra Java driver. Chances are the Cassandra cluster is unreachable from your application usually because of some networking issue.
You will need to verify that there is network connectivity between your application and the contact points + CQL port you've configured. Cheers!

Am I missing something if I use my entity class without #Id in Spring Data JDBC?

I am new to spring.
I just tried successfully using an entity class without #Id in Spring Data JDBC
Custom query was added in my repository for retrieving data from 2 mysql tables and returning an entity having the joined table data.
If I plan to use only custom queries, am I missing anything here?
Here's my entity class without #Id or #Entity:
public class Item
{
private long id;
private String code;
private String itemName;
private String groupName;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getItemName() {
return itemName;
}
public void setItemName(String itemName) {
this.itemName = itemName;
}
public String getGroupName() {
return groupName;
}
public void setGroupName(String groupName) {
this.groupName = groupName;
}
}
Repository layer:
#Repository
public interface ItemRepository extends PagingAndSortingRepository<Item, Long>
{
#Query("SELECT a.id, a.code, a.name AS item_name,
b.name as group_name from item a, item_group b
WHERE a.group_id = b.id AND a.id=:id")
Item findItemById(#Param("id") Long id);
}
Service layer:
#Service
public class ItemServiceImpl implements ItemService
{
private final ItemRepository itemRepository;
public ItemServiceImpl(ItemRepository itemRepository)
{
this.itemRepository = itemRepository;
}
#Override
#Transactional(readOnly=true)
public Item findItemById(Long id)
{
return itemRepository.findItemById(id);
}
}
My updated main Configuration class in response to answer of Jens:
#SpringBootApplication
#EnableJdbcRepositories
public class SpringDataJdbcApplication extends AbstractJdbcConfiguration
{
public static void main(String[] args)
{
SpringApplication.run(SpringDataJdbcApplication.class, args);
}
#Bean
#ConfigurationProperties(prefix="spring.datasource")
public DataSource dataSource()
{
DataSourceBuilder dataSourceBuilder = DataSourceBuilder.create();
return dataSourceBuilder.build();
}
#Bean
NamedParameterJdbcOperations namedParameterJdbcOperations(DataSource dataSource)
{
return new NamedParameterJdbcTemplate(dataSource);
}
#Bean
PlatformTransactionManager transactionManager()
{
return new DataSourceTransactionManager(dataSource());
}
}
If you don't get any exceptions you should be fine. There shouldn't be anything in Spring Data JDBC that silently breaks when the id is not specified.
The problem is though: I don't consider it a feature that this works, but just accidental behaviour. This means it might break with any version, although replacing these methods with custom implementations based on a NamedParameterJdbcTemplate shouldn't be to hard, so the risk is limited.
The question though is: Why don't you add the #Id annotation, after all your entity does have an id. And the whole idea of a repository conceptually requires an id.
If it's working and you really don't want to use the annotations, you can do it. But I think that it's unnecessary complication. You can expect errors that would not be there if you had used the annotations and code will be harder to debug. If you are new in Spring I recommend to use annotations. But after all it depend on you how will you design your applications. For sure advantage of approach without annotations is higher control about database.

Not able to see table created through spring boot java

I am trying to see my table created through java in H2 console, but i cannot see any table created in H2 console. I am using spring boot, and i am not using spring security, just i have created a simple dummy code to try H2 database for understanding. I have tried many solutions provided on questions asked on the same topic on stack-overflow but non of them works for me.
My Config property file is:
spring.h2.console.enabled=true
spring.datasource.platform=h2
spring.datasource.url=jdbc:h2:file:D:/temp/test
Entity class code are as follows:
#Entity
public class Alien {
#Id
private int aId;
private String aName;
public int getaId() {
return aId;
}
public void setaId(int aId) {
this.aId = aId;
}
public String getaName() {
return aName;
}
public void setaName(String aName) {
this.aName = aName;
}
}
When you log in to your H2 console in the browser you have to specify the JDBC URL to your database as you don't use the default in-memory one.
Your JDBC URL is jdbc:h2:file:D:/temp/test. Once you specify this URL in the H2 console login screen, put in the correct username and password, you should be able to see your file-based local database.
Use #Table for creatting a table from entity class
#Entity
#Table(name="alien")
public class Alien {
#Id
private int aId;
private String aName;
public int getaId() {
return aId;
}
public void setaId(int aId) {
this.aId = aId;
}
public String getaName() {
return aName;
}
public void setaName(String aName) {
this.aName = aName;
}
}

DuplicateKeyException: error code 11000 and error message 'E11000'

i want to update/replace document using id field only, i am using mongoTemplate.save(p, collection) method but i am getting DuplicateKeyException: error code 11000 and error message 'E11000'
public class MongoDAO {
#Autowired
#Qualifier("mongoTemplate")
private MongoTemplate mongoTemplate;
private static final String PERSON_COLLECTION = "person";
public MongoTemplate getMongoTemplate() {
return mongoTemplate;
}
public void update(Object p) {
this.mongoTemplate.save(p, PERSON_COLLECTION);
}
}
This is my person DAO
public class PersonDAO{
#Autowired
MongoDAO mongoDAO;
public void updatePerson(){
//read
Person p1 = mongoDAO.readById("1234");
//update
p1.setName("David");
mongoDAO.update(p1);
}
}
Person.java class
package com.mongo.andy;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Field;
public class Person {
#Id
private String id;
#Field
private String name;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
I simply want to get the object from mongodb change the values and update the document based on _id
Using mongooperation.save() or mongotemplate.save() i am getting below error
com.mongodb.DuplicateKeyException: Write failed with error code 11000 and error message 'E11000 duplicate key error collection: Person.person index: _id_ dup key: { : "5996f1d43b6af5c797a1cf4g" }'
at com.mongodb.operation.BaseWriteOperation.convertBulkWriteException(BaseWriteOperation.java:236)
at com.mongodb.operation.BaseWriteOperation.access$300(BaseWriteOperation.java:60)
at com.mongodb.operation.BaseWriteOperation$1.call(BaseWriteOperation.java:146)
at com.mongodb.operation.BaseWriteOperation$1.call(BaseWriteOperation.java:133)
at com.mongodb.operation.OperationHelper.withConnectionSource(OperationHelper.java:230)
at com.mongodb.operation.OperationHelper.withConnection(OperationHelper.java:221)
at com.mongodb.operation.BaseWriteOperation.execute(BaseWriteOperation.java:133)
at com.mongodb.operation.BaseWriteOperation.execute(BaseWriteOperation.java:60)
at com.mongodb.Mongo.execute(Mongo.java:781)
at com.mongodb.Mongo$2.execute(Mongo.java:764)
at com.mongodb.DBCollection.executeWriteOperation(DBCollection.java:333)
at com.mongodb.DBCollection.insert(DBCollection.java:328)
at com.mongodb.DBCollection.insert(DBCollection.java:319)
at com.mongodb.DBCollection.insert(DBCollection.java:289)
at com.mongodb.DBCollection.insert(DBCollection.java:255)
at com.mongodb.DBCollection.insert(DBCollection.java:192)
at org.springframework.data.mongodb.core.MongoTemplate$9.doInCollection(MongoTemplate.java:1051)
at org.springframework.data.mongodb.core.MongoTemplate.execute(MongoTemplate.java:479)
at org.springframework.data.mongodb.core.MongoTemplate.insertDBObject(MongoTemplate.java:1046)
at org.springframework.data.mongodb.core.MongoTemplate.doInsert(MongoTemplate.java:855)
at org.springframework.data.mongodb.core.MongoTemplate.doSaveVersioned(MongoTemplate.java:1001)
at org.springframework.data.mongodb.core.MongoTemplate.save(MongoTemplate.java:985)
at com.mcmcg.dia.account.metadata.dao.MongoDAO.update(MongoDAO.java:105)
at com.mcmcg.dia.account.metadata.service.AccountOALDService.mongotestapi(AccountOALDService.java:265)
at com.mcmcg.dia.account.metadata.service.AccountOALDService$$FastClassBySpringCGLIB$$7f85f843.invoke(<generated>)
Please provide the solution and suggest if there is any other way to update/replace documents in mongodb using spring-data on the basis of id field only. I have large custom object and not interesting writing any queries for update.
I was able to do so in couchbase db using upsert(), finding similar way in mongodb.
Instead of this.mongoTemplate.save(p, PERSON_COLLECTION); try with:
public void update(Object p) {
BasicDBObject dbObject = new BasicDBObject();
mongoTemplate.getConverter().write(p, dbObject);
mongoTemplate.upsert(new Query(Criteria.where("_id").is(((Person) p).getId())),
Update.fromDBObject(dbObject, "_id"), PERSON_COLLECTION);
}
The solution is similar to how the upsert method it is implemented in MongoTemplate.

How to enable auditing for MongoDB via Annotations in Spring

I wanted to enable some auditing features, such as #CreatedDate. I am not using Spring xml configuration file, so I cannot add mongo:auditing to Spring configuration. I was wondering if there was an alternative way of enable auditing. The following code is the model for user. But whenever I create a user, the date is not stored in the document, so the auditing it's not working. Could someone give me some help?
#Document(collection = "user")
public class User {
#Id
private String id;
#Indexed(unique = true)
private String email;
private String name;
#CreatedDate
private Date date;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
Because you are not using configuration via XML, I believe you are using annotations. You own a class like this:
public class MongoConfig extends AbstractMongoConfiguration {...}
Thus, in addition to the annotations you should already have, add: #EnableMongoAuditing
Your configuration class will look like this now:
#Configuration
#EnableMongoRepositories(basePackages="...")
#EnableMongoAuditing
public class MongoConfig extends AbstractMongoConfiguration {...}
I hope this helps!
That's all you need. No subclasses or other stuff.
#Configuration
#EnableMongoAuditing
public class AnyConfig {}
You should write a configuration class in which you can connect to MongoDB database using mongoClient by passing db url. and add the anootaion of #EnableMongoAuditing on top of that class.

Categories

Resources